Hi,
I am looking into POSIX threads and thread-specific data, and I am
unclear how pthreads treats the main thread (or expects the main thread
to be treated). For instance, it seems perfectly legal to create
thread-specific data for the main thread. However, this data's
destructor function does not seem to be called unless the main thread
explicitly exits with pthread_exit(). I would have thought that a
multi-threaded application would have executed the clean-up handlers for
ALL threads. Worse still, on some platforms, exiting the main thread via
pthread_exit() means that certain static destructors aren't called.
This is my demo code (C++):
#include <cstring>
#include <iostream>
using namespace std;
#include <unistd.h>
#include <pthread.h>
extern "C"
{
static void cleanUp(void*);
void* thread_function(void*);
class ThreadSingleQuote:}
{
private:
ThreadSingle();
~ThreadSingle();
ThreadSingle(const ThreadSingle&);
ThreadSingle& operator=(const ThreadSingle&);
class Manager
{
public:
Manager();
~Manager();
};
static pthread_key_t key;
static Manager manager;
friend class Manager;
friend void cleanUp(void*);
public:
static ThreadSingle* Instance();
pthread_key_t ThreadSingle::key;Quote:};
ThreadSingle::Manager ThreadSingle::manager;
ThreadSingle::Manager::Manager()
{
pthread_key_create(&key, cleanUp);
cout << "Creating multi-threaded key: " << key << endl;
ThreadSingle::Manager::~Manager()Quote:}
{
/*
* Delete any data attached to the main thread ...
*/
void *p = pthread_getspecific(key);
if (p) cleanUp(p);
pthread_key_delete(key);
cout << "Deleted multi-threaded key: " << key << endl;
static voidQuote:}
cleanUp(void *p)
{
cout << "Calling clean-up with " << p << endl;
delete static_cast<ThreadSingle*>(p);
ThreadSingle*Quote:}
ThreadSingle::Instance()
{
ThreadSingle* ptr =
static_cast<ThreadSingle*>(pthread_getspecific(key));
if ( !ptr )
{
ptr = new ThreadSingle();
pthread_setspecific(key, ptr);
}
cout << "- ThreadSingle at " << ptr << endl;
return ptr;
ThreadSingle::ThreadSingle()Quote:}
{
cout << "Creating ThreadSingle" << endl;
ThreadSingle::~ThreadSingle()Quote:}
{
cout << "Destroying ThreadSingle" << endl;
void*Quote:}
thread_function(void *p)
{
cout << "In a thread: arg=" << p << endl;
ThreadSingle::Instance();
ThreadSingle::Instance();
sleep(1);
ThreadSingle::Instance();
ThreadSingle::Instance();
return p;
intQuote:}
main()
{
ThreadSingle::Instance();
pthread_t id;
if ( pthread_create(&id, NULL, thread_function,
reinterpret_cast<void*>(0x8080)) != 0 )
{
cout << "Could not create thread" << endl;
}
else
{
int ret;
ThreadSingle::Instance();
sleep(1);
ThreadSingle::Instance();
ThreadSingle::Instance();
void *status;
if ((ret = pthread_join(id, &status)) != 0)
{
cout << "Error: " << strerror(ret) << endl;
}
else
{
cout << "Thread returns: " << status << endl;
}
}
return 0;
The point here is to make sure that any instance of the class isQuote:}
destroyed whenever its thread exits, and I guess it all boils down to
whether it is legal for the main thread to call pthread_exit() or not. I
am hoping "not", because I can then safely destroy the object in the
Manager's static destructor. Note that this code also has to make
limited sense if compiled in single-threaded mode.
Can anyone advise me on this, please?
Cheers,
Chris