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
00102 bool wait( OSMutexBase &mtx, CleanupItem guard ) {
00103 int res;
00104 OSMutexPthread *posmux = static_cast<OSMutexPthread *>( &mtx );
00105 if ( guard.first != 0 ) {
00106 pthread_cleanup_push( wefts_pthread_cond_guard, &guard );
00107 res = (pthread_cond_wait( &m_cond, &( posmux->m_mutex ) ) == 0);
00108 pthread_cleanup_pop( 0 );
00109 }
00110 else
00111 res = (pthread_cond_wait( &m_cond, &( posmux->m_mutex ) ) == 0);
00112 return res;
00113 }
00114
00116 bool timedWait( OSMutexBase &mtx, long seconds, long nanoseconds,
00117 CleanupItem guard ) {
00118 int res;
00119 struct timeval now;
00120 struct timespec timeout;
00121 OSMutexPthread *posmux = static_cast<OSMutexPthread *>( &mtx );
00122
00123 gettimeofday(&now, NULL);
00124 timeout.tv_sec = now.tv_sec + seconds;
00125 timeout.tv_nsec = now.tv_usec * 1000 + nanoseconds;
00126
00127 if ( guard.first != 0 ) {
00128 pthread_cleanup_push( wefts_pthread_cond_guard, &guard );
00129 res = ( pthread_cond_timedwait( &m_cond, &( posmux->m_mutex ), &timeout ) == 0);
00130 pthread_cleanup_pop( 0 );
00131 }
00132 else
00133 res = ( pthread_cond_timedwait( &m_cond, &( posmux->m_mutex ), &timeout ) == 0);
00134
00135 return res;
00136 }
00137
00138 };
00139
00143 class OSThreadPthread: public OSThreadBase {
00144 private:
00146 pthread_t m_thid;
00148 bool m_valid;
00149
00150 public:
00151 OSThreadPthread(): OSThreadBase() { invalidate(); }
00152 OSThreadPthread( bool val ): OSThreadBase( val ) { setCurrent(); }
00153
00154 bool start( void *(*func)(void *), void *data ) {
00155 return (pthread_create( &m_thid, 0, func, data ) == 0);
00156 }
00157
00158 bool stop() { return (pthread_cancel( m_thid ) == 0); }
00159
00160 void *join() throw( NotJoinableError ) {
00161 void *ret;
00162 int retval = pthread_join( m_thid, &ret );
00163 if ( retval != 0 ) throw NotJoinableError( retval );
00164 return ret;
00165 }
00166
00167 int enableCancel(){
00168 int old_state;
00169 if ( pthread_setcancelstate( PTHREAD_CANCEL_ENABLE , &old_state ) == 0)
00170 return old_state;
00171 return -1;
00172 }
00173
00174 int disableCancel() {
00175 int old_state;
00176 if ( pthread_setcancelstate( PTHREAD_CANCEL_DISABLE , &old_state ) == 0)
00177 return old_state;
00178 return -1;
00179 }
00180
00181 bool setCancelState( int state ) {
00182 return (pthread_setcancelstate( state , 0 ) == 0);
00183 }
00184
00185 void testCancel() { pthread_testcancel(); }
00186 void setCancelDeferred(){pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, 0 );}
00187 void detach() { pthread_detach( m_thid ); }
00188 void exit( void *data ) { pthread_exit( data ); }
00189
00190 bool same() const {
00191 return (m_valid && pthread_equal( pthread_self(), m_thid ));
00192 }
00193
00194 bool equal( const OSThreadBase &th ) const {
00195 const OSThreadPthread *other = static_cast<const OSThreadPthread *>( &th );
00196 return (m_valid && other->m_valid &&
00197 pthread_equal( other->m_thid, m_thid ) );
00198 }
00199
00200 virtual bool setCurrent() { m_thid = pthread_self(); m_valid=true;}
00201
00202 virtual void invalidate() { m_valid = false; }
00203 };
00204
00206 class OSSpecificDataPthread: public OSSpecificDataBase
00207 {
00208 private:
00209 pthread_key_t m_data;
00210
00211 public:
00215 OSSpecificDataPthread() throw( InitError )
00216 :OSSpecificDataBase()
00217 {
00218 int res = pthread_key_create( &m_data, 0 );
00219 if ( res != 0 ) throw InitError( res );
00220 }
00221
00226 ~OSSpecificDataPthread() { pthread_key_delete( m_data ); }
00227
00228 void *data() const { return pthread_getspecific( m_data ); }
00229
00230 void data(const void *dt) { pthread_setspecific( m_data, dt ); }
00231 };
00232
00234 inline void OSPushCleanupAndExecute(
00235 void (*runner)(void *),
00236 void (*cleaner)(void *),
00237 void *data )
00238 {
00239 pthread_cleanup_push( cleaner, data );
00240 runner( data );
00241 pthread_cleanup_pop( 1 );
00242 }
00243
00244
00245 typedef OSSpecificDataPthread OSSpecificData;
00246 typedef OSThreadPthread OSThread;
00247 typedef OSConditionPthread OSCondition;
00248 typedef OSMutexPthread OSMutex;
00249
00251 }
00252
00253 #endif
00254
00255