So, while removing the guard on Count::value( ) seems to work, it’s not airtight, and thus on some machines you may see aberrant behavior.
Terminating when blocked
Entrance::run( ) in the previous example includes a call to sleep( ) in the main loop. We know that in that example the sleep will eventually wake up and the task will reach the top of the loop where it has an opportunity to break out of that loop by checking the isPaused( ) status. However, sleep( ) is just one situation in which a thread is
Thread states
A thread can be in any one of four states:
1.
2.
3.
4.
Becoming blocked
A thread is blocked when it cannot continue running. A thread can become blocked for the following reasons:
· You’ve put the thread to sleep by calling sleep(milliseconds), in which case it will not be run for the specified time.
· You’ve suspended the execution of the thread with wait( ). It will not become runnable again until the thread gets the signal( ) or broadcast( ) message. We’ll examine these in a later section.
· The thread is waiting for some I/O to complete.
· The thread is trying to enter a block of code that is guarded by a mutex, and that mutex has already been acquired by another thread.
The problem we need to look at now is this: sometimes you want to terminate a thread that is in a blocked state. It can be blocked for any of the reasons in the above list (
Interruption
As you might imagine, it’s much messier to break out of the middle of a loop than it is to wait for the loop to get to a test of isCanceled( ) (or some other place where the programmer is ready to leave the loop). When you break out of a blocked task, you might be breaking out of your run( ) loop in a place where you must destroy objects and clean up resources. Because of this, breaking out of the middle of a run( ) loop in a task is more like throwing an exception than anything else, so in ZThreads, exceptions are used for this kind of abort. (This walks the fine edge of being an inappropriate use of exceptions because it means you are often using them for control flow.) To return to a known good state when terminating a task this way, carefully consider the execution paths of your code and properly clean up everything inside the catch clause. We’ll look at these issues in this section.
To terminate a blocked thread, the ZThread library provides the Thread::interrupt( ) function. This sets the
Here’s an example that shows the basics of interrupt( ):
//: C11:Interrupting.cpp
// Interrupting a blocked thread.
//{L} ZThread
#include "zthread/Thread.h"
#include
using namespace ZThread;
using namespace std;
class Blocked : public Runnable {
public:
void run() {
try {
Thread::sleep(1000);
cout << "Waiting for get() in run():";
cin.get();
} catch(Interrupted_Exception&) {
cout << "Caught Interrupted_Exception" << endl;
// Exit the task
}
}
};