Re: [c++-pthreads] Re: C++ and POSIX Threads Mailing List
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [c++-pthreads] Re: C++ and POSIX Threads Mailing List



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.