]> git.llucax.com Git - z.facultad/75.42/plaqui.git/blob - docs/oo_callbacks_cpp/oo_callbacks_cpp.html
Mini bugfix.
[z.facultad/75.42/plaqui.git] / docs / oo_callbacks_cpp / oo_callbacks_cpp.html
1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2 <!-- saved from url=(0045)http://cscene.org/topics/misc/cs7-04.xml.html -->
3 <HTML><HEAD><TITLE>Callbacks in C++: The OO Way</TITLE>
4 <META content="text/html; charset=iso-8859-1" http-equiv=Content-Type><LINK 
5 href="default.css" rel=stylesheet 
6 type=text/css>
7 <META content="MSHTML 5.00.2920.0" name=GENERATOR></HEAD>
8 <BODY>
9 <TABLE width="100%">
10   <TBODY>
11   <TR>
12     <TD><A href="http://cscene.org/"><IMG alt="cscene logo" border=0 
13       class=logo height=52 src="logo.gif" 
14       width=120></A></TD>
15     <TD align=middle width="100%"><A 
16       href="http://cscene.org/index.html">C-Scene</A> <A 
17       href="http://cscene.org/issues.html">Issues 1..9</A> <A 
18       href="http://cscene.org/bios.html">Authors</A> <BR><A 
19       href="http://cscene.org/topics/algo.xml.html">Algorithms</A> <A 
20       href="http://cscene.org/topics/books.xml.html">Books</A> <A 
21       href="http://cscene.org/topics/patterns.xml.html">Patterns</A> <A 
22       href="http://cscene.org/topics/graphics.xml.html">Graphics</A> <A 
23       href="http://cscene.org/topics/misc.xml.html">Miscellaneous</A> <A 
24       href="http://cscene.org/topics/unix.xml.html">UNIX</A> <A 
25       href="http://cscene.org/topics/web.xml.html">Web &amp; XML</A> <A 
26       href="http://cscene.org/topics/windows.xml.html">Windows</A> <BR><A 
27       href="http://cscene.org/feedback.html">Feedback</A> <A 
28       href="http://cscene.org/faqs.html">FAQs</A> <A 
29       href="http://cscene.org/changes.html">Changes</A> <A 
30       href="http://cscene.org/submit.html">Submissions</A> </TD>
31     <TD>
32       <FORM action=http://www.google.com/search method=get><INPUT name=hl 
33       type=hidden value=en><INPUT name=safe type=hidden value=off><INPUT 
34       name=domains type=hidden value=cscene.org><INPUT name=sitesearch 
35       type=hidden value=cscene.org><INPUT maxLength=256 name=q size=31><INPUT name=btnG type=submit value=Search></FORM></TD></TR></TBODY></TABLE>
36 <H1 class=s1>Callbacks in C++: The OO Way</H1>
37 <DIV class=toc>
38 <H2 class=s2 id=N1698364>Content</H2>
39 <OL>
40   <LI><A href="http://cscene.org/topics/misc/cs7-04.xml.html#N7895983">What are 
41   Callbacks?</A>
42   <LI><A href="http://cscene.org/topics/misc/cs7-04.xml.html#N310499">A simple 
43   Thread class</A>
44   <LI><A href="http://cscene.org/topics/misc/cs7-04.xml.html#N7751758">Thread 
45   implementation</A>
46   <LI><A href="http://cscene.org/topics/misc/cs7-04.xml.html#N3038356">A real 
47   Thread class</A></LI></OL></DIV>
48 <DIV class=article>
49 <P>by <I>Jürgen Hermann</I><BR>last updated <I>2001/08/02</I> (version 
50 <I>1.1.1.1</I>)<BR>also available as <A 
51 href="http://cscene.org/topics/misc/cs7-04.xml.txt">XML</A></P>
52 <DIV class=s2>
53 <H2 class=s2 id=N7895983>What are Callbacks?</H2>
54 <P>Many operating systems and other subsystems (like GUI libraries) feature a 
55 special type of hook into those systems, named callbacks or callback functions. 
56 Upon initialization or by calling an API function you pass pointers to the 
57 callback into the subsystem, for later use. The problem with those functions is, 
58 since these subsystems are nowadays not yet OO, that they have no notion of what 
59 an object is. So if you want to have a <EM>callback object&nbsp;</EM> instead of 
60 a mere function, some OO magic is called for.</P>
61 <P>As an example, consider the <CODE>BeginThread</CODE> API that many OSes have 
62 in a quite similar form; we assume that it takes a pointer to the function that 
63 provides the actual code for the newly created thread plus a <EM>data 
64 pointer&nbsp;</EM> that is passed to that function as a startup parameter. Thus, 
65 we end up with <CODE>BeginThread (void (*thread_func) (void*), void* 
66 startup_data)</CODE>. Now let's make a <CODE>Thread</CODE> class of 
67 that.</P></DIV>
68 <DIV class=s2>
69 <H2 class=s2 id=N310499>A simple Thread class</H2>
70 <P>What we want to have is an ABC (abstract base class) that you can inherit 
71 from, creating specialized thread classes and in turn thread objects (i.e. 
72 actual threads). The code of the thread is located in a <EM>pure 
73 virtual&nbsp;</EM> function <CODE>code</CODE> that is provided by the inherited 
74 class. <CODE>code</CODE> is then similar to the <CODE>thread_func</CODE> 
75 parameter of the <CODE>BeginThread</CODE> call, but is a full-blown member 
76 function, not just a C function. So, we get this interface for the 
77 <CODE>Thread</CODE> class:</P><PRE class=source>class Thread {
78 public:
79     virtual ~Thread();
80     void run();
81
82 protected:
83     Thread();
84     virtual void code() = 0;
85
86 private:
87     int running;
88
89     static void dispatch(void* thread_obj);
90 };
91 </PRE>
92 <P>This might seem quite unusual to you (like having a protected constructor), 
93 but things will be explained in due course.</P></DIV>
94 <DIV class=s2>
95 <H2 class=s2 id=N7751758>Thread implementation</H2>
96 <P>When we put the thread concept into a class, we have to consider lifetime. A 
97 thread exists as long as the thread function does not return, thus the object 
98 has to have the same lifetime. Because of this, an <CODE>auto</CODE> thread 
99 object does not make much sense; we insure that every thread object exists on 
100 the heap by making the ctor protected and providing a static factory method 
101 <CODE>create</CODE> for thread objects in each derived class:</P><PRE class=source>Thread::Thread() 
102     : running(0) 
103 {
104 }
105
106 DerivedThread&amp; DerivedThread::create()
107 {
108     return *new DerivedThread;
109 }
110 </PRE>
111 <P><CODE>create</CODE> has to be added to every inherited class, returning an 
112 object of that class.</P>
113 <P>Next, we need a <CODE>run</CODE> method that actually starts the thread. This 
114 can't be done in the ctor: when <CODE>code</CODE> would be registered as a 
115 thread of execution in the <EM>base class&nbsp;</EM> ctor, the superclass would 
116 not yet be fully created and calling <CODE>code</CODE> would be quite invalid 
117 and dangerous. <CODE>run</CODE> does its job by registering the 
118 <CODE>dispatch</CODE> function as a thread, giving that thread the object 
119 pointer as a startup parameter; since <CODE>dispatch</CODE> is static, it has a 
120 prototype that matches the <CODE>void(*)(void*)</CODE> parameter of 
121 <CODE>BeginThread</CODE>.</P><PRE class=source>void Thread::run()
122 {
123     // Don't start two threads on the same object
124     if (running) return;
125
126     // Create an OS thread, using the static callback
127     BeginThread(Thread::dispatch, this);
128     running = 1;
129 }
130 </PRE>
131 <P>So finally, <CODE>dispatch</CODE> is called and performs the step from a 
132 procedural callback to the callback object:</P><PRE class=source>void Thread::dispatch(void* thread_obj)
133 {
134     // Call the actual OO thread code
135     ((Thread*)thread_obj)-&gt;code();
136
137     // After code() returns, kill the thread object
138     delete (Thread*)thread_obj;
139 }
140 </PRE></DIV>
141 <DIV class=s2>
142 <H2 class=s2 id=N3038356>A real Thread class</H2>
143 <P>A real-world thread class has to consider a few things we have ignored here. 
144 These things include: </P>
145 <OL class=userlist>
146   <LI>more access to the thread data, like a method giving the thread ID. 
147   <LI>a method for killing the thread, including the deletion of the thread 
148   object. </LI></OL>
149 <P>Developed and tested on Windows NT, this is the <A 
150 href="../../tests/oo_thread.cpp">source</A> for a little 
151 example program that implements the above in the real world. If you run it, you 
152 get something similar to the following output:</P><PRE class=source>[\cscene\callback]callback
153 Started thread #80 for dice1
154 Started thread #84 for dice2
155 dice1 rolled 1
156 dice2 rolled 1
157 dice2 rolled 3
158 dice1 rolled 1
159 dice2 rolled 4
160 dice1 rolled 6
161 dice1 rolled 3
162 dice2 rolled 3
163 dice1 rolled 1
164 dice1 rolled 4
165 dice2 rolled 4
166 dice2 rolled 3
167 dice1 rolled 1
168 dice2 rolled 6
169 dice1 rolled 2
170 dice2 rolled 2
171 dice1 rolled 1
172 dice2 rolled 4
173 dice2 rolled 1
174 dice1 rolled 4
175 dice1 rolled 5
176 dice2 rolled 1
177 dice1 rolled 3
178 dice2 rolled 3
179 dice1 rolled 2
180 dice1 rolled 6
181 dice2 rolled 2
182 dice1 rolled 1
183 dice2 rolled 3
184 dice1 rolled 4
185 dice1 rolled 5
186 dice2 rolled 3
187 dice2 rolled 6
188 dice1 rolled 4
189 </PRE>
190 <P>Have fun!</P></DIV>
191 <P><SMALL><EM>This article is Copyright © 1997-98 by Jürgen Hermann<BR>and 
192 Copyright © 1999 by C-Scene. All Rights Reserved. </EM></SMALL></P></DIV>
193 <DIV class=lastwords>
194 <HR>
195 Copyright © 1997-2000 by C-Scene. All Rights Reserved.<BR><BR>Part of the 
196 graphics and stylesheets used to generate this site are<BR>Copyright © 1999-2000 
197 by Apache Software Foundation. </DIV></BODY></HTML>