Often, as a C++ programmer, you may want to abstract the concept of a thread into a C++ class. To do this, you must realize that the Pthread APIs are C language APIs. The Pthread APIs use functions that have C linkage and calling conventions. For your application to successfully use the pthread functions, you must provide helper functions of the appropriate type and linkage for the Pthread APIs that take function pointers as parameters.
When sharing objects between threads, always be aware of which thread is manipulating the object, which thread is responsible for freeing the object, and what thread safety issues are created by sharing objects between threads.
The following example shows how to successfully create a program that abstracts a thread into a C++ class. It can be easily extended to provide a mechanism by which the thread creation and manipulation itself is also encapsulated into the class.
See Code disclaimer information for information pertaining to code examples.
/* This C++ example must be compiled with VisualAge C++ for OS/400 */ #define _MULTI_THREADED #include <stdio.h> #include <stdlib.h> #include <stddef.h> #include <pthread.h> class ThreadClass { public: ThreadClass(char *s) { data1 = 42; data2 = strlen(s); strncpy(str, s, sizeof(str)-1); str[49]=0; } void *run(void); private: int data1; int data2; char str[50]; }; extern "C" void *ThreadStartup(void *); int main(int argc, char **argv) { ThreadClass *t=NULL; pthread_t thread; int rc; // Use printf instead of cout. // At the time this test was written, the C++ standard class library // was not thread safe. printf("Entered test %s\n", argv[0]); printf("Create a ThreadClass object\n"); t = new ThreadClass("Testing C++ object/thread creation\n"); printf("Start a real thread to process the ThreadClass object\n"); // #define COMPILE_ERROR #ifdef COMPILE_ERROR // This is an ERROR. You cannot create a thread by using a pointer // to a member function. Thread creation requires a C linkage function. // If you remove the comments from the line `#define COMPILE_ERROR' // the compiler will give a message similar to this: // "ATESTCPP0.C", line 46.53: 1540-055: (S) "void*(ThreadClass::*)()" // cannot be converted to "extern "C" void*(*)(void*)". rc = pthread_create(&thread, NULL, ThreadClass::run, NULL); #else // Instead, this is the correct way to start a thread on a C++ object rc = pthread_create(&thread, NULL, ThreadStartup, t); #endif if (rc) { printf("Failed to create a thread\n"); exit(EXIT_FAILURE); } printf("Waiting for thread to complete\n"); rc = pthread_join(thread, NULL); if (rc) { printf("Failed to join to the thread, rc=%d\n"); exit(EXIT_FAILURE); } printf("Testcase complete\n"); exit(EXIT_SUCCESS); } // This function is a helper function. It has normal C linkage, and is // as the base for newly created ThreadClass objects. It runs the // run method on the ThreadClass object passed to it (as a void *). // After the ThreadClass method completes normally (i.e returns), // we delete the object. void *ThreadStartup(void *_tgtObject) { ThreadClass *tgtObject = (ThreadClass *)_tgtObject; printf("Running thread object in a new thread\n"); void *threadResult = tgtObject->run(); printf("Deleting object\n"); delete tgtObject; return threadResult; } void *ThreadClass::run(void) { printf("Entered the thread for object %.8x %.8x %.8x %.8x\n", this); printf("Object identity: %d, %d: %s\n", data1, data2, str); return NULL; }
Output
Entered test QP0WTEST/ACPPOBJ Create a ThreadClass object Start a real thread to process the ThreadClass object Waiting for thread to complete Running thread object in a new thread Entered the thread for object 80000000 00000000 d017dad2 57001f60 Object identity: 42, 35: Testing C++ object/thread creation Deleting object Testcase complete
Top | Pthread APIs | APIs by category |