- 13.1 Concurrentgate
- 13.2 A Brief History of Data Sharing
- 13.3 Look, Ma, No (Default) Sharing
- 13.4 Starting a Thread
- 13.5 Exchanging Messages between Threads
- 13.6 Pattern Matching with receive
- 13.7 File Copyingwith a Twist
- 13.8 Thread Termination
- 13.9 Out-of-Band Communication
- 13.10 Mailbox Crowding
- 13.11 The shared Type Qualifier
- 13.12 Operations with shared Data and Their Effects
- 13.13 Lock-Based Synchronization with synchronized classes
- 13.14 Field Typing in synchronized classes
- 13.15 Deadlocks and the synchronized Statement
- 13.16 Lock-Free Coding with shared classes
- 13.17 Summary
13.9 Out-of-Band Communication
Consider that you're using the presumably smart file-copying program we just defined to copy a large file from a fast local store to a slow network drive. Midway through the copy, there's a read error—the file is corrupt. That causes read and subsequently main to throw an exception while there are many buffers in flight that haven't yet been written. More generally, we saw that if the owner terminates normally, any blocking call to receive from its owned threads will throw. What happens if the owner exits with an exception?
If a thread terminates by means of an exception, that indicates a serious issue that must be signaled with relative urgency to the owned threads. Indeed this is carried out via an out-of-band message.
Recall that receive cares only about matching messages and lets all others accumulate in the queue. There is one amendment to that behavior. A thread may initiate an out-of-band message by calling prioritySend instead of send. The two functions accept the same parameters but exhibit different behaviors that actually manifest themselves on the receiving side. Passing a message of type T with prioritySend causes receive in the receiving thread to act as follows:
- If the call to receive handles type T, then the priority message will be the next message handled, even though it arrived later than other regular (non-priority) messages. Priority messages are always pushed to the beginning of the queue, so the latest priority message sent is always the first fetched by receive (even if other priority messages are already waiting).
- If the call to receive does not handle type T (i.e., would leave the message waiting in the mailbox) and if T inherits Exception, receive throws the message directly.
- If the call to receive does not handle type T and T does not inherit Exception, receive throws an exception of type PriorityMessageException!T. That exception holds a copy of the message sent in the form of a member called message.
If a thread exits via an exception, the exception OwnerFailed propagates to all of its owned threads by means of prioritySend. In the file copy program, main throwing also causes fileWriter to throw as soon as it calls receive, and the entire process terminates by printing an error message and returning a nonzero exit code. Unlike the normal termination case, there may be buffers in flight that have been read but not yet written.