migrated some primitives from Processor to System.
Fixed a bug in manipulating moo->sem_io_wait_count. Experimenting to add a shortcut exception handling syntax
This commit is contained in:
		| @ -57,7 +57,7 @@ TODO: can i convert 'thisProcess primError' to a relevant exception? | ||||
|  | ||||
| 		self.signalContext := thisContext. | ||||
| 		exctx := (thisContext sender) findExceptionContext. | ||||
| 		 | ||||
|  | ||||
| 		##[exctx notNil] whileTrue: [ | ||||
| 		while (exctx notNil) | ||||
| 		{ | ||||
| @ -69,7 +69,7 @@ TODO: can i convert 'thisProcess primError' to a relevant exception? | ||||
| 				exctx basicAt: actpos put: false. | ||||
| 				[ retval := exblk value: self ] ensure: [ exctx basicAt: actpos put: true ]. | ||||
| 				thisContext unwindTo: (exctx sender) return: nil. | ||||
| 				Processor return: retval to: (exctx sender). | ||||
| 				System return: retval to: (exctx sender). | ||||
| 			}. | ||||
| 			exctx := (exctx sender) findExceptionContext. | ||||
| 		}. | ||||
| @ -113,7 +113,7 @@ System logNl: '== END OF BACKTRACE =='. | ||||
|  | ||||
| 	method return: value | ||||
| 	{ | ||||
| 		if (self.handlerContext notNil) { Processor return: value to: self.handlerContext } | ||||
| 		if (self.handlerContext notNil) { System return: value to: self.handlerContext } | ||||
| 	} | ||||
|  | ||||
| 	method retry | ||||
| @ -122,7 +122,7 @@ System logNl: '== END OF BACKTRACE =='. | ||||
| 		if (self.handlerContext notNil)  | ||||
| 		{ | ||||
| 			self.handlerContext pc: 0. | ||||
| 			Processor return: self to: self.handlerContext. | ||||
| 			System return: self to: self.handlerContext. | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @ -136,7 +136,7 @@ System logNl: '== END OF BACKTRACE =='. | ||||
| 			ctx := self.signalContext sender. | ||||
| 			self.signalContext := nil. | ||||
| 			self.handlerContext := nil. | ||||
| 			Processor return: value to: ctx. | ||||
| 			System return: value to: ctx. | ||||
| 		}. | ||||
| 	} | ||||
|  | ||||
| @ -212,31 +212,45 @@ extend Context | ||||
| } | ||||
|  | ||||
| ##============================================================================ | ||||
| pooldic MethodContext.Preamble | ||||
| { | ||||
| 	## this must follow MOO_METHOD_PREAMBLE_EXCEPTION in moo.h | ||||
| 	EXCEPTION := 13. | ||||
|  | ||||
| 	## this must follow MOO_METHOD_PREAMBLE_ENSURE in moo.h | ||||
| 	ENSURE := 14. | ||||
| } | ||||
|  | ||||
| pooldic MethodContext.Index | ||||
| { | ||||
| 	## [ value-block ] ensure: [ ensure-block ] | ||||
| 	## assuming ensure block is a parameter the ensure: method to a  | ||||
| 	## block context, the first parameter is placed after the fixed | ||||
| 	## instance variables of the method context. As MethodContex has | ||||
| 	## instance variables, the ensure block must be at the 9th position | ||||
| 	## which translates to index 8  | ||||
| 	ENSURE := 8. | ||||
|  | ||||
|  | ||||
| 	## [ ... ] on: Exception: do: [:ex | ... ] | ||||
| 	FIRST_ON := 8. | ||||
| } | ||||
|  | ||||
| extend MethodContext | ||||
| { | ||||
| 	method isExceptionContext | ||||
| 	{ | ||||
| 		## 12 - MOO_METHOD_PREAMBLE_EXCEPTION in VM. | ||||
| 		^self.method preambleCode == 13. | ||||
| 		^self.method preambleCode == MethodContext.Preamble.EXCEPTION. | ||||
| 	} | ||||
|  | ||||
| 	method isEnsureContext | ||||
| 	{ | ||||
| 		## 13 - MOO_METHOD_PREAMBLE_ENSURE in VM. | ||||
| 		^self.method preambleCode == 14 | ||||
| 		^self.method preambleCode == MethodContext.Preamble.ENSURE. | ||||
| 	} | ||||
|  | ||||
| 	method ensureBlock | ||||
| 	{ | ||||
| ## TODO: change 8 to a constant when moo is enhanced to support constant definition | ||||
|  | ||||
| 		(* [ value-block ] ensure: [ ensure-block ] | ||||
| 		 * assuming ensure block is a parameter the ensure: method to a  | ||||
| 		 * block context, the first parameter is placed after the fixed | ||||
| 		 * instance variables of the method context. As MethodContex has | ||||
| 		 * 8 instance variables, the ensure block must be at the 9th position | ||||
| 		 * which translates to index 8 *) | ||||
| 		^if (self.method preambleCode == 14) { self basicAt: 8 } else { nil } | ||||
| 		^if (self.method preambleCode == MethodContext.Preamble.ENSURE) { self basicAt: MethodContext.Index.ENSURE } else { nil } | ||||
| 	} | ||||
|  | ||||
|  | ||||
| @ -250,10 +264,7 @@ extend MethodContext | ||||
| 		 *   basicAt: 8 must be the on: argument. | ||||
| 		 *   basicAt: 9 must be the do: argument  *) | ||||
|  | ||||
| ## TODO: change 8 to a constant when moo is enhanced to support constant definition | ||||
| ##       or calcuate the minimum size using the class information. | ||||
|  | ||||
| 		| size exc | | ||||
| 		| size exc i | | ||||
| 		 | ||||
| 		if (self isExceptionContext)  | ||||
| 		{ | ||||
| @ -262,10 +273,20 @@ extend MethodContext | ||||
| 			 *       those must be skipped from scanning. *) | ||||
|  | ||||
| 			size := self basicSize. | ||||
| 			8 priorTo: size by: 2 do: [ :i |  | ||||
| 			##8 priorTo: size by: 2 do: [ :i |  | ||||
| 			##	exc := self basicAt: i. | ||||
| 			##	if ((exception_class == exc) or: [exception_class inheritsFrom: exc]) { ^self basicAt: (i + 1) }. | ||||
| 			##] | ||||
| 			i := MethodContext.Index.FIRST_ON. | ||||
| 			while (i < size) | ||||
| 			{ | ||||
| 				exc := self basicAt: i. | ||||
| 				if ((exception_class == exc) or: [exception_class inheritsFrom: exc]) { ^self basicAt: (i + 1) }. | ||||
| 			] | ||||
| 				if ((exception_class == exc) or: [exception_class inheritsFrom: exc])  | ||||
| 				{  | ||||
| 					^self basicAt: (i + 1). | ||||
| 				}. | ||||
| 				i := i + 2. | ||||
| 			}. | ||||
| 		}. | ||||
| 		^nil. | ||||
| 	} | ||||
| @ -319,7 +340,7 @@ extend MethodContext | ||||
| 		 * [ [Exception signal: 'xxx'] ensure: [20] ] on: Exception do: [:ex | ...] | ||||
| 		 * ---------------------------------------------------------------- *) | ||||
| 		thisContext unwindTo: self.sender return: nil. | ||||
| 		Processor return: retval to: self.sender. | ||||
| 		System return: retval to: self.sender. | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| @ -239,6 +239,54 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit | ||||
| 		^x | ||||
| 	} | ||||
|  | ||||
| 	method _waitWithTimeout: seconds | ||||
| 	{ | ||||
| 		| s r | | ||||
|  | ||||
| 		## create an internal semaphore for timeout notification. | ||||
| 		s := Semaphore _new. | ||||
| 		if (s isError) { ^s }. | ||||
|  | ||||
| 		## grant the partial membership to the internal semaphore. | ||||
| 		## it's partial because it's not added to self.semarr. | ||||
| 		##s _group: self.  | ||||
| 		if ((r := (self addSemaphore: s)) isError) { ^r }. | ||||
|  | ||||
| 		## arrange the processor to notify upon timeout. | ||||
| 		if ((r := (System _signal: s after: seconds)) isError) { ^r }. | ||||
|  | ||||
| 		if ((r := self _wait) isError)  | ||||
| 		{ | ||||
| 			System _unsignal: s. | ||||
| 			^r. | ||||
| 		}. | ||||
|  | ||||
| 		## if the internal semaphore has been signaled,  | ||||
| 		## arrange to return nil to indicate timeout. | ||||
| 		if (r == s) { r := nil } | ||||
| 		elsif (r signalAction notNil) { r signalAction value: r }. | ||||
|  | ||||
| 		## nullify the membership | ||||
| 		self _removeSemaphore: s. | ||||
|  | ||||
| 		## cancel the notification arrangement in case it didn't time out. | ||||
| 		System _unsignal: s. | ||||
|  | ||||
| 		^r. | ||||
| 	} | ||||
|  | ||||
| 	method waitWithTimeout: seconds | ||||
| 	{ | ||||
| 		| r | | ||||
| 		r := self _waitWithTimeout: seconds. | ||||
| 		if (r isError)   | ||||
| 		{ | ||||
| 			Exception signal: 'Error has occurred...' error: r. | ||||
| 		}. | ||||
| 		^r | ||||
| 	} | ||||
|  | ||||
| (* | ||||
| 	method waitWithTimeout: seconds | ||||
| 	{ | ||||
| 		| s r | | ||||
| @ -254,8 +302,13 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit | ||||
| 		## arrange the processor to notify upon timeout. | ||||
| 		System signal: s after: seconds. | ||||
|  | ||||
| 		## wait on the semaphore group. | ||||
| 		r := self wait. | ||||
| 		[ | ||||
| 			## wait on the semaphore group. | ||||
| 			r := self wait. | ||||
| 		] on: Exception do: [:ex | | ||||
| 			System _unsignal: s. | ||||
| 			ex throw | ||||
| 		]. | ||||
|  | ||||
| 		## if the internal semaphore has been signaled,  | ||||
| 		## arrange to return nil to indicate timeout. | ||||
| @ -270,6 +323,7 @@ method(#class,#abstract) xxx. => method(#class) xxx { self subclassResponsibilit | ||||
|  | ||||
| 		^r. | ||||
| 	}  | ||||
| *) | ||||
| } | ||||
|  | ||||
| class SemaphoreHeap(Object) | ||||
| @ -471,10 +525,4 @@ class(#final,#limited) ProcessScheduler(Object) | ||||
| 			]. | ||||
| 		*) | ||||
| 	} | ||||
|  | ||||
| 	method return: object to: context | ||||
| 	{ | ||||
| 		<primitive: #_processor_return_to> | ||||
| 		self primitiveFailed. | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -97,6 +97,7 @@ class System(Apex) | ||||
|  | ||||
| 	method(#class,#primitive) _popCollectable. | ||||
| 	method(#class,#primitive) collectGarbage. | ||||
| 	method(#class,#primitive) return: object to: context. | ||||
|  | ||||
| 	## ======================================================================================= | ||||
|  | ||||
|  | ||||
		Reference in New Issue
	
	Block a user