<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE article SYSTEM "sbk:/style/dtd/article.dtd">

<article status="published"
         year="1997-1999"
         author="J&uuml;rgen Hermann"
         rcsid="$Id: cs7-04.xml,v 1.1 2000/02/16 00:03:56 jh Exp $">

  <copyright>
    This article is Copyright &copy; 1997-98 by J&uuml;rgen Hermann<br/>
    and Copyright &copy; 1999 by C-Scene. All Rights Reserved.
  </copyright>

<s1 title="Callbacks in C++: The OO Way">

  <s2 title="What are Callbacks?">
<p>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 <em>callback object&nbsp;</em> instead of a mere function, some 
OO magic is called for.</p>

<p>As an example, consider the <code>BeginThread</code> API 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 <em>data
pointer&nbsp;</em> that is passed to that function as a startup parameter. Thus, 
we end up with <code>BeginThread (void (*thread_func) (void*), void* startup_data)</code>. 
Now let's make a <code>Thread</code> class of that.</p>


  </s2>

  <s2 title="A simple Thread class">

<p>What we want to have is an ABC (abstract base class) that you can inherit from, 
creating specialized thread classes and in turn thread objects (i.e. actual 
threads). The code of the thread is located in a <em>pure virtual&nbsp;</em> function
<code>code</code> that is provided by the inherited class. <code>code</code> is then 
similar to the <code>thread_func</code> parameter of the <code>BeginThread</code> call,
but is a full-blown member function, not just a C function.

So, we get this interface for the <code>Thread</code> class:</p>
<source>
class Thread {
public:
    virtual ~Thread();
    void run();

protected:
    Thread();
    virtual void code() = 0;

private:
    int running;

    static void dispatch(void* thread_obj);
};
</source>

<p>This might seem quite unusual to you (like having a protected constructor), but 
things will be explained in due course.</p>


  </s2>

  <s2 title="Thread implementation">

<p>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 <code>auto</code> thread 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 method <code>create</code> for 
thread objects in each derived class:</p>
<source>
Thread::Thread() 
    : running(0) 
{
}

DerivedThread&amp; DerivedThread::create()
{
    return *new DerivedThread;
}
</source>

<p><code>create</code> has to be added to every inherited class, returning an object 
of that class.</p>

<p>Next, we need a <code>run</code> method that actually starts the thread. 
This can't be done in the ctor: when <code>code</code> would be registered 
as a thread of execution in the <em>base class&nbsp;</em> ctor, the superclass 
would not yet be fully created and calling <code>code</code> would be quite invalid
and dangerous. <code>run</code> does its job by registering the <code>dispatch</code>
function as a thread, giving that thread the object pointer as a startup parameter;
since <code>dispatch</code> is static, it has a prototype
that matches the <code>void(*)(void*)</code> parameter of <code>BeginThread</code>.</p>
<source>
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;
}
</source>

<p>So finally, <code>dispatch</code> is called and performs the step from a procedural
callback to the callback object:</p>
<source>
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;
}
</source>


  </s2>

  <s2 title="A real Thread class">

<p>A real-world thread class has to consider a few things we have ignored here.
These things include:
</p>
<ol>
<li> more access to the thread data, like a method giving the thread ID.</li>
<li> a method for killing the thread, including the deletion of the thread object.</li>
</ol>

<p>Developed and tested on Windows NT, this is the
<jump href="../../archives/callback.cpp.txt">source</jump> for a little example program that implements the above in the real world.
If you run it, you get something similar to the following output:</p>

<source>
[\cscene\callback]callback
Started thread #80 for dice1
Started thread #84 for dice2
dice1 rolled 1
dice2 rolled 1
dice2 rolled 3
dice1 rolled 1
dice2 rolled 4
dice1 rolled 6
dice1 rolled 3
dice2 rolled 3
dice1 rolled 1
dice1 rolled 4
dice2 rolled 4
dice2 rolled 3
dice1 rolled 1
dice2 rolled 6
dice1 rolled 2
dice2 rolled 2
dice1 rolled 1
dice2 rolled 4
dice2 rolled 1
dice1 rolled 4
dice1 rolled 5
dice2 rolled 1
dice1 rolled 3
dice2 rolled 3
dice1 rolled 2
dice1 rolled 6
dice2 rolled 2
dice1 rolled 1
dice2 rolled 3
dice1 rolled 4
dice1 rolled 5
dice2 rolled 3
dice2 rolled 6
dice1 rolled 4
</source>

<p>Have fun!</p>

  </s2>
</s1>
</article>