enhanced finalization handling further
This commit is contained in:
		| @ -19,7 +19,7 @@ class(#pointer,#final,#limited) Process(Object) | ||||
|  | ||||
| 	method terminate | ||||
| 	{ | ||||
| ##search from the top contextof the process down to intial_context and find ensure blocks and execute them. | ||||
| ##search from the top context of the process down to intial_context and 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. | ||||
| @ -42,8 +42,8 @@ class(#pointer,#final,#limited) Process(Object) | ||||
| 		## the process must not be scheduled. | ||||
| 		## ---------------------------------------------------------------------------------------------------------- | ||||
|  | ||||
| 		##(Processor activeProcess ~~ self) ifTrue: [ self _suspend ]. | ||||
| 		(thisProcess ~~ self) ifTrue: [ self _suspend ]. | ||||
| 		##if (Processor activeProcess ~~ self) { self _suspend }. | ||||
| 		if (thisProcess ~~ self) { self _suspend }. | ||||
| 		self.current_context unwindTo: self.initial_context return: nil. | ||||
| 		^self _terminate | ||||
| 	} | ||||
| @ -68,7 +68,7 @@ class Semaphore(Object) | ||||
| 	    fireTimeSec   :=   0, | ||||
| 	    fireTimeNsec  :=   0, | ||||
| 	    ioIndex       :=  -1, | ||||
| 	    ioData        := nil, | ||||
| 	    ioHandle      := nil, | ||||
| 	    ioMask        :=   0. | ||||
|  | ||||
| 	method(#class) forMutualExclusion | ||||
| @ -129,6 +129,11 @@ class Semaphore(Object) | ||||
| 	{ | ||||
| 		^self.fireTimeSec < (aSemaphore fireTime) | ||||
| 	} | ||||
|  | ||||
| 	method notYoungerThan: aSemaphore | ||||
| 	{ | ||||
| 		^self.fireTimeSec >= (aSemaphore fireTime) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| class SemaphoreHeap(Object) | ||||
| @ -190,36 +195,30 @@ class SemaphoreHeap(Object) | ||||
| 		self.arr at: anIndex put: aSemaphore. | ||||
| 		aSemaphore heapIndex: anIndex. | ||||
|  | ||||
| 		^(aSemaphore youngerThan: item) | ||||
| 			ifTrue: [ self siftUp: anIndex ] | ||||
| 			ifFalse: [ self siftDown: anIndex ]. | ||||
| 		^if (aSemaphore youngerThan: item) { self siftUp: anIndex } else { self siftDown: anIndex }. | ||||
| 	} | ||||
|  | ||||
| 	method deleteAt: anIndex | ||||
| 	{ | ||||
| 		| item | | ||||
| 		| item xitem | | ||||
|  | ||||
| 		item := self.arr at: anIndex. | ||||
| 		item heapIndex: -1. | ||||
|  | ||||
| 		self.size := self.size - 1. | ||||
| 		(anIndex == self.size)  | ||||
| 			ifTrue: [ | ||||
| 				"the last item" | ||||
| 				self.arr at: self.size put: nil. | ||||
| 			] | ||||
| 			ifFalse: [ | ||||
| 				| xitem | | ||||
|  | ||||
| 				xitem := self.arr at: self.size. | ||||
| 				self.arr at: anIndex put: xitem. | ||||
| 				xitem heapIndex: anIndex. | ||||
| 				self.arr at: self.size put: nil. | ||||
|  | ||||
| 				(xitem youngerThan: item)  | ||||
| 					ifTrue: [self siftUp: anIndex ] | ||||
| 					ifFalse: [self siftDown: anIndex ] | ||||
| 			] | ||||
| 		if (anIndex == self.size)  | ||||
| 		{ | ||||
| 			## the last item | ||||
| 			self.arr at: self.size put: nil. | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			xitem := self.arr at: self.size. | ||||
| 			self.arr at: anIndex put: xitem. | ||||
| 			xitem heapIndex: anIndex. | ||||
| 			self.arr at: self.size put: nil. | ||||
| 			if (xitem youngerThan: item) { self siftUp: anIndex } else { self siftDown: anIndex }. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method parentIndex: anIndex | ||||
| @ -239,34 +238,31 @@ class SemaphoreHeap(Object) | ||||
|  | ||||
| 	method siftUp: anIndex | ||||
| 	{ | ||||
| 		| pindex cindex par item stop | | ||||
| 		| pindex cindex par item | | ||||
|  | ||||
| 		(anIndex <= 0) ifTrue: [ ^anIndex ]. | ||||
| 		if (anIndex <= 0) { ^anIndex }. | ||||
|  | ||||
| 		pindex := anIndex. | ||||
| 		item := self.arr at: anIndex. | ||||
|  | ||||
| 		stop := false. | ||||
| 		[ stop ] whileFalse: [ | ||||
|  | ||||
| 		while (true) | ||||
| 		{ | ||||
| 			cindex := pindex. | ||||
|  | ||||
| 			(cindex > 0) | ||||
| 				ifTrue: [ | ||||
| 					pindex := self parentIndex: cindex. | ||||
| 					par := self.arr at: pindex. | ||||
| 			if (pindex <= 0) { break }. | ||||
|  | ||||
| 					(item youngerThan: par)  | ||||
| 						ifTrue: [ | ||||
| 							## move the parent down | ||||
| 							self.arr at: cindex put: par. | ||||
| 							par heapIndex: cindex. | ||||
| 						] | ||||
| 						ifFalse: [ stop := true ]. | ||||
| 				] | ||||
| 				ifFalse: [ stop := true ]. | ||||
| 		]. | ||||
| 			pindex := self parentIndex: cindex. | ||||
| 			par := self.arr at: pindex. | ||||
|  | ||||
| 			if (item notYoungerThan: par)  { break }. | ||||
|  | ||||
| 			## item is younger than the parent.  | ||||
| 			## move the parent down | ||||
| 			self.arr at: cindex put: par. | ||||
| 			par heapIndex: cindex. | ||||
| 		}. | ||||
|  | ||||
| 		## place the item as high as it can | ||||
| 		self.arr at: cindex put: item. | ||||
| 		item heapIndex: cindex. | ||||
|  | ||||
| @ -275,36 +271,29 @@ class SemaphoreHeap(Object) | ||||
|  | ||||
| 	method siftDown: anIndex | ||||
| 	{ | ||||
| 		| base capa cindex item | | ||||
| 		| base capa cindex item  | ||||
| 		  left right younger xitem | | ||||
|  | ||||
| 		base := self.size quo: 2. | ||||
| 		(anIndex >= base) ifTrue: [^anIndex]. | ||||
| 		if (anIndex >= base) { ^anIndex }. | ||||
|  | ||||
| 		cindex := anIndex. | ||||
| 		item := self.arr at: cindex. | ||||
|  | ||||
| 		[ cindex < base ] whileTrue: [ | ||||
| 			| left right younger xitem | | ||||
|  | ||||
| 		while (cindex < base)  | ||||
| 		{ | ||||
| 			left := self leftChildIndex: cindex. | ||||
| 			right := self rightChildIndex: cindex. | ||||
|  | ||||
| 			((right < self.size) and: [(self.arr at: right) youngerThan: (self.arr at: left)]) | ||||
| 				ifTrue: [ younger := right ] | ||||
| 				ifFalse: [ younger := left ]. | ||||
| 			younger := if ((right < self.size) and: [(self.arr at: right) youngerThan: (self.arr at: left)]) { right } else { left }. | ||||
|  | ||||
| 			xitem := self.arr at: younger. | ||||
| 			(item youngerThan: xitem)  | ||||
| 				ifTrue: [ | ||||
| 					"break the loop" | ||||
| 					base := anIndex  | ||||
| 				] | ||||
| 				ifFalse: [ | ||||
| 					self.arr at: cindex put: xitem. | ||||
| 					xitem heapIndex: cindex. | ||||
| 					cindex := younger. | ||||
| 				] | ||||
| 		]. | ||||
| 			if (item youngerThan: xitem)  { break }. | ||||
|  | ||||
| 			self.arr at: cindex put: xitem. | ||||
| 			xitem heapIndex: cindex. | ||||
| 			cindex := younger. | ||||
| 		}. | ||||
|  | ||||
| 		self.arr at: cindex put: item. | ||||
| 		item heapIndex: cindex. | ||||
| @ -315,13 +304,8 @@ class SemaphoreHeap(Object) | ||||
|  | ||||
| class(#final,#limited) ProcessScheduler(Object) | ||||
| { | ||||
| 	var tally, active, runnable_head, runnable_tail, sem_heap. | ||||
|  | ||||
| 	method new | ||||
| 	{ | ||||
| 		"instantiation is not allowed" | ||||
| 		^nil. "TODO: raise an exception" | ||||
| 	} | ||||
| 	var(#get) tally, active. | ||||
| 	var runnable_head, runnable_tail (*, sem_heap*). | ||||
|  | ||||
| 	method activeProcess | ||||
| 	{ | ||||
| @ -333,8 +317,8 @@ class(#final,#limited) ProcessScheduler(Object) | ||||
| 		<primitive: #_processor_schedule> | ||||
| 		self primitiveFailed. | ||||
|  | ||||
| 		"The primitive does something like the following in principle: | ||||
| 		(self.tally = 0) | ||||
| 		(* The primitive does something like the following in principle: | ||||
| 		(self.tally == 0) | ||||
| 			ifTrue: [ | ||||
| 				self.head := process. | ||||
| 				self.tail := process. | ||||
| @ -346,16 +330,16 @@ class(#final,#limited) ProcessScheduler(Object) | ||||
| 				self.head := process. | ||||
| 				self.tally := self.tally + 1. | ||||
| 			]. | ||||
| 		" | ||||
| 		*) | ||||
| 	} | ||||
|  | ||||
| 	" | ||||
| 	(* ------------------- | ||||
| 	method yield | ||||
| 	{ | ||||
| 		<primitive: #_processor_yield> | ||||
| 		self primitiveFailed | ||||
| 	} | ||||
| 	" | ||||
| 	----------------- *) | ||||
|  | ||||
| 	method signal: semaphore after: secs | ||||
| 	{ | ||||
|  | ||||
| @ -32,23 +32,36 @@ class System(Apex) | ||||
|  | ||||
| 	method(#class) __gc_finalizer | ||||
| 	{ | ||||
| 		| tmp | | ||||
| 		| tmp gc | | ||||
|  | ||||
| 		gc := false. | ||||
| 		while (true) | ||||
| 		{ | ||||
| ## TODO: exit from this loop when there are no other processes running. | ||||
| ## TODO: exit from this loop when there are no other processes running except this finalizer process | ||||
| 			while ((tmp := self _popCollectable) notError) | ||||
| 			{ | ||||
| 				## TODO: Do i have to protected this in an exception handler??? | ||||
| 				tmp finalize. | ||||
| 				if (tmp respondsTo: #finalize) { tmp finalize }. | ||||
| 			}. | ||||
|  | ||||
| 			System logNl: 'gc_waiting....'. | ||||
| 			Processor sleepFor: 1. ## TODO: wait on semaphore instead.. | ||||
| 			(* | ||||
| 			if (Processor tally == 1 and: [Processor active == thisProcess])  | ||||
| 			{ | ||||
| 				if (gc) { break }. | ||||
|  | ||||
| 				self collectGarbage. | ||||
| 		'GC GC GC GC' dump. | ||||
| 		Processor tally dump. | ||||
| 				gc := true. | ||||
| 			}.*) | ||||
|  | ||||
| 			##System logNl: 'gc_waiting....'. | ||||
| 			##Processor sleepFor: 1. ## TODO: wait on semaphore instead.. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	method(#class,#primitive) _popCollectable. | ||||
| 	method(#class,#primitive) collectGarbage. | ||||
| } | ||||
|  | ||||
| pooldic System.Log | ||||
|  | ||||
| @ -618,10 +618,11 @@ extend X11 | ||||
| 'CLOSING X11 EVENT LOOP' dump. | ||||
|  | ||||
| 				Processor unsignal: self.event_loop_sem. | ||||
| 		## TODO: LOOK HERE FOR RACE CONDITION | ||||
| 				self.event_loop_sem := nil. | ||||
|  | ||||
| 				self.event_loop_proc := nil. | ||||
| 				 | ||||
| 				self dispose. | ||||
|  | ||||
| 			] fork. | ||||
| 		} | ||||
| 	} | ||||
| @ -630,6 +631,7 @@ extend X11 | ||||
| 	{ | ||||
| 		if (self.event_loop_sem notNil) | ||||
| 		{ | ||||
| 		## TODO: handle race-condition with the part maked 'LOOK HERE FOR RACE CONDITION' | ||||
| 			self.event_loop_proc terminate. | ||||
| 			self.event_loop_proc := nil. | ||||
| 			self.event_loop_sem := nil. | ||||
| @ -704,14 +706,19 @@ extend X11 | ||||
|  | ||||
| class Fx(Object) | ||||
| { | ||||
| 	var(#class) X := 20. | ||||
| 	var x. | ||||
|  | ||||
| 	method initialize | ||||
| 	{ | ||||
| 		self.X := self.X + 1. | ||||
| 		self.x := self.X. | ||||
| 		self addToBeFinalized. | ||||
| 	} | ||||
|  | ||||
| 	method finalize | ||||
| 	{ | ||||
| 		System logNl: 'Greate... FX instance finalized'. | ||||
| 		System logNl: ('Greate... FX instance finalized' & self.x asString). | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -722,6 +729,7 @@ class MyObject(Object) | ||||
| 	method main1 | ||||
| 	{ | ||||
| 		| comp1 | | ||||
|  | ||||
| 		self.disp1 := X11 new. | ||||
| 		self.disp2 := X11 new. | ||||
|  | ||||
| @ -755,11 +763,9 @@ class MyObject(Object) | ||||
| 		self.disp1 enterEventLoop. ## this is not a blocking call. it spawns another process. | ||||
| 		self.disp2 enterEventLoop. | ||||
|  | ||||
|  | ||||
|  | ||||
| 		comp1 := Fx new. | ||||
| 		Fx new. | ||||
| 		Fx new. | ||||
| 		comp1 := Fx new. | ||||
| 		Fx new. | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -17,6 +17,38 @@ class MyObject(Object) | ||||
| 		^a | ||||
| 	} | ||||
|  | ||||
| 	method(#class) test_semaphore_heap | ||||
| 	{ | ||||
| 		| sempq a | | ||||
| 		sempq := SemaphoreHeap new. | ||||
|  | ||||
| 		'--------------------------' dump. | ||||
|  | ||||
| 		1 to: 200 by: 1 do: [ :i |   | ||||
| 			| sem | | ||||
| 			sem := Semaphore new.  | ||||
| 			sem fireTime: (200 - i). | ||||
| 			sempq insert: sem | ||||
| 		]. | ||||
|  | ||||
| 		'--------------------------' dump. | ||||
| 		sempq deleteAt: 40. | ||||
| 		sempq deleteAt: 50. | ||||
| 		sempq deleteAt: 100. | ||||
|  | ||||
| 	 | ||||
| 		a := -100. | ||||
| 		[sempq size > 0] whileTrue: [ | ||||
| 			| sem b | | ||||
| 			sem := sempq popTop. | ||||
| 			b := sem fireTime. | ||||
| 			if (a > b) { ^false }. | ||||
| 			a := b. | ||||
| 		]. | ||||
| 		 | ||||
| 		^true | ||||
| 	} | ||||
|  | ||||
| 	method(#class) main | ||||
| 	{ | ||||
| 		| tc limit | | ||||
| @ -24,7 +56,8 @@ class MyObject(Object) | ||||
| 		tc := %( | ||||
| 			## 0 - 4 | ||||
| 			[ self proc1 == 100 ],  | ||||
| 			[ Processor sleepFor: 2.  self proc1 == 200 ] | ||||
| 			[ Processor sleepFor: 2.  self proc1 == 200 ], | ||||
| 			[ self test_semaphore_heap == true ] | ||||
| 		). | ||||
|  | ||||
| 		limit := tc size. | ||||
| @ -33,7 +66,7 @@ class MyObject(Object) | ||||
| 			| tb | | ||||
| 			tb := tc at: idx. | ||||
| 			System log(System.Log.INFO, idx asString, (if (tb value) { ' PASS' } else { ' FAIL' }), S'\n'). | ||||
| 		] | ||||
| 		]. | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user