00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#ifndef WT_OS_PTHREAD_H
00024
#define WT_OS_PTHREAD_H
00025
00026
#include <wefts_cleanup.h>
00027
#include <wefts_os_base.h>
00028
#include <wefts_error.h>
00029
00030
#ifdef __extern_c
00031
extern "C" {
00032
#endif
00033
00034
#include <pthread.h>
00035
#include <sys/time.h>
00036
00037
#ifdef __extern_c
00038
}
00039
#endif
00040
00046
namespace Wefts {
00047
00055
void wefts_pthread_cond_guard(
void *param );
00056
void wefts_pthread_cond_reset(
void *param );
00057
00058 class OSMutexPthread:
public OSMutexBase {
00059
protected:
00060 pthread_mutex_t
m_mutex;
00061
00062
friend class OSConditionPthread;
00063
public:
00064 OSMutexPthread() throw(
InitError )
00065 :
OSMutexBase()
00066 {
00067
int res = pthread_mutex_init( &
m_mutex, NULL );
00068
if ( res != 0 )
throw InitError( res );
00069 }
00070
00071 ~OSMutexPthread() { pthread_mutex_destroy( &
m_mutex ); }
00072
00073 virtual inline void lock() { pthread_mutex_lock( &
m_mutex); }
00074
00075 virtual inline bool trylock() {
return (pthread_mutex_trylock( &
m_mutex) == 0); }
00076
00078 virtual inline void unlock() { pthread_mutex_unlock( &
m_mutex ); }
00079 };
00080
00085 class OSConditionPthread:
public OSConditionBase {
00086
private:
00087 pthread_cond_t
m_cond;
00088
00089
public:
00090 OSConditionPthread() throw(
InitError )
00091 :
OSConditionBase()
00092 {
00093
int res = pthread_cond_init( &
m_cond, NULL );
00094
if ( res != 0 )
throw InitError( res );
00095 }
00096
00097 ~OSConditionPthread() { pthread_cond_destroy( &
m_cond ); }
00098
00099 void signal() { pthread_cond_broadcast( &
m_cond ); }
00100 void signalOne() { pthread_cond_signal( &
m_cond ); }
00101
00103 bool wait(
OSMutexBase &mtx,
CleanupItem &guard ) {
00104
int res;
00105
OSMutexPthread *posmux = static_cast<OSMutexPthread *>( &mtx );
00106
if ( guard.
handler != 0 ) {
00107 pthread_cleanup_push(
wefts_pthread_cond_guard, &guard );
00108 res = (pthread_cond_wait( &
m_cond, &( posmux->
m_mutex ) ) == 0);
00109 pthread_cleanup_pop( 0 );
00110 }
00111
else
00112 res = (pthread_cond_wait( &
m_cond, &( posmux->
m_mutex ) ) == 0);
00113
return res;
00114 }
00115
00117 bool timedWait(
OSMutexBase &mtx,
long seconds,
long nanoseconds,
00118
CleanupItem &guard ) {
00119
int res;
00120
struct timeval now;
00121
struct timespec timeout;
00122
OSMutexPthread *posmux = static_cast<OSMutexPthread *>( &mtx );
00123
00124 gettimeofday(&now, NULL);
00125 timeout.tv_sec = now.tv_sec + seconds;
00126 timeout.tv_nsec = now.tv_usec * 1000 + nanoseconds;
00127
00128
if ( guard.
handler != 0 ) {
00129 pthread_cleanup_push(
wefts_pthread_cond_guard, &guard );
00130 res = ( pthread_cond_timedwait( &
m_cond, &( posmux->m_mutex ), &timeout ) == 0);
00131 pthread_cleanup_pop( 0 );
00132 }
00133
else
00134 res = ( pthread_cond_timedwait( &
m_cond, &( posmux->m_mutex ), &timeout ) == 0);
00135
00136
return res;
00137 }
00138
00139 };
00140
00144 class OSThreadPthread:
public OSThreadBase {
00145
private:
00147 pthread_t
m_thid;
00149 bool m_valid;
00150
00151
public:
00152 OSThreadPthread():
OSThreadBase() {
invalidate(); }
00153 OSThreadPthread(
bool val ):
OSThreadBase( val ) {
setCurrent(); }
00154
00155
virtual bool priority( OSPriority prio_class,
int boost = 0);
00156
00157 bool start(
void *(*func)(
void *),
void *data ) {
00158
return (pthread_create( &
m_thid, 0, func, data ) == 0);
00159 }
00160
00161 bool stop() {
return (pthread_cancel(
m_thid ) == 0); }
00162
00163 void *
join() throw(
NotJoinableError )
00164 {
00165
void *ret;
00166
int retval = pthread_join(
m_thid, &ret );
00167
if ( retval != 0 )
throw NotJoinableError( retval );
00168
return ret;
00169 }
00170
00171 int enableCancel()
00172 {
00173
int old_state;
00174
if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , &old_state ) == 0)
00175
return old_state;
00176
return -1;
00177 }
00178
00179 int disableCancel()
00180 {
00181
int old_state;
00182
if ( pthread_setcancelstate( PTHREAD_CANCEL_DISABLE , &old_state ) == 0)
00183
return old_state;
00184
return -1;
00185 }
00186
00187 bool setCancelState(
int state ) {
00188
return (pthread_setcancelstate( state , 0 ) == 0);
00189 }
00190
00191 virtual inline void *
osRun(
void * (*runner)(
void *),
void *data,
void (*cleaner)(
void *))
00192 {
00193
00194
ThreadAndReturn thret = { data, 0 };
00195 pthread_cleanup_push( cleaner, &thret );
00196 thret.
runReturn = runner( data );
00197 pthread_cleanup_pop( 1 );
00198
return thret.
runReturn;
00199 }
00200
00201
00202 void testCancel() { pthread_testcancel(); }
00203 void setCancelDeferred(){pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, 0 );}
00204 void detach() { pthread_detach(
m_thid ); }
00205 void exit(
void *data ) { pthread_exit( data ); }
00206
00207 bool same()
const {
00208
return (
m_valid && pthread_equal( pthread_self(),
m_thid ));
00209 }
00210
00211 bool equal(
const OSThreadBase &th )
const {
00212
const OSThreadPthread *other = static_cast<const OSThreadPthread *>( &th );
00213
return (
m_valid && other->
m_valid &&
00214 pthread_equal( other->
m_thid,
m_thid ) );
00215 }
00216
00217 virtual bool setCurrent() {
m_thid = pthread_self();
m_valid=
true;}
00218
00219 virtual void invalidate() {
m_valid =
false; }
00220 };
00221
00223 class OSSpecificDataPthread:
public OSSpecificDataBase
00224 {
00225
private:
00226 pthread_key_t
m_data;
00227
00228
public:
00232 OSSpecificDataPthread() throw(
InitError )
00233 :
OSSpecificDataBase()
00234 {
00235
int res = pthread_key_create( &
m_data, 0 );
00236
if ( res != 0 )
throw InitError( res );
00237 }
00238
00243 ~OSSpecificDataPthread() { pthread_key_delete(
m_data ); }
00244
00245 void *
data()
const {
return pthread_getspecific(
m_data ); }
00246
00247 void data(
const void *dt) { pthread_setspecific(
m_data, dt ); }
00248 };
00249
00253 typedef OSSpecificDataPthread OSSpecificData;
00254 typedef OSThreadPthread OSThread;
00255 typedef OSConditionPthread OSCondition;
00256 typedef OSMutexPthread OSMutex;
00257
00259 }
00260
00261
#endif
00262
00263