--- a/Exception.st Tue Oct 28 21:15:01 1997 +0100
+++ b/Exception.st Wed Oct 29 15:12:43 1997 +0100
@@ -10,6 +10,8 @@
hereby transferred.
"
+'From Smalltalk/X, Version:3.2.1 on 25-oct-1997 at 11:48:51 pm' !
+
Object subclass:#Exception
instanceVariableNames:'signal parameter errorString suspendedContext handlerContext
rejected originator resumeBlock rejectBlock'
@@ -699,7 +701,7 @@
|theContext block noHandlerSignal any msg conArg1
theSignal c ex1 activeHandlers inHandler rejected
- lastHandler h raiseReceiver r|
+ lastHandler h raiseReceiver r firstHandler|
theContext := thisContext sender sender. "the raise/raiseRequest-context"
"the signal raise context"
@@ -721,102 +723,126 @@
"/ same handler)
"/ the code below collects active handlers ...
- [c notNil] whileTrue:[
- c := c findNextContextWithSelector:#doRaise or:nil or:nil.
- c notNil ifTrue:[
-
- ex1 := c receiver.
+ "/ on the fly, look for the first #handle:do: - context,
+ "/ and remember it (as firstHandler) to avoid walking the context chain twice
+ "/ in most cases ...
- ((ex1 class == self class)
- or:[ex1 species == self species]) ifTrue:[
- c := c sender.
- (c notNil and:[c receiver == ex1]) ifTrue:[
- c := c sender.
- c notNil ifTrue:[
+ firstHandler := nil.
- "/ the common case (really ?) first
- ((raiseReceiver := c receiver) == theSignal) ifTrue:[
- (c selector startsWith:'raise') ifTrue:[
- h := ex1 handlerContext.
- h notNil ifTrue:[
- activeHandlers isNil ifTrue:[
- activeHandlers := OrderedCollection new
- ].
+ [c notNil] whileTrue:[
+ firstHandler isNil ifTrue:[
+ c := c findNextContextWithSelector:#doRaise or:#'handle:do:' or:#'handle:from:do:'.
+ ] ifFalse:[
+ c := c findNextContextWithSelector:#doRaise or:nil or:nil.
+ ].
+ c notNil ifTrue:[
+ (c selector == #doRaise) ifTrue:[
- lastHandler := h.
- activeHandlers add:lastHandler.
- inHandler := true.
- c := lastHandler.
- ]
- ]
- ] ifFalse:[
- raiseReceiver isSignal ifTrue:[
+ ex1 := c receiver.
+
+ ((ex1 class == self class)
+ or:[ex1 species == self species]) ifTrue:[
+ c := c sender.
+ (c notNil and:[c receiver == ex1]) ifTrue:[
+ c := c sender.
+ c notNil ifTrue:[
+
+ "/ the common case (really ?) first
+ ((raiseReceiver := c receiver) == theSignal) ifTrue:[
(c selector startsWith:'raise') ifTrue:[
h := ex1 handlerContext.
h notNil ifTrue:[
- r := h receiver.
- (r notNil and:[r accepts:theSignal]) ifTrue:[
+ activeHandlers isNil ifTrue:[
+ activeHandlers := OrderedCollection new
+ ].
- activeHandlers isNil ifTrue:[
- activeHandlers := OrderedCollection new
- ].
- lastHandler := h.
- activeHandlers add:lastHandler.
- inHandler := true.
- c := lastHandler.
- ]
+ lastHandler := h.
+ activeHandlers add:lastHandler.
+ inHandler := true.
+ c := lastHandler.
+ ]
+ ]
+ ] ifFalse:[
+ raiseReceiver isSignal ifTrue:[
+ (c selector startsWith:'raise') ifTrue:[
+ h := ex1 handlerContext.
+ h notNil ifTrue:[
+ r := h receiver.
+ (r notNil and:[r accepts:theSignal]) ifTrue:[
+
+ activeHandlers isNil ifTrue:[
+ activeHandlers := OrderedCollection new
+ ].
+ lastHandler := h.
+ activeHandlers add:lastHandler.
+ inHandler := true.
+ c := lastHandler.
+ ]
+ ]
]
]
- ]
+ ]
]
]
]
+ ] ifFalse:[
+ "/ must be a #handle:do context ...
+ firstHandler := c.
]
]
].
"/ now, start searching for a handler,
- "/ start search above the last active handler
+ "/ start search above the last active handler.
+ "/ Or start with the first handle:do: context, if one
+ "/ was found as a side effect of the previous handler search.
+ "/ If nil, then there is no handler and we can directly proceed
+ "/ to the unhandled code below.
lastHandler notNil ifTrue:[
theContext := lastHandler.
+ theContext := lastHandler findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
+ ] ifFalse:[
+ theContext := firstHandler
].
+ "/ remember if there was any handler
+ "/ for the better errorString (unhandled vs. rejected exception)
+
any := false.
[theContext notNil] whileTrue:[
- theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
- theContext notNil ifTrue:[
- (theContext selector == #'handle:do:'
- or:[(theContext argAt:2) == originator])
- ifTrue:[
- (activeHandlers notNil
- and:[activeHandlers includesIdentical:theContext]) ifTrue:[
- 'skip activeHandler: ' print. theContext displayString printCR.
+ (theContext selector == #'handle:do:'
+ or:[(theContext argAt:2) == originator])
+ ifTrue:[
+ (activeHandlers notNil
+ and:[activeHandlers includesIdentical:theContext]) ifTrue:[
+ 'skip activeHandler: ' print. theContext displayString printCR.
- ] ifFalse:[
- "
- if this is the Signal>>handle:do: context
- or a SignalSet>>handle:do: context with self in it,
- call the handler
- "
- r := theContext receiver.
- (r notNil and:[r accepts:signal]) ifTrue:[
- "call the handler"
+ ] ifFalse:[
+ "
+ if this is the Signal>>handle:do: context
+ or a SignalSet>>handle:do: context with self in it,
+ call the handler
+ "
+ r := theContext receiver.
+ (r notNil and:[r accepts:signal]) ifTrue:[
+ "call the handler"
- conArg1 := theContext argAt:1.
+ conArg1 := theContext argAt:1.
- handlerContext := theContext.
- any := true.
+ handlerContext := theContext.
+ any := true.
- self doCallHandler:conArg1.
+ self doCallHandler:conArg1.
- "if the handler rejects, we arrive here"
- "continue search for another handler"
- rejected := true.
- ].
- ]
+ "/ if the handler rejects, we arrive here
+ "/ continue search for another handler
+
+ rejected := true.
+ ].
]
- ]
+ ].
+ theContext := theContext findNextContextWithSelector:#'handle:do:' or:#'handle:from:do:' or:nil.
].
activeHandlers := nil.
@@ -879,8 +905,8 @@
"... and call it"
^ block value:self.
- "Created: 12.5.1996 / 15:09:39 / cg"
- "Modified: 1.3.1997 / 23:53:14 / cg"
+ "Created: / 12.5.1996 / 15:09:39 / cg"
+ "Modified: / 25.10.1997 / 11:44:35 / cg"
!
raise
@@ -919,6 +945,6 @@
!Exception class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.56 1997-10-10 17:51:02 cg Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic/Exception.st,v 1.57 1997-10-29 14:12:40 cg Exp $'
! !
Exception initialize!