45 ! |
47 ! |
46 |
48 |
47 documentation |
49 documentation |
48 " |
50 " |
49 Note: |
51 Note: |
50 The instance based Signal framework is being replaced by |
52 The instance based Signal framework is being replaced by |
51 class based exceptions. |
53 class based exceptions. |
52 I.e. what used to be instances of Signal/QuerySignal is beeing |
54 I.e. what used to be instances of Signal/QuerySignal is being |
53 rewritten into subclasses of Exception/Error/Query and Warning. |
55 rewritten into subclasses of Exception/Error/Query and Warning. |
54 Although the functionality is basically unchanged, the new |
56 Although the functionality is basically unchanged, the new |
55 class based exceptions are easier to instanciate (no need for |
57 class based exceptions are easier to instanciate (no need for |
56 creation in a classes initialize method), easier to use (no real |
58 creation in a classes initialize method), easier to use (no real |
57 need for SIgnal-constant accessors) and allow for easier parameter |
59 need for SIgnal-constant accessors) and allow for easier parameter |
58 passing (not only a single parameter, but allows for individual |
60 passing (not only a single parameter, but allows for individual |
59 exception subclasses to add additional state). |
61 exception subclasses to add additional state). |
60 |
62 |
61 GenericException and its subclasses implement the same protocol as Signal. |
63 GenericException and its subclasses implement the same protocol as Signal. |
62 So class based exceptions may be implemented as subclasses of GenericException. |
64 So class based exceptions may be implemented as subclasses of GenericException. |
63 |
65 |
64 Normally all exceptions are subclasses of Exception. Exceptions, that are |
66 Normally all exceptions are subclasses of Exception. Exceptions, that are |
67 |
69 |
68 Instances of Exception are passed to a Signal handling block as argument. |
70 Instances of Exception are passed to a Signal handling block as argument. |
69 The handler block may perform various actions by sending corresponding messages |
71 The handler block may perform various actions by sending corresponding messages |
70 to the exception object. The following actions are possible: |
72 to the exception object. The following actions are possible: |
71 |
73 |
72 reject - don't handle this signal; |
74 reject - don't handle this signal; |
73 another handler will be searched for, |
75 another handler will be searched for, |
74 upper in the calling hierarchy |
76 upper in the calling hierarchy |
75 |
77 |
76 proceed - return from the Signal>>raise, with nil as value |
78 proceed - return from the Signal>>raise, with nil as value |
77 |
79 |
78 proceedWith:val - same, but return val from Signal>>raise |
80 proceedWith:val - same, but return val from Signal>>raise |
79 |
81 |
80 return - return from the Signal>>handle:do:, with nil as value |
82 return - return from the Signal>>handle:do:, with nil as value |
81 |
83 |
82 returnWith:val - same, but return val from Signal>>handle:do: |
84 returnWith:val - same, but return val from Signal>>handle:do: |
83 (this is also the handler's default, |
85 (this is also the handler's default, |
84 if it falls through; taking the handlerBlocks value |
86 if it falls through; taking the handlerBlocks value |
85 as return value) |
87 as return value) |
86 |
88 |
87 restart - restart the Signal>>handle:do:, after repairing |
89 restart - restart the Signal>>handle:do:, after repairing |
88 |
90 |
89 Via the Exception object, the handler can also query the state of execution: |
91 Via the Exception object, the handler can also query the state of execution: |
90 where the Signal was raised, where the handler is, the signal which caused |
92 where the Signal was raised, where the handler is, the signal which caused |
91 the error and the messageText passed when the signal was raised. Also, an optional |
93 the error and the messageText passed when the signal was raised. Also, an optional |
92 parameter can be passed - the use is signal specific. |
94 parameter can be passed - the use is signal specific. |
93 |
95 |
94 [instance variables:] |
96 [instance variables:] |
95 signal <Signal> the signal which caused the exception |
97 signal <Signal> the signal which caused the exception |
96 |
98 |
97 parameter <Object> a parameter (if any) which was passed when raising |
99 parameter <Object> a parameter (if any) which was passed when raising |
98 the signal (only if raised with #raiseWith:aParameter) |
100 the signal (only if raised with #raiseWith:aParameter) |
99 |
101 |
100 messageText <String> an messageText |
102 messageText <String> an messageText |
101 (usually the signals own messageText, but sometimes |
103 (usually the signals own messageText, but sometimes |
102 changed explicitely in #raiseWith:errorString:) |
104 changed explicitely in #raiseWith:errorString:) |
103 |
105 |
104 suspendedContext <Context> the context in which the raise occured |
106 suspendedContext <Context> the context in which the raise occured |
105 |
107 |
106 handlerContext <Context> the context of the handler (if any) |
108 handlerContext <Context> the context of the handler (if any) |
107 |
109 |
108 In case of an unhandled signal raise, Exceptions EmergenyHandler will be evaluated. |
110 In case of an unhandled signal raise, Exceptions EmergenyHandler will be evaluated. |
109 The default emergeny handler will enter the debugger. |
111 The default emergeny handler will enter the debugger. |
110 |
112 |
111 For applications, which do not want Debuggers to come up, other handlers are |
113 For applications, which do not want Debuggers to come up, other handlers are |
112 possible. |
114 possible. |
113 For example, to get the typical C++ behavior, use: |
115 For example, to get the typical C++ behavior, use: |
114 Exception emergencyHandler:[:ex | Smalltalk exitWithCoreDump] |
116 Exception emergencyHandler:[:ex | Smalltalk exitWithCoreDump] |
115 |
117 |
116 |
118 |
117 Raising: |
119 Raising: |
118 two different raising messages are to be used, |
120 two different raising messages are to be used, |
119 depending on whether the exception is proceedable or not |
121 depending on whether the exception is proceedable or not |
120 |
122 |
121 For some stupid reason, someone decided that the raise-code checks if |
123 For some stupid reason, someone decided that the raise-code checks if |
122 the raising messages matches to what the signal thinks is its proceedability. |
124 the raising messages matches to what the signal thinks is its proceedability. |
123 (i.e. not only do both the sender and the signal itself specify proceedability, |
125 (i.e. not only do both the sender and the signal itself specify proceedability, |
124 this is checked by the raise code and a warning is generated if there is a mismatch) |
126 this is checked by the raise code and a warning is generated if there is a mismatch) |
125 This used to be even worse (WrongProceedabilityError), but we relaxed this to |
127 This used to be even worse (WrongProceedabilityError), but we relaxed this to |
126 a message sent to stderr. |
128 a message sent to stderr. |
127 |
129 |
128 That means, that PROCEEDABLE signals must be raised with: |
130 That means, that PROCEEDABLE signals must be raised with: |
129 raiseRequest |
131 raiseRequest |
130 and NON-PROCEEDABLE signals must be raised with: |
132 and NON-PROCEEDABLE signals must be raised with: |
131 raise |
133 raise |
132 |
134 |
133 If you dont know/care as a raiser, you can use |
135 If you dont know/care as a raiser, you can use |
134 raiseSignal |
136 raiseSignal |
135 which checks for proceedability and sends the appropriate message. |
137 which checks for proceedability and sends the appropriate message. |
136 (sigh) |
138 (sigh) |
137 |
139 |
138 all of the 3 messages above come in various flavours: |
140 all of the 3 messages above come in various flavours: |
139 raiseXXX - do not pass any additional parameter; |
141 raiseXXX - do not pass any additional parameter; |
140 default messageText |
142 default messageText |
141 |
143 |
142 raiseXXXWith: - pass additional parameter; |
144 raiseXXXWith: - pass additional parameter; |
143 default messageText |
145 default messageText |
144 |
146 |
145 raiseXXXErrorString: - do not pass any additional parameter; |
147 raiseXXXErrorString: - do not pass any additional parameter; |
146 given errorString |
148 given errorString |
147 |
149 |
148 raiseXXXWith:errorString: |
150 raiseXXXWith:errorString: |
149 - pass any additional parameter; |
151 - pass any additional parameter; |
150 AND given errorString |
152 AND given errorString |
151 |
153 |
152 |
154 |
153 [see also:] |
155 [see also:] |
154 Signal SignalSet QuerySignal |
156 Signal SignalSet QuerySignal |
155 Context Block |
157 Context Block |
156 Object DebugView |
158 Object DebugView |
157 (``Exception handling and signals'': programming/exceptions.html) |
159 (``Exception handling and signals'': programming/exceptions.html) |
158 |
160 |
159 [author:] |
161 [author:] |
160 Claus Gittinger |
162 Claus Gittinger |
161 " |
163 " |
162 ! |
164 ! |
163 |
165 |
164 examples |
166 examples |
165 " |
167 " |
549 |
550 |
550 "Created: / 23-07-1999 / 14:07:17 / stefan" |
551 "Created: / 23-07-1999 / 14:07:17 / stefan" |
551 "Modified: / 10-08-2010 / 09:30:42 / cg" |
552 "Modified: / 10-08-2010 / 09:30:42 / cg" |
552 ! |
553 ! |
553 |
554 |
|
555 raiseAsQuery |
|
556 "utility to avoid code duplication. |
|
557 raise the exception as a query. This means, that if it is unhandled, |
|
558 a default value is returned (i.e. an implicit resume). |
|
559 Return the handler's value (if there is one), or the default value, if not. |
|
560 Invoking the handler is exactly the functionality of Signal>>raiseRequest, |
|
561 but we can do it faster here (avoiding the construction of an exception instance)." |
|
562 |
|
563 |con signal ret| |
|
564 |
|
565 self isQuerySignal ifFalse:[ self error:'this may only be used by queries' ]. |
|
566 |
|
567 con := Context findFirstSpecialHandle:true raise:false. |
|
568 [con notNil] whileTrue:[ |
|
569 (con selector == #answer:do:) ifTrue:[ |
|
570 signal := con receiver. |
|
571 signal == self ifTrue:[ |
|
572 ret := con argAt:1. |
|
573 con := nil. |
|
574 ^ ret |
|
575 ]. |
|
576 signal isNil ifTrue:[ |
|
577 self error:'nil receiver in #answer:do: - send'. |
|
578 ]. |
|
579 (signal accepts:self) ifTrue:[ |
|
580 ret := con argAt:1. |
|
581 con := nil. |
|
582 ^ ret |
|
583 ]. |
|
584 ] ifFalse:[ |
|
585 "ask the the receiver of the #handle:do: or #on:do: or whatever- message for the handler. |
|
586 nil is returned, if the signal is not accepted" |
|
587 |r| |
|
588 r := con receiver. "receiver of #handle:do: or #on:do:" |
|
589 (r notNil and:[(r handlerForSignal:self |
|
590 context:con |
|
591 originator:thisContext sender homeReceiver) notNil] |
|
592 ) ifTrue:[ |
|
593 "there is another handler block, maybe it will return the answer. |
|
594 Call it via raiseRequest" |
|
595 con := nil. |
|
596 ^ here raiseRequest "/ <- notice the here, to avoid recursion due |
|
597 "/ to redefined raiseRequest in Query |
|
598 ]. |
|
599 ]. |
|
600 con := con findSpecialHandle:true raise:false. |
|
601 ]. |
|
602 |
|
603 "/ no handler found - return the default value |
|
604 ^ self defaultAnswer |
|
605 |
|
606 "Modified: / 15-06-1998 / 21:27:37 / cg" |
|
607 "Modified: / 25-07-1999 / 23:15:16 / stefan" |
|
608 "Modified: / 11-03-2015 / 11:26:45 / sr" |
|
609 ! |
|
610 |
554 raiseErrorString:aString |
611 raiseErrorString:aString |
555 "raise a signal nonproceedable. |
612 "raise a signal nonproceedable. |
556 The argument is used as messageText." |
613 The argument is used as messageText." |
557 |
614 |
558 <context: #return> |
615 <context: #return> |