[c++-pthreads] Re: C++ and POSIX Threads Mailing List
Alexander Terekhov
TEREKHOV at de.ibm.com
Fri Dec 19 13:44:56 UTC 2003
Ted Baker wrote:
[...]
> I guess that for C++ you do want to preserve interoperability
> with C, up to some point. However, if you want good integration
> with exception handling, you may have to make some compromise
> like we did with Ada.
C++ should simply adopt <pthread.h> as <cthread> and introduce
"better" <thread>. To me, threaded-C is nothing but "a little
bit castrated" threaded-C++, I mean... (just an illustration,
nothing real)
typedef std::thread * pthread_t; // e.g.
#define PTHREAD_CANCELED std::thread_canceled()
struct thread_canceled {
operator void * () { return &unique; }
static thread_canceled unique;
};
class thread_termination_request : public std::exception ...
class thread_cancel_request : public std::thread_termination_request ...
class thread_exit_request : public std::thread_termination_request ...
template<typename T> class thread_exit_value : public
std::thread_exit_request ...
extern "C" pthread_t pthread_self() throw() {
return std::thread_self().raw_ptr();
}
extern "C" void pthread_exit(void * ptr)
throw(std::thread_termination_request) {
ptr == PTHREAD_CANCELED ? std::thread_cancel() :
std::thread_exit(ptr);
}
template<typename T>
void thread_exit(T value) {
assert(std::thread_self().can_exit_with<T>());
throw thread_exit_value(value);
}
template<>
void thread_exit(std::thread_canceled) {
thread_cancel();
}
void thread_cancel() {
throw std::thread_cancel_request();
}
struct no_cleanup {
void operator()(void *) {
// NOOP
}
};
template<typename cleanup>
bool no_TSD_cleanup(const cleanup &) throw() {
return false;
}
template<>
bool no_TSD_cleanup(const no_cleanup &) throw() {
return true;
}
template<typename T, typename cleanup>
class thread_specific_ptr : cleanup /* noncopyable */ {
_TSD_key_t _key;
static void dtor(void * data, void * THIS) {
static_cast<thread_specific_ptr *>(THIS)->
operator()(static_cast<T *>(data));
}
public:
thread_specific_ptr()
throw(std::bad_alloc, std::try_again);
thread_specific_ptr(const cleanup&)
throw(std::bad_alloc, std::try_again);
~thread_specific_ptr() throw();
T * get() throw();
void set(T *) throw(std::bad_alloc);
T * operator->() throw();
T * release() throw();
void dispose() throw();
void reset(T *) throw(std::bad_alloc);
};
template<typename T, typename cleanup>
thread_specific_ptr<T, cleanup>::thread_specific_ptr()
throw(std::bad_alloc, std::try_again) {
_tsd_key_create(&_key, no_TSD_cleanup(
*static_cast<cleanup *> (this)) ? 0 : &dtor, this);
}
template<typename T, typename cleanup>
thread_specific_ptr<T, cleanup>::thread_specific_ptr(
const cleanup& _cleanup) throw(std::bad_alloc,
std::try_again) : cleanup(_cleanup) {
_tsd_key_create(&_key, no_TSD_cleanup(
__cleanup) ? 0 : &dtor, this);
}
/* ... */
extern "C" typedef void (* _c_TSD_dtor_t)(void *);
extern "C++" typedef void (* _cpp_TSD_dtor_t)(void *);
struct _cthread_TSD_cleanup {
_cthread_TSD_cleanup(_c_TSD_dtor_t _c_TSD_dtor_) :
_func(_c_TSD_dtor_ ? c : null),
_c_TSD_dtor(_c_TSD_dtor_) {
}
_cthread_TSD_cleanup(_cpp_TSD_dtor_t _cpp_TSD_dtor_) :
_func(_cpp_TSD_dtor_ ? cpp : null),
_cpp_TSD_dtor(_cpp_TSD_dtor_) {
}
void operator()(void * _data) {
if (_data) switch(_func) {
case c: _c_TSD_dtor(_data); break;
case cpp: _cpp_TSD_dtor(_data); break;
}
}
enum { null, c, cpp } _func;
union {
_c_TSD_dtor_t _c_TSD_dtor;
_cpp_TSD_dtor_t _cpp_TSD_dtor;
};
};
template<>
bool no_TSD_cleanup(const _cthread_TSD_cleanup & _cleanup)
throw() {
return _cleanup._func == _cthread_TSD_cleanup::null;
}
typedef std::thread_specific_ptr<void, _cthread_TSD_cleanup> *
pthread_key_t;
// try { throw; } catch... "idiom"
int _translate_exception_to_error_code() throw();
extern "C" int pthread_key_create(pthread_key_t * key,
void ( * dtor)(void *)) throw() {
try {
*key = new std::thread_specific_ptr<void,
_cthread_TSD_cleanup>(_cthread_TSD_cleanup(dtor));
}
catch(...) {
return _translate_exception_to_error_code();
}
return 0;
}
extern "C++" int pthread_key_create(pthread_key_t * key,
void ( * dtor)(void *)) throw() {
try {
*key = new std::thread_specific_ptr<void,
_cthread_TSD_cleanup>(_cthread_TSD_cleanup(dtor));
}
catch(...) {
return _translate_exception_to_error_code();
} return 0;
}
extern "C" int pthread_key_delete(pthread_key_t key)
throw() {
delete key;
return 0;
}
extern "C" void * pthread_getspecific(pthread_key_t key)
throw() {
return key->get();
}
extern "C" int pthread_setspecific(pthread_key_t key,
const void * p) throw() {
try {
key->set(const_cast<void *>(p));
}
catch(...) {
return _translate_exception_to_error_code();
}
return 0;
}
extern "C" int pthread_resetspecific(pthread_key_t key,
const void * p) throw() {
try {
key->reset(const_cast<void *>(p));
}
catch(...) {
return _translate_exception_to_error_code();
}
return 0;
}
extern "C" void * pthread_releasespecific(pthread_key_t key)
throw() {
return key->release();
}
extern "C" void pthread_disposespecific(pthread_key_t key)
throw() {
return key->dispose();
}
// PODs
typedef std::aligned_storage<std::mutex> pthread_mutex_t;
typedef std::aligned_storage<std::mutexattr_t> pthread_mutexattr_t;
#define PTHREAD_MUTEX_INITIALIZER { /* magic */ }
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
extern "C" int pthread_mutex_init(pthread_mutex_t * mutex_storage,
const pthread_mutexattr_t * attr_storage) throw() {
try {
attr_storage ? new (mutex_storage->place())
std::mutex(attr_storage->object()) :
new (mutex_storage->place())
std::mutex();
}
catch(...) { // see ES of mutex::mutex(/*...*/)
return _translate_exception_to_error_code();
}
return 0;
}
extern "C" int pthread_mutex_lock(pthread_mutex_t * m) throw() {
try {
m->object().acquire();
}
catch(...) { // see ES of mutex::acquire()
return _translate_exception_to_error_code();
}
return 0;
}
extern "C" int pthread_mutex_destroy(pthread_mutex_t * m) throw() {
m->object().~mutex();
return 0;
}
typedef aligned_storage< once_call< void > > pthread_once_t;
#define PTHREAD_ONCE_INIT { /* magic */ }
extern "C" int pthread_once(pthread_once_t * once_control,
void (* init_routine)()) {
once_control->object()(init_routine);
return 0;
}
extern "C++" int pthread_once(pthread_once_t * once_control,
void (* init_routine)()) {
once_control->object()(init_routine);
return 0;
}
and so forth (or something like that ;-) ). See also
http://groups.google.com/groups?selm=3ECB8F71.689E551C%40web.de
regards,
alexander.
More information about the c++-pthreads
mailing list