X-Git-Url: https://git.llucax.com/z.facultad/75.42/plaqui.git/blobdiff_plain/636801b890ff84ae25747057e3d2c6074616f16e..f53d095dd5ffb5afacf5c6f9a23d6cf1985fc237:/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 @@ - - -
- | C-Scene Issues 1..9 Authors Algorithms Books Patterns Graphics Miscellaneous UNIX Web & XML Windows Feedback FAQs Changes Submissions |
- - |
by Jürgen Hermann
last updated 2001/08/02 (version
-1.1.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 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.
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.
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-world thread class has to consider a few things we have ignored here. -These things include:
-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.
+ | C-Scene Issues 1..9 Authors Algorithms Books Patterns Graphics Miscellaneous UNIX Web & XML Windows Feedback FAQs Changes Submissions |
+ + |
by Jürgen Hermann
last updated 2001/08/02 (version
+1.1.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 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.
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.
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-world thread class has to consider a few things we have ignored here. +These things include:
+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.