Next: , Previous: , Up: Exception handling  


6.11.6 Hooking into the stack unwinding

More often useful than even #on:do: is #ensure:, which guarantees that some code is executed when the stack unwinds, whether because of normal execution or because of a signalled exception.

Here is an example of use of #ensure: and a situation where the stack can unwind even without a signal:

Object subclass: ExecuteWithBreak [
  | breakBlock |

  break: anObject [
    breakBlock value: anObject
  ]

  valueWithBreak: aBlock [
    "Sets up breakBlock before entering the block,
     and passes self to the block."
    | oldBreakBlock |
    oldBreakBlock := breakBlock.
    ^[breakBlock := [:arg | ^arg].
      aBlock value]
        ensure: [breakBlock := oldBreakBlock]
  ]
]

This class provides a way to stop the execution of a block without exiting the whole method as using ^ inside a block would do. The use of #ensure: guarantees (hence the name "ensure") that even if breakBlock is invoked or an error is handled by unwinding, the old “break block” will be restored.

The definition of breakBlock is extremely simply; it is an example of the general unwinding feature of blocks, that you have probably already used:

       (history includesKey: num)
           ifTrue: [ ^self error: 'Duplicate check number' ].

You have probably been using #ensure: without knowing. For example, File>>#withReadStreamDo: uses it to ensure that the file is closed when leaving the block.