X-Git-Url: https://git.llucax.com/z.facultad/75.42/plaqui.git/blobdiff_plain/636801b890ff84ae25747057e3d2c6074616f16e..791761837820d89454dc5ee4a019860dcd6b6477:/docs/oo_callbacks_cpp/oo_callbacks_cpp.html diff --git a/docs/oo_callbacks_cpp/oo_callbacks_cpp.html b/docs/oo_callbacks_cpp/oo_callbacks_cpp.html index 5eaa828..839e513 100644 --- a/docs/oo_callbacks_cpp/oo_callbacks_cpp.html +++ b/docs/oo_callbacks_cpp/oo_callbacks_cpp.html @@ -1,197 +1,197 @@ - - -Callbacks in C++: The OO Way - - - - - - - - -
C-Scene Issues 1..9 Authors
Algorithms Books Patterns Graphics Miscellaneous UNIX Web & XML Windows
Feedback FAQs Changes Submissions
-
-

Callbacks in C++: The OO Way

-
-

Content

-
    -
  1. What are - Callbacks? -
  2. A simple - Thread class -
  3. Thread - implementation -
  4. A real - Thread class
-
-

by Jürgen Hermann
last updated 2001/08/02 (version -1.1.1.1)
also available as XML

-
-

What are Callbacks?

-

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 BeginThread 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 data -pointer  that is passed to that function as a startup parameter. Thus, -we end up with BeginThread (void (*thread_func) (void*), void* -startup_data). Now let's make a Thread class of -that.

-
-

A simple Thread class

-

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 pure -virtual  function code that is provided by the inherited -class. code is then similar to the thread_func -parameter of the BeginThread call, but is a full-blown member -function, not just a C function. So, we get this interface for the -Thread class:

class Thread {
-public:
-    virtual ~Thread();
-    void run();
-
-protected:
-    Thread();
-    virtual void code() = 0;
-
-private:
-    int running;
-
-    static void dispatch(void* thread_obj);
-};
-
-

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

-
-

Thread implementation

-

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 auto 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 -create for thread objects in each derived class:

Thread::Thread() 
-    : running(0) 
-{
-}
-
-DerivedThread& DerivedThread::create()
-{
-    return *new DerivedThread;
-}
-
-

create has to be added to every inherited class, returning an -object of that class.

-

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

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, dispatch is 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;
-}
-
-
-

A real Thread class

-

A real-world thread class has to consider a few things we have ignored here. -These things include:

-
    -
  1. more access to the thread data, like a method giving the thread ID. -
  2. a method for killing the thread, including the deletion of the thread - object.
-

Developed and tested on Windows NT, this is the source 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:

[\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
-
-

Have fun!

-

This article is Copyright © 1997-98 by Jürgen Hermann
and -Copyright © 1999 by C-Scene. All Rights Reserved.

-
-
-Copyright © 1997-2000 by C-Scene. All Rights Reserved.

Part of the -graphics and stylesheets used to generate this site are
Copyright © 1999-2000 -by Apache Software Foundation.
+ + +Callbacks in C++: The OO Way + + + + + + + + +
C-Scene Issues 1..9 Authors
Algorithms Books Patterns Graphics Miscellaneous UNIX Web & XML Windows
Feedback FAQs Changes Submissions
+
+

Callbacks in C++: The OO Way

+
+

Content

+
    +
  1. What are + Callbacks? +
  2. A simple + Thread class +
  3. Thread + implementation +
  4. A real + Thread class
+
+

by Jürgen Hermann
last updated 2001/08/02 (version +1.1.1.1)
also available as XML

+
+

What are Callbacks?

+

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 BeginThread 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 data +pointer  that is passed to that function as a startup parameter. Thus, +we end up with BeginThread (void (*thread_func) (void*), void* +startup_data). Now let's make a Thread class of +that.

+
+

A simple Thread class

+

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 pure +virtual  function code that is provided by the inherited +class. code is then similar to the thread_func +parameter of the BeginThread call, but is a full-blown member +function, not just a C function. So, we get this interface for the +Thread class:

class Thread {
+public:
+    virtual ~Thread();
+    void run();
+
+protected:
+    Thread();
+    virtual void code() = 0;
+
+private:
+    int running;
+
+    static void dispatch(void* thread_obj);
+};
+
+

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

+
+

Thread implementation

+

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 auto 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 +create for thread objects in each derived class:

Thread::Thread() 
+    : running(0) 
+{
+}
+
+DerivedThread& DerivedThread::create()
+{
+    return *new DerivedThread;
+}
+
+

create has to be added to every inherited class, returning an +object of that class.

+

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

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, dispatch is 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;
+}
+
+
+

A real Thread class

+

A real-world thread class has to consider a few things we have ignored here. +These things include:

+
    +
  1. more access to the thread data, like a method giving the thread ID. +
  2. a method for killing the thread, including the deletion of the thread + object.
+

Developed and tested on Windows NT, this is the source 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:

[\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
+
+

Have fun!

+

This article is Copyright © 1997-98 by Jürgen Hermann
and +Copyright © 1999 by C-Scene. All Rights Reserved.

+
+
+Copyright © 1997-2000 by C-Scene. All Rights Reserved.

Part of the +graphics and stylesheets used to generate this site are
Copyright © 1999-2000 +by Apache Software Foundation.