enhanced unwind handling upon process termination
This commit is contained in:
		@ -170,10 +170,20 @@
 | 
			
		||||
		^self atLevel: Log.INFO log: message.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#method log: message and: message2
 | 
			
		||||
	{
 | 
			
		||||
		^self atLevel: Log.INFO log: message and: message2.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#method logNl: message
 | 
			
		||||
	{
 | 
			
		||||
		^self atLevel: Log.INFO logNl: message.
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#method logNl: message and: message2
 | 
			
		||||
	{
 | 
			
		||||
		^self atLevel: Log.INFO logNl: message and: message2.
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#class Namespace(Set)
 | 
			
		||||
 | 
			
		||||
@ -150,6 +150,7 @@
 | 
			
		||||
		## -------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
		| ctx stop |
 | 
			
		||||
 | 
			
		||||
		ctx := self.
 | 
			
		||||
		stop := false.
 | 
			
		||||
		[stop] whileFalse: [
 | 
			
		||||
 | 
			
		||||
@ -43,9 +43,38 @@
 | 
			
		||||
		self primitiveFailed
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#method _suspend
 | 
			
		||||
	{
 | 
			
		||||
		<primitive: #_process_suspend>
 | 
			
		||||
		self primitiveFailed
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#method terminate
 | 
			
		||||
	{
 | 
			
		||||
##search from the top contextof the process down to intial_contextand find ensure blocks and execute them.
 | 
			
		||||
		## if a different process calls 'terminate' on a process,
 | 
			
		||||
		## the ensureblock is not executed in the context of the
 | 
			
		||||
		## process being terminated, but in the context of terminatig process.
 | 
			
		||||
		##
 | 
			
		||||
		## 1) process termianted by another process
 | 
			
		||||
		##   p := [ 
 | 
			
		||||
		##       [  1 to: 10000 by: 1 do: [:ex | System logNl: i asString] ] ensure: [System logNl: 'ensured....'] 
 | 
			
		||||
		##   ] newProcess.
 | 
			
		||||
		##   p resume.
 | 
			
		||||
		##   p terminate.
 | 
			
		||||
		##
 | 
			
		||||
		## 2) process terminated by itself
 | 
			
		||||
		##   p := [ 
 | 
			
		||||
		##       [ Processor activeProcess terminate. ] ensure: [System logNl: 'ensured....'] 
 | 
			
		||||
		##   ] newProcess.
 | 
			
		||||
		##   p resume.
 | 
			
		||||
		##   p terminate.
 | 
			
		||||
		## ----------------------------------------------------------------------------------------------------------
 | 
			
		||||
		## the process must be frozen first. while unwinding is performed, 
 | 
			
		||||
		## the process must not be scheduled.
 | 
			
		||||
		## ----------------------------------------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
		(Processor activeProcess ~~ self) ifTrue: [ self _suspend ].
 | 
			
		||||
		self.current_context unwindTo: self.initial_context return: nil.
 | 
			
		||||
		^self _terminate
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -80,7 +80,8 @@
 | 
			
		||||
		v1 := [
 | 
			
		||||
			[    
 | 
			
		||||
				[ 
 | 
			
		||||
					1 to: 10000 by: 1 do: [:i | System logNl: i asString. Processor sleepFor: 5. ]  
 | 
			
		||||
					##1 to: 20000 by: 1 do: [:i | System logNl: i asString. "Processor sleepFor: 1." ]  
 | 
			
		||||
					Processor activeProcess terminate.
 | 
			
		||||
				] ensure: [ System logNl: '<<<PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP>>>' ].
 | 
			
		||||
 | 
			
		||||
			] ensure: [ System logNl: '<<--------------------->>' ].
 | 
			
		||||
@ -88,9 +89,10 @@
 | 
			
		||||
 | 
			
		||||
		System logNl: 'RESUMING v1'.
 | 
			
		||||
		v1 resume.
 | 
			
		||||
		Processor sleepFor: 1.
 | 
			
		||||
		v1 terminate.
 | 
			
		||||
 | 
			
		||||
		##[    
 | 
			
		||||
 		##[    
 | 
			
		||||
		##	[ Processor activeProcess terminate. ] ensure: [System logNl: '<<<PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP>>>' ].
 | 
			
		||||
		##] ensure: [ System logNl: '<<--------------------->>' ].
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -97,6 +97,7 @@
 | 
			
		||||
		(stix)->active_method = (stix_oop_method_t)(stix)->active_context->origin->method_or_nargs; \
 | 
			
		||||
		SET_ACTIVE_METHOD_CODE(stix); \
 | 
			
		||||
		LOAD_ACTIVE_IP (stix); \
 | 
			
		||||
		(stix)->processor->active->current_context = (stix)->active_context; \
 | 
			
		||||
	} while (0)
 | 
			
		||||
 | 
			
		||||
#define FETCH_BYTE_CODE(stix) ((stix)->active_code[(stix)->ip++])
 | 
			
		||||
@ -1234,14 +1235,19 @@ static int prim_log (stix_t* stix, stix_ooi_t nargs)
 | 
			
		||||
			else if (STIX_OBJ_GET_FLAGS_TYPE(msg) == STIX_OBJ_TYPE_OOP)
 | 
			
		||||
			{
 | 
			
		||||
				/* visit only 1-level down into an array-like object */
 | 
			
		||||
				stix_oop_t inner;
 | 
			
		||||
				stix_oow_t i;
 | 
			
		||||
				stix_oop_t inner, _class;
 | 
			
		||||
				stix_oow_t i, spec;
 | 
			
		||||
 | 
			
		||||
				if (STIX_CLASSOF(stix,msg) == stix->_association) goto dump_object;
 | 
			
		||||
				_class = STIX_CLASSOF(stix, msg);
 | 
			
		||||
 | 
			
		||||
				spec = STIX_OOP_TO_SMOOI(((stix_oop_class_t)_class)->spec);
 | 
			
		||||
				if (STIX_CLASS_SPEC_NAMED_INSTVAR(spec) > 0 || !STIX_CLASS_SPEC_IS_INDEXED(spec)) goto dump_object;
 | 
			
		||||
 | 
			
		||||
				for (i = 0; i < STIX_OBJ_GET_SIZE(msg); i++)
 | 
			
		||||
				{
 | 
			
		||||
					inner = ((stix_oop_oop_t)msg)->slot[i];
 | 
			
		||||
 | 
			
		||||
					if (i > 0) stix_logbfmt (stix, mask, " ");
 | 
			
		||||
					if (STIX_OOP_IS_POINTER(inner) &&
 | 
			
		||||
					    STIX_OBJ_GET_FLAGS_TYPE(inner) == STIX_OBJ_TYPE_CHAR)
 | 
			
		||||
					{
 | 
			
		||||
@ -1869,6 +1875,20 @@ static int prim_process_yield (stix_t* stix, stix_ooi_t nargs)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int prim_process_suspend (stix_t* stix, stix_ooi_t nargs)
 | 
			
		||||
{
 | 
			
		||||
	stix_oop_t rcv;
 | 
			
		||||
	STIX_ASSERT (nargs == 0);
 | 
			
		||||
 | 
			
		||||
	rcv = STIX_STACK_GET(stix, stix->sp);
 | 
			
		||||
	if (STIX_CLASSOF(stix,rcv) != stix->_process) return 0;
 | 
			
		||||
 | 
			
		||||
	suspend_process (stix, (stix_oop_process_t)rcv);
 | 
			
		||||
 | 
			
		||||
	/* keep the receiver in the stack top */
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int prim_semaphore_signal (stix_t* stix, stix_ooi_t nargs)
 | 
			
		||||
{
 | 
			
		||||
	stix_oop_t rcv;
 | 
			
		||||
@ -2724,6 +2744,7 @@ static prim_t primitives[] =
 | 
			
		||||
	{   0,  0,  prim_process_resume,                   "_process_resume"      },
 | 
			
		||||
	{   0,  0,  prim_process_terminate,                "_process_terminate"   },
 | 
			
		||||
	{   0,  0,  prim_process_yield,                    "_process_yield"       },
 | 
			
		||||
	{   0,  0,  prim_process_suspend,                  "_process_suspend"     },
 | 
			
		||||
	{   0,  0,  prim_semaphore_signal,                 "_semaphore_signal"    },
 | 
			
		||||
	{   0,  0,  prim_semaphore_wait,                   "_semaphore_wait"      },
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user