| 1.  
      What are Callbacks? 2.  
      A simple Thread class
 3.  
      Thread implementation
 4.  
      A real Thread class
 
 
        by Jürgen Hermannlast updated 2000/02/16
        (version 1.1)
 also available as XML
 |  |  |  | Many operating systems and other subsystems (like GUI libraries) feature 
a special type of hook into those systems, named callbacks or callback 
functions. Upon initialization or by calling an API function you pass 
pointers to the callback into the subsystem, for later use.
The problem with those functions is, since these subsystems are nowadays 
not yet OO, that they have no notion of what an object is. So if you want 
to have a callback object  instead of a mere function, some 
OO magic is called for. As an example, consider the BeginThreadAPI that many OSes have 
in a quite similar form; we assume that it takes a pointer to the function 
that provides the actual code for the newly created thread plus a data
pointer  that is passed to that function as a startup parameter. Thus, 
we end up withBeginThread (void (*thread_func) (void*), void* startup_data). 
Now let's make aThreadclass of that. | 
 
 
 |  |  |  | When we put the thread concept into a class, we have to consider lifetime. A 
thread exists as long as the thread function does not return, thus the object 
has to have the same lifetime. Because of this, an autothread object does not 
make much sense; we insure that every thread object exists on the heap by making 
the ctor protected and providing a static factory methodcreatefor 
thread objects in each derived class: |  |  |  |  |  | 
Thread::Thread() 
    : running(0) 
{
}
DerivedThread& DerivedThread::create()
{
    return *new DerivedThread;
}
 |  |  |  |  |  | 
createhas to be added to every inherited class, returning an object 
of that class.
 Next, we need a runmethod that actually starts the thread. 
This can't be done in the ctor: whencodewould be registered 
as a thread of execution in the base class  ctor, the superclass 
would not yet be fully created and callingcodewould be quite invalid
and dangerous.rundoes its job by registering thedispatchfunction as a thread, giving that thread the object pointer as a startup parameter;
sincedispatchis static, it has a prototype
that matches thevoid(*)(void*)parameter ofBeginThread. |  |  |  |  |  | 
void Thread::run()
{
    // Don't start two threads on the same object
    if (running) return;
    // Create an OS thread, using the static callback
    BeginThread(Thread::dispatch, this);
    running = 1;
}
 |  |  |  |  |  | 
So finally, dispatchis called and performs the step from a procedural
callback to the callback object: |  |  |  |  |  | 
void Thread::dispatch(void* thread_obj)
{
    // Call the actual OO thread code
    ((Thread*)thread_obj)->code();
    // After code() returns, kill the thread object
    delete (Thread*)thread_obj;
}
 |  |  |  |  |  | 
 | 
 
 
 
    This article is Copyright © 1997-98 by Jürgen Hermannand Copyright © 1999 by C-Scene. All Rights Reserved.
 |