| 1 | \chapter{Features} | 
|---|
| 2 |  | 
|---|
| 3 | This chapter covers the design and user interface of the \CFA exception | 
|---|
| 4 | handling mechanism. | 
|---|
| 5 |  | 
|---|
| 6 | \section{Virtual Casts} | 
|---|
| 7 |  | 
|---|
| 8 | Virtual casts and virtual types are not truly part of the exception system but | 
|---|
| 9 | they did not exist in \CFA and are useful in exceptions. So a minimal version | 
|---|
| 10 | of they virtual system was designed and implemented. | 
|---|
| 11 |  | 
|---|
| 12 | Virtual types are organizied in simple hierarchies. Each virtual type may have | 
|---|
| 13 | a parent and can have any number of children. A type's descendants are its | 
|---|
| 14 | children and its children's descendants. A type may not be its own descendant. | 
|---|
| 15 |  | 
|---|
| 16 | Each virtual type has an associated virtual table type. A virtual table is a | 
|---|
| 17 | structure that has fields for all the virtual members of a type. A virtual | 
|---|
| 18 | type has all the virtual members of its parent and can add more. It may also | 
|---|
| 19 | update the values of the virtual members. | 
|---|
| 20 |  | 
|---|
| 21 | Except for virtual casts, this is only used internally in the exception | 
|---|
| 22 | system. There is no general purpose interface for the other features. A | 
|---|
| 23 | a virtual cast has the following syntax: | 
|---|
| 24 |  | 
|---|
| 25 | \begin{lstlisting} | 
|---|
| 26 | (virtual TYPE)EXPRESSION | 
|---|
| 27 | \end{lstlisting} | 
|---|
| 28 |  | 
|---|
| 29 | This has the same precidence as a traditional C-cast and can be used in the | 
|---|
| 30 | same places. This will convert the result of EXPRESSION to the type TYPE. Both | 
|---|
| 31 | the type of EXPRESSION and TYPE must be pointers to virtual types. | 
|---|
| 32 |  | 
|---|
| 33 | The cast is checked and will either return the original value or null, based | 
|---|
| 34 | on the result of the check. The check is does the object pointed at have a | 
|---|
| 35 | type that is a descendant of the target type. If it is the result is the | 
|---|
| 36 | pointer, otherwise the result is null. | 
|---|
| 37 |  | 
|---|
| 38 | \section{Exceptions} | 
|---|
| 39 | % Leaving until later, hopefully it can talk about actual syntax instead | 
|---|
| 40 | % of my many strange macros. Syntax aside I will also have to talk about the | 
|---|
| 41 | % features all exceptions support. | 
|---|
| 42 |  | 
|---|
| 43 | \section{Termination} | 
|---|
| 44 |  | 
|---|
| 45 | Termination exception throws are likely the most framilar kind, as they are | 
|---|
| 46 | used in several popular programming languages. A termination will throw an | 
|---|
| 47 | exception, search the stack for a handler, unwind the stack to where the | 
|---|
| 48 | handler is defined, execute the handler and then continue execution after | 
|---|
| 49 | the handler. They are used when execution cannot continue here. | 
|---|
| 50 |  | 
|---|
| 51 | Termination has two pieces of syntax it uses. The first is the throw: | 
|---|
| 52 | \begin{lstlisting} | 
|---|
| 53 | throw EXPRESSION; | 
|---|
| 54 | \end{lstlisting} | 
|---|
| 55 |  | 
|---|
| 56 | The expression must evaluate to a reference to a termination exception. A | 
|---|
| 57 | termination exception is any exception with a | 
|---|
| 58 | \codeCFA{void defaultTerminationHandler(T &);} (the default handler) defined | 
|---|
| 59 | on it. The handler is taken from the call sight with \CFA's trait system and | 
|---|
| 60 | passed into the exception system along with the exception itself. | 
|---|
| 61 |  | 
|---|
| 62 | The exception passed into the system is then copied into managed memory. | 
|---|
| 63 | This is to ensure it remains in scope during unwinding. It is the user's | 
|---|
| 64 | responsibility to make sure the original exception is freed when it goes out | 
|---|
| 65 | of scope. Being allocated on the stack is sufficient for this. | 
|---|
| 66 |  | 
|---|
| 67 | Then the exception system will search the stack starting from the throw and | 
|---|
| 68 | proceding towards the base of the stack, from callee to caller. As it goes | 
|---|
| 69 | it will check any termination handlers it finds: | 
|---|
| 70 |  | 
|---|
| 71 | \begin{lstlisting} | 
|---|
| 72 | try { | 
|---|
| 73 | TRY_BLOCK | 
|---|
| 74 | } catch (EXCEPTION_TYPE * NAME) { | 
|---|
| 75 | HANDLER | 
|---|
| 76 | } | 
|---|
| 77 | \end{lstlisting} | 
|---|
| 78 |  | 
|---|
| 79 | This shows a try statement with a single termination handler. The statements | 
|---|
| 80 | in TRY\_BLOCK will be executed when control reaches this statement. While | 
|---|
| 81 | those statements are being executed if a termination exception is thrown and | 
|---|
| 82 | it is not handled by a try statement further up the stack the EHM will check | 
|---|
| 83 | all of the terminations handlers attached to the try block, top to bottom. | 
|---|
| 84 |  | 
|---|
| 85 | At each handler the EHM will check to see if the thrown exception is a | 
|---|
| 86 | descendant of EXCEPTION\_TYPE. If it is the pointer to the exception is | 
|---|
| 87 | bound to NAME and the statements in HANDLER are executed. If control reaches | 
|---|
| 88 | the end of the handler then it exits the block, the exception is freed and | 
|---|
| 89 | control continues after the try statement. | 
|---|
| 90 |  | 
|---|
| 91 | The default handler is only used if no handler for the exception is found | 
|---|
| 92 | after the entire stack is searched. When that happens the default handler | 
|---|
| 93 | is called with a reference to the exception as its only argument. If the | 
|---|
| 94 | handler returns control continues from after the throw statement. | 
|---|
| 95 |  | 
|---|
| 96 | \paragraph{Conditional Catches} | 
|---|
| 97 |  | 
|---|
| 98 | Catch clauses may also be written as: | 
|---|
| 99 | \begin{lstlisting} | 
|---|
| 100 | catch (EXCEPTION_TYPE * NAME ; CONDITION) | 
|---|
| 101 | \end{lstlisting} | 
|---|
| 102 | This has the same behaviour as a regular catch clause except that if the | 
|---|
| 103 | exception matches the given type the condition is also run. If the result is | 
|---|
| 104 | true only then is this considered a matching handler. If the result is false | 
|---|
| 105 | then the handler does not match and the search continues with the next clause | 
|---|
| 106 | in the try block. | 
|---|
| 107 |  | 
|---|
| 108 | The condition considers all names in scope at the beginning of the try block | 
|---|
| 109 | to be in scope along with the name introduce in the catch clause itself. | 
|---|
| 110 |  | 
|---|
| 111 | \paragraph{Re-Throwing} | 
|---|
| 112 |  | 
|---|
| 113 | You can also rethrow the most recent termination exception with | 
|---|
| 114 | \codeCFA{throw;}. % This is terrible and you should never do it. | 
|---|
| 115 | This can be done in a handler or any function that could be called from a | 
|---|
| 116 | handler. | 
|---|
| 117 |  | 
|---|
| 118 | This will start another termination throw reusing the exception, meaning it | 
|---|
| 119 | does not copy the exception or allocated any more memory for it. However the | 
|---|
| 120 | default handler is still at the original through and could refer to data that | 
|---|
| 121 | was on the unwound section of the stack. So instead a new default handler that | 
|---|
| 122 | does a program level abort is used. | 
|---|
| 123 |  | 
|---|
| 124 | \section{Resumption} | 
|---|
| 125 |  | 
|---|
| 126 | Resumption exceptions are less popular then termination but in many | 
|---|
| 127 | regards are simpler and easier to understand. A resumption throws an exception, | 
|---|
| 128 | searches for a handler on the stack, executes that handler on top of the stack | 
|---|
| 129 | and then continues execution from the throw. These are used when a problem | 
|---|
| 130 | needs to be fixed before execution continues. | 
|---|
| 131 |  | 
|---|
| 132 | A resumption is thrown with a throw resume statement: | 
|---|
| 133 | \begin{lstlisting} | 
|---|
| 134 | throwResume EXPRESSION; | 
|---|
| 135 | \end{lstlisting} | 
|---|
| 136 | The result of EXPRESSION must be a resumption exception type. A resumption | 
|---|
| 137 | exception type is any type that satifies the assertion | 
|---|
| 138 | \codeCFA{void defaultResumptionHandler(T &);} (the default handler). When the | 
|---|
| 139 | statement is executed the expression is evaluated and the result is thrown. | 
|---|
| 140 |  | 
|---|
| 141 | Handlers are declared using clauses in try statements: | 
|---|
| 142 | \begin{lstlisting} | 
|---|
| 143 | try { | 
|---|
| 144 | TRY_BLOCK | 
|---|
| 145 | } catchResume (EXCEPTION_TYPE * NAME) { | 
|---|
| 146 | HANDLER | 
|---|
| 147 | } | 
|---|
| 148 | \end{lstlisting} | 
|---|
| 149 | This is a simple example with the try block and a single resumption handler. | 
|---|
| 150 | Multiple resumption handlers can be put in a try statement and they can be | 
|---|
| 151 | mixed with termination handlers. | 
|---|
| 152 |  | 
|---|
| 153 | When a resumption begins it will start searching the stack starting from | 
|---|
| 154 | the throw statement and working its way to the callers. In each try statement | 
|---|
| 155 | handlers will be tried top to bottom. Each handler is checked by seeing if | 
|---|
| 156 | the thrown exception is a descendant of EXCEPTION\_TYPE. If not the search | 
|---|
| 157 | continues. Otherwise NAME is bound to a pointer to the exception and the | 
|---|
| 158 | HANDLER statements are executed. After they are finished executing control | 
|---|
| 159 | continues from the throw statement. | 
|---|
| 160 |  | 
|---|
| 161 | If no approprate handler is found then the default handler is called. The | 
|---|
| 162 | throw statement acts as a regular function call passing the exception to | 
|---|
| 163 | the default handler and after the handler finishes executing control continues | 
|---|
| 164 | from the throw statement. | 
|---|
| 165 |  | 
|---|
| 166 | The exception system also tracks the position of a search on the stack. If | 
|---|
| 167 | another resumption exception is thrown while a resumption handler is running | 
|---|
| 168 | it will first check handlers pushed to the stack by the handler and any | 
|---|
| 169 | functions it called, then it will continue from the try statement that the | 
|---|
| 170 | handler is a part of; except for the default handler where it continues from | 
|---|
| 171 | the throw the default handler was passed to. | 
|---|
| 172 |  | 
|---|
| 173 | This makes the search pattern for resumption reflect the one for termination, | 
|---|
| 174 | which is what most users expect. | 
|---|
| 175 |  | 
|---|
| 176 | % This might need a diagram. But it is an important part of the justifaction | 
|---|
| 177 | % of the design of the traversal order. | 
|---|
| 178 | It also avoids the recursive resumption problem. If the entire stack is | 
|---|
| 179 | searched loops of resumption can form. Consider a handler that handles an | 
|---|
| 180 | exception of type A by resuming an exception of type B and on the same stack, | 
|---|
| 181 | later in the search path, is a second handler that handles B by resuming A. | 
|---|
| 182 |  | 
|---|
| 183 | Assuming no other handlers on the stack handle A or B then in either traversal | 
|---|
| 184 | system an A resumed from the top of the stack will be handled by the first | 
|---|
| 185 | handler. A B resumed from the top or from the first handler it will be handled | 
|---|
| 186 | by the second hander. The only difference is when A is thrown from the second | 
|---|
| 187 | handler. The entire stack search will call the first handler again, creating a | 
|---|
| 188 | loop. Starting from the position in the stack though will break this loop. | 
|---|
| 189 |  | 
|---|
| 190 | \paragraph{Conditional Catches} | 
|---|
| 191 |  | 
|---|
| 192 | Resumption supports conditional catch clauses like termination does. They | 
|---|
| 193 | use the same syntax except the keyword is changed: | 
|---|
| 194 | \begin{lstlisting} | 
|---|
| 195 | catchResume (EXCEPTION_TYPE * NAME ; CONDITION) | 
|---|
| 196 | \end{lstlisting} | 
|---|
| 197 |  | 
|---|
| 198 | It also has the same behaviour, after the exception type has been matched | 
|---|
| 199 | with the EXCEPTION\_TYPE the CONDITION is evaluated with NAME in scope. If | 
|---|
| 200 | the result is true then the hander is run, otherwise the search continues | 
|---|
| 201 | just as if there had been a type mismatch. | 
|---|
| 202 |  | 
|---|
| 203 | \paragraph{Re-Throwing} | 
|---|
| 204 |  | 
|---|
| 205 | You may also re-throw resumptions with a \codeCFA{throwResume;} statement. | 
|---|
| 206 | This can only be done from inside of a \codeCFA{catchResume} block. | 
|---|
| 207 |  | 
|---|
| 208 | Outside of any side effects of any code already run in the handler this will | 
|---|
| 209 | have the same effect as if the exception had not been caught in the first | 
|---|
| 210 | place. | 
|---|
| 211 |  | 
|---|
| 212 | \section{Finally Clauses} | 
|---|
| 213 |  | 
|---|
| 214 | A \codeCFA{finally} clause may be placed at the end of a try statement after | 
|---|
| 215 | all the handler clauses. In the simply case, with no handlers, it looks like | 
|---|
| 216 | this: | 
|---|
| 217 |  | 
|---|
| 218 | \begin{lstlisting} | 
|---|
| 219 | try { | 
|---|
| 220 | TRY_BLOCK | 
|---|
| 221 | } finally { | 
|---|
| 222 | FINAL_STATEMENTS | 
|---|
| 223 | } | 
|---|
| 224 | \end{lstlisting} | 
|---|
| 225 |  | 
|---|
| 226 | Any number of termination handlers and resumption handlers may proceed the | 
|---|
| 227 | finally clause. | 
|---|
| 228 |  | 
|---|
| 229 | The FINAL\_STATEMENTS, the finally block, are executed whenever the try | 
|---|
| 230 | statement is removed from the stack. This includes: the TRY\_BLOCK finishes | 
|---|
| 231 | executing, a termination exception finishes executing and the stack unwinds. | 
|---|
| 232 |  | 
|---|
| 233 | Execution of the finally block should finish by letting control run off | 
|---|
| 234 | the end of the block. This is because after the finally block is complete | 
|---|
| 235 | control will continue to where ever it would if the finally clause was not | 
|---|
| 236 | present. | 
|---|
| 237 |  | 
|---|
| 238 | Because of this local control flow out of the finally block is forbidden. | 
|---|
| 239 | The compiler rejects uses of \codeCFA{break}, \codeCFA{continue}, | 
|---|
| 240 | \codeCFA{fallthru} and \codeCFA{return} that would cause control to leave | 
|---|
| 241 | the finally block. Other ways to leave the finally block - such as a long | 
|---|
| 242 | jump or termination - are much harder to check, at best requiring additional | 
|---|
| 243 | runtime overhead, and so are merely discouraged. | 
|---|
| 244 |  | 
|---|
| 245 | \section{Cancellation} | 
|---|
| 246 |  | 
|---|
| 247 | Cancellation can be thought of as a stack-level abort or as an uncatchable | 
|---|
| 248 | termination. It unwinds the entirety of the current exception and if possible | 
|---|
| 249 | passes an exception to a different stack as a message. | 
|---|
| 250 |  | 
|---|
| 251 | There is no special statement for starting a cancellation, instead you call | 
|---|
| 252 | the standard libary function \codeCFA{cancel\_stack} which takes an exception. | 
|---|
| 253 | Unlike in a throw this exception is not used in control flow but is just there | 
|---|
| 254 | to pass information about why the cancellation happened. | 
|---|
| 255 |  | 
|---|
| 256 | The handler is decided entirely by which stack is being cancelled. There are | 
|---|
| 257 | three handlers that apply to three different groups of stacks: | 
|---|
| 258 | \begin{itemize} | 
|---|
| 259 | \item Main Stack: | 
|---|
| 260 | The main stack is the one on which the program main is called at the beginning | 
|---|
| 261 | of your program. It is also the only stack you have without the libcfathreads. | 
|---|
| 262 |  | 
|---|
| 263 | Because of this there is no other stack ``above" (or possibly at all) for main | 
|---|
| 264 | to notify when a cancellation occurs. So after the stack is unwound we do a | 
|---|
| 265 | program level abort. | 
|---|
| 266 |  | 
|---|
| 267 | \item Thread Stack: | 
|---|
| 268 | Thread stacks are those created \codeCFA{thread} or otherwise satify the | 
|---|
| 269 | \codeCFA{is\_thread} trait. | 
|---|
| 270 |  | 
|---|
| 271 | Threads only have two structural points of communication that must happen, | 
|---|
| 272 | start and join. As the thread must be running to preform a cancellation it | 
|---|
| 273 | will be after start and before join, so join is one cancellation uses. | 
|---|
| 274 |  | 
|---|
| 275 | After the stack is unwound the thread will halt as if had completed normally | 
|---|
| 276 | and wait for another thread to join with it. The other thread, when it joins, | 
|---|
| 277 | checks for a cancellation. If so it will throw the resumption exception | 
|---|
| 278 | \codeCFA{ThreadCancelled}. | 
|---|
| 279 |  | 
|---|
| 280 | There is a difference here in how explicate joins (with the \codeCFA{join} | 
|---|
| 281 | function) and implicate joins (from a destructor call). Explicate joins will | 
|---|
| 282 | take the default handler (\codeCFA{defaultResumptionHandler}) from the context | 
|---|
| 283 | and use like a regular through does if the exception is not caught. The | 
|---|
| 284 | implicate join does a program abort instead. | 
|---|
| 285 |  | 
|---|
| 286 | This is for safety. One of the big problems in exceptions is you cannot handle | 
|---|
| 287 | two terminations or cancellations on the same stack as either can destroy the | 
|---|
| 288 | context required for the other. This can happen with join but as the | 
|---|
| 289 | destructors will always be run when the stack is being unwound and one | 
|---|
| 290 | termination/cancellation is already active. Also since they are implicite they | 
|---|
| 291 | are easier to forget about. | 
|---|
| 292 |  | 
|---|
| 293 | \item Coroutine Stack: | 
|---|
| 294 | Coroutine stacks are those created with \codeCFA{coroutine} or otherwise | 
|---|
| 295 | satify the \codeCFA{is\_coroutine} trait. | 
|---|
| 296 |  | 
|---|
| 297 | A coroutine knows of two other coroutines, its starter and its last resumer. | 
|---|
| 298 | The last resumer is ``closer" so that is the one notified. | 
|---|
| 299 |  | 
|---|
| 300 | After the stack is unwound control goes to the last resumer. | 
|---|
| 301 | Resume will resume throw a \codeCFA{CoroutineCancelled} exception, which is | 
|---|
| 302 | polymorphic over the coroutine type and has a pointer to the coroutine being | 
|---|
| 303 | cancelled and the cancelling exception. The resume function also has an | 
|---|
| 304 | assertion that the \codeCFA{defaultResumptionHandler} for the exception. So it | 
|---|
| 305 | will use the default handler like a regular throw. | 
|---|
| 306 |  | 
|---|
| 307 | \end{itemize} | 
|---|