handle error in consumer, pass info to producer,
and raise exception there.
--- a/OperationQueue.st Thu Feb 01 14:32:24 2001 +0100
+++ b/OperationQueue.st Thu Feb 01 18:54:53 2001 +0100
@@ -8,7 +8,7 @@
!
Object subclass:#OperationInQueue
- instanceVariableNames:'operation operationPerformedSema operationResult'
+ instanceVariableNames:'operation operationPerformedSema operationResult exception'
classVariableNames:''
poolDictionaries:''
privateIn:OperationQueue
@@ -115,9 +115,17 @@
theOperation := opInQ operation.
Object abortSignal handle:[:ex |
+ Transcript showCR:'operation aborted'.
opInQ operationResult:nil.
] do:[
Object errorSignal handle:[:ex |
+ |ex2|
+
+ Transcript showCR:'operation error: ', ex errorString.
+
+ ex2 := ex shallowCopy.
+ ex2 suspendedContext:(self copyContextChain:ex suspendedContext).
+ opInQ exception:ex2.
opInQ operationResult:nil.
] do:[
rslt := theOperation value.
@@ -161,6 +169,32 @@
] valueUninterruptably
! !
+!OperationQueue methodsFor:'debugging support'!
+
+copyContextChain:aContext
+ "dequeue the next order, evaluate it and wake up waiters"
+
+ |copy|
+
+ copy := aContext shallowCopy.
+ aContext sender notNil ifTrue:[
+ copy setSender:(self copyContextChain:aContext sender)
+ ].
+ ^ copy
+!
+
+linkContextChain:aConsumerChain
+ "for debugging - concatenate aConsumerChain to my own context chain (to make debugging easier)"
+
+ |c|
+
+ c := aConsumerChain.
+ [c sender notNil and:[c methodHome selector ~~ #fetchNextOperationAndExecute]] whileTrue:[
+ c := c sender.
+ ].
+ c setSender:(thisContext sender).
+! !
+
!OperationQueue methodsFor:'initialization'!
initializeLock
@@ -186,11 +220,10 @@
If a similar order is already in the queue, wait for that one to finish.
If asynchronous is true, do not wait (but also: do not return a return value)"
- |myOpInQ|
+ |myOpInQ ex|
queueLock critical:[
"/ operation already in queue ?
-
queue withAccessLockedDo:[
myOpInQ := nil.
queue do:[:eachOpInQ |
@@ -219,7 +252,13 @@
"/ wait for the operation to finish
myOpInQ operationPerformedSema wait.
+ (ex := myOpInQ exception) notNil ifTrue:[
+ "/ trick: makes calling chain look as if the error happended here
+ "/ (in reality, it happended in the consumer-process).
+ self linkContextChain:ex suspendedContext.
+ ^ ex signal raiseErrorString:('asyncronous operation error:' , ex errorString) in:ex suspendedContext
+ ].
"/ now, the operation has been performed - return its result
^ myOpInQ operationResult
! !
@@ -234,6 +273,18 @@
!OperationQueue::OperationInQueue methodsFor:'accessing'!
+exception
+ "return the value of the instance variable 'exception' (automatically generated)"
+
+ ^ exception
+!
+
+exception:something
+ "set the value of the instance variable 'exception' (automatically generated)"
+
+ exception := something.
+!
+
operation
"return the value of the instance variable 'operation' (automatically generated)"
@@ -273,5 +324,5 @@
!OperationQueue class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libbasic2/OperationQueue.st,v 1.4 2000-12-15 15:55:35 martin Exp $'
+ ^ '$Header: /cvs/stx/stx/libbasic2/OperationQueue.st,v 1.5 2001-02-01 17:54:53 martin Exp $'
! !