LINUX TIPS AND TRICKS --- August 25, 2000

Published by ITworld.com, the IT problem-solving network
http://www.itworld.com/newsletters

*********************************************************************

Executing a member function in a separate thread
by Danny Kalev

Existing thread libraries were designed to handle C functions, not C++ 
class member functions. Such libraries (e.g., pthreads) usually provide 
an API function that takes a pointer to a callback function and invokes 
it in a separate thread. The problem: you can't execute an object's 
member function in a separate thread using these libraries. Therefore, 
the following code doesn't compile:

/*a typical thread library API*/
int thr_create (void (*pf)(), void* prm, thread_t* pth);

#include "class1.h"
int func (void *param )
{
 thread_t t1;
 return thr_create ( &class1::some_method, param, &t1); /* compilation
error*/
}

The function thr_create() takes an address of a callback function, a 
list of arguments for the callback function passed as void*, and a 
pointer to thread_t. The code won't compile because the first argument 
is a pointer to a member function of class1. Ordinary functions and 
member functions are entirely different constructs in C++. Is there a 
workaround?

Static Member Functions
Unlike an ordinary member function, a static member function doesn't 
take an implicit "this" argument. Therefore, you can take its address 
and treat it as a pointer to an ordinary function. However, sometimes 
you can't make the member function static (e.g., when the member 
function is virtual or if you're using a third-party class). 
Fortunately, there is a way to get around this too. 

Nonstatic Member Functions
Suppose you want to invoke Hack::func2(), a nonstatic member function of 
class Hack, in a separate thread. Instead of directly passing 
&Hack::func2 to thr_create(), declare an ordinary function that takes 
void*:

void intermediary(void*);

Next, create a struct that packs a pointer to the member function in 
question and a pointer to the class:

struct A
{
 void (Hack::*pmf)(); /*pointer to a member function*/ 
 Hack * p;
};

Create an instance of A and fill it:

A a; 
Hack h;
/*fill struct*/
a.pmf = &Hack::func2; /*take address of member function*/
a.p = & h; 

The body of intermediary() looks like this:

void intermediary(void* ptr)
{
 A* pa=(A*) ptr; /*cast p to A* */
 void (Hack::*pmf)()=pa->pmf; /*extract ptr to member func*/
 Hack* ph=pa->p; /*extract address of Hack object*/
 (ph->*pmf)(); /*call member function*/
}

Finally, pass the address of intermediary() to thr_create() as its first
argument:

thr_create (intermediary, (void*) &a, &t1 );

thr_create() invokes the function intermediary() and passes a's address 
to it. intermediary() in turn unpacks the A struct from its void* 
argument and invokes the desired member function. This technique enables 
you to safely launch a member function in a separate thread even if your 
thread library doesn't support member functions directly.

Resources

Threads libraries in Solaris 
New features for developing multi-threaded code 
http://www.sunworld.com/sunworldonline/swol-06-2000/swol-06-insidesolaris.html

RADical developments for Linux 
Kylix comes knocking; Lazarus lurks 
http://www.linuxworld.com/linuxworld/lw-2000-07/lw-07-newslint_1.html

************************************************************************ 

About the author
----------------
Danny Kalev is a system analyst and software engineer with more
than 10 years of experience, specializing in C++ and
object-oriented analysis and design on various platforms including
VMS, DOS, Windows, Unix, and Linux. His technical interests involve
code optimization, networking, and distributed computing. He is
also a member of the ANSI C++ standardization committee and the
author of ANSI/ISO C++ Professional Programmer's Handbook (Que,
1999). Contact him at linuxnl@excite.com.

*********************************************************************

CUSTOMER SERVICE

You can subscribe or unsubscribe to any of your e-mail newsletters by 
updating your form at: 
http://www.itworld.com/cgi-bin/w3-msql/newsletters/subcontent12.html?

For subscription changes that cannot be handled via the web, please send 
an email to our customer service dept: support@itworld.com

*********************************************************************

CONTACTS

* For editorial comments, write Andrew Santosusso, Associate Editor, 
Newsletters at: andrew_santosusso@itworld.com
* For advertising information, write Dan Chupka, Account Executive at:
dan_chupka@itworld.com
* For recruitment advertising information, write Jamie Swartz, Eastern
Regional Sales Manager at: jamie_swartz@itworld.com or Paul Duthie,
Western Regional Sales Manager at: paul_duthie@itworld.com
* For all other inquiries, write Jodie Naze, Product Manager,
Newsletters at: jodie_naze@itworld.com

*********************************************************************

Copyright 2000 ITworld.com, Inc., All Rights Reserved. 

http://www.itworld.com