00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "LOW_thread_Factory.h"
00019 #include "LOW_thread_thread_POSIX.h"
00020 #include "LOW_helper_msglog.h"
00021
00022
00023 #include <errno.h>
00024 #include <pthread.h>
00025 #include <signal.h>
00026
00027
00028
00029
00030
00031
00032
00033 LOW_thread_thread_POSIX::LOW_thread_thread_POSIX( LOW_thread_runable *inRunable,
00034 const LOW_thread_Factory::detachState_t inDetachState,
00035 const LOW_thread_Factory::schedPolicy_t inSchedPolicy,
00036 const LOW_thread_Factory::schedPrio_t inSchedPrio)
00037 {
00038 createSyncMutex = LOW_thread_Factory::new_mutex( LOW_thread_mutex::mutexKind_errorCheck);
00039
00040 myRunable = inRunable;
00041
00042 if ( int errVal=pthread_attr_init( &initAttr) != 0 )
00043 throw thread_thread_error( errVal, "pthread_attr_init() failed", __FILE__, __LINE__);
00044
00045 switch ( inDetachState ) {
00046 case LOW_thread_Factory::detachState_joinable:
00047 if ( int errVal=pthread_attr_setdetachstate( &initAttr, PTHREAD_CREATE_JOINABLE) != 0 )
00048 throw thread_thread_error( errVal, "pthread_attr_setdetachstate() failed", __FILE__, __LINE__);
00049 break;
00050 case LOW_thread_Factory::detachState_detached:
00051 if ( int errVal=pthread_attr_setdetachstate( &initAttr, PTHREAD_CREATE_DETACHED) != 0 )
00052 throw thread_thread_error( errVal, "pthread_attr_setdetachstate() failed", __FILE__, __LINE__);
00053 break;
00054 case LOW_thread_Factory::detachState_default:
00055 break;
00056 default:
00057 throw thread_thread_error( "internal error: unknown value of detachState_t", __FILE__, __LINE__);
00058 }
00059
00060 switch ( inSchedPolicy ) {
00061 case LOW_thread_Factory::schedPolicy_regular:
00062 if ( int errVal=pthread_attr_setschedpolicy( &initAttr, SCHED_OTHER) != 0 )
00063 throw thread_thread_error( errVal, "pthread_attr_setschedpolicy() failed", __FILE__, __LINE__);
00064 break;
00065 case LOW_thread_Factory::schedPolicy_roundRobin:
00066 if ( int errVal=pthread_attr_setschedpolicy( &initAttr, SCHED_RR) != 0 )
00067 throw thread_thread_error( errVal, "pthread_attr_setschedpolicy() failed", __FILE__, __LINE__);
00068 break;
00069 case LOW_thread_Factory::schedPolicy_fifo:
00070 if ( int errVal=pthread_attr_setschedpolicy( &initAttr, SCHED_FIFO) != 0 )
00071 throw thread_thread_error( errVal, "pthread_attr_setschedpolicy() failed", __FILE__, __LINE__);
00072 break;
00073 case LOW_thread_Factory::schedPolicy_default:
00074 break;
00075 default:
00076 throw thread_thread_error( "internal error: unknown value of schedPolicy_t", __FILE__, __LINE__);
00077 }
00078
00079 if ( inSchedPrio != schedPrio_default ) {
00080 struct sched_param newSchedParam;
00081 newSchedParam.sched_priority = inSchedPrio;
00082 if ( int errVal=pthread_attr_setschedparam( &initAttr, &newSchedParam) != 0 )
00083 throw thread_thread_error( errVal, "pthread_attr_setschedparam() failed", __FILE__, __LINE__);
00084 }
00085
00086 isStarted = false;
00087 isTerminated = false;
00088 }
00089
00090
00091 LOW_thread_thread_POSIX::~LOW_thread_thread_POSIX()
00092 {
00093 pthread_cancel( threadID);
00094 pthread_join( threadID, NULL);
00095
00096 delete createSyncMutex;
00097
00098 if ( int errVal=pthread_attr_destroy( &initAttr) != 0 )
00099 LOW_helper_msglog::printPerror( errVal, "~LOW_thread_thread_POSIX: pthread_attr_destroy() failed");
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109 bool LOW_thread_thread_POSIX::getIsStarted() const
00110 {
00111 return isStarted;
00112 }
00113
00114
00115 bool LOW_thread_thread_POSIX::getIsTerminated() const
00116 {
00117 return isTerminated;
00118 }
00119
00120
00121 int LOW_thread_thread_POSIX::getReturnValue() const
00122 {
00123 if ( ! getIsStarted() )
00124 throw thread_thread_error( "thread was not started", __FILE__, __LINE__);
00125
00126 if ( ! getIsTerminated() )
00127 throw thread_thread_error( "thread not terminated yet", __FILE__, __LINE__);
00128
00129 return returnValue;
00130 }
00131
00132
00133 void LOW_thread_thread_POSIX::create()
00134 {
00135 if ( getIsStarted() )
00136 throw thread_thread_error( "thread already started", __FILE__, __LINE__);
00137
00138 LOW_thread_mutex::mutexLock theLock = LOW_thread_mutex::mutexLock( *createSyncMutex);
00139
00140 if ( int errVal=pthread_create( &threadID, &initAttr, threadRunner, this) != 0 )
00141 throw thread_thread_error( errVal, "pthread_create() failed", __FILE__, __LINE__);
00142
00143 isStarted = true;
00144 }
00145
00146
00147 void LOW_thread_thread_POSIX::cancel()
00148 {
00149 if ( int errVal=pthread_cancel( threadID) != 0 )
00150 throw thread_thread_error( errVal, "pthread_cancel() failed", __FILE__, __LINE__);
00151 }
00152
00153
00154 int LOW_thread_thread_POSIX::join()
00155 {
00156 if ( int errVal=pthread_join( threadID, reinterpret_cast<void**>(&returnValue)) != 0 )
00157 throw thread_thread_error( errVal, "pthread_join() failed", __FILE__, __LINE__);
00158
00159 return returnValue;
00160 }
00161
00162
00163 void LOW_thread_thread_POSIX::detach()
00164 {
00165 if ( int errVal=pthread_detach( threadID) != 0 )
00166 throw thread_thread_error( errVal, "pthread_detach() failed", __FILE__, __LINE__);
00167 }
00168
00169
00170 void LOW_thread_thread_POSIX::setScheduling( const LOW_thread_Factory::schedPolicy_t inPolicy, const LOW_thread_Factory::schedPrio_t inPrio)
00171 {
00172 struct sched_param schedParams;
00173
00174 schedParams.sched_priority = inPrio;
00175 if ( int errVal=pthread_setschedparam( threadID, inPolicy, &schedParams) != 0 )
00176 throw thread_thread_error( errVal, "pthread_setschedparam() failed", __FILE__, __LINE__);
00177 }
00178
00179
00180 LOW_thread_Factory::schedPolicy_t LOW_thread_thread_POSIX::getSchedPolicy() const
00181 {
00182 int schedPolicy;
00183 struct sched_param schedParams;
00184
00185 if ( int errVal=pthread_getschedparam( threadID, &schedPolicy, &schedParams) != 0 )
00186 throw thread_thread_error( errVal, "pthread_getschedparam() failed", __FILE__, __LINE__);
00187
00188 return static_cast<LOW_thread_Factory::schedPolicy_t>(schedPolicy);
00189 }
00190
00191
00192 LOW_thread_Factory::schedPrio_t LOW_thread_thread_POSIX::getSchedPrio() const
00193 {
00194 int schedPolicy;
00195 struct sched_param schedParams;
00196
00197 if ( int errVal=pthread_getschedparam( threadID, &schedPolicy, &schedParams) != 0 )
00198 throw thread_thread_error( errVal, "pthread_getschedparam() failed", __FILE__, __LINE__);
00199
00200 return schedParams.sched_priority;
00201 }
00202
00203
00204 LOW_thread_Factory::cancelAttrib_t LOW_thread_thread_POSIX::getCancelAttrib() const
00205 {
00206 if ( ! getIsStarted() || getIsTerminated() )
00207 throw thread_thread_error( "thread not running", __FILE__, __LINE__);
00208
00209 return cancelAttrib;
00210 }
00211
00212
00213
00214
00215 void LOW_thread_thread_POSIX::thread_exit( const int inRetVal)
00216 {
00217 if ( ! pthread_equal( threadID, pthread_self()) )
00218 throw thread_thread_permission( "only the current thread is allowed to use thread_exit()", __FILE__, __LINE__);
00219
00220 pthread_exit( reinterpret_cast<void*>(inRetVal));
00221 }
00222
00223
00224 void LOW_thread_thread_POSIX::testCancel()
00225 {
00226 if ( ! pthread_equal( threadID, pthread_self()) )
00227 throw thread_thread_permission( "only the current thread is allowed to use testCancel()", __FILE__, __LINE__);
00228
00229 pthread_testcancel();
00230 }
00231
00232
00233 void LOW_thread_thread_POSIX::setCancelAttrib( const LOW_thread_Factory::cancelAttrib_t inCancelAttrib)
00234 {
00235 if ( ! pthread_equal( threadID, pthread_self()) )
00236 throw thread_thread_permission( "only the current thread is allowed to use setCancelState()", __FILE__, __LINE__);
00237
00238 cancelAttrib = inCancelAttrib;
00239
00240 switch ( inCancelAttrib ) {
00241 case LOW_thread_Factory::cancelAttrib_disable:
00242 if ( int errVal=pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL) != 0 )
00243 throw thread_thread_error( errVal, "pthread_setcancelstate() failed", __FILE__, __LINE__);
00244 break;
00245
00246 case LOW_thread_Factory::cancelAttrib_defered:
00247 if ( int errVal=pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, NULL) != 0 )
00248 throw thread_thread_error( errVal, "pthread_setcanceltype() failed", __FILE__, __LINE__);
00249 if ( int errVal=pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL) != 0 )
00250 throw thread_thread_error( errVal, "pthread_setcancelstate() failed", __FILE__, __LINE__);
00251 break;
00252
00253 case LOW_thread_Factory::cancelAttrib_async:
00254 if ( int errVal=pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0 )
00255 throw thread_thread_error( errVal, "pthread_setcanceltype() failed", __FILE__, __LINE__);
00256 if ( int errVal=pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL) != 0 )
00257 throw thread_thread_error( errVal, "pthread_setcancelstate() failed", __FILE__, __LINE__);
00258 break;
00259
00260 default:
00261 throw thread_thread_error( "internal error: unknown value of cancelAttrib_t", __FILE__, __LINE__);
00262 }
00263 }
00264
00265
00266
00267
00268
00269
00270
00271 void* LOW_thread_thread_POSIX::threadRunner( void *inLaunchMe)
00272 {
00273 LOW_thread_thread_POSIX *myThreadObj = static_cast<LOW_thread_thread_POSIX*>(inLaunchMe);
00274
00275
00276 LOW_thread_mutex::mutexLock theLock = LOW_thread_mutex::mutexLock( *myThreadObj->createSyncMutex);
00277
00278
00279 myThreadObj->setCancelAttrib( LOW_thread_Factory::cancelAttrib_async);
00280
00281
00282 sigset_t noSignals;
00283 sigemptyset( &noSignals);
00284 if ( int errVal=pthread_sigmask( SIG_SETMASK, &noSignals, NULL) != 0 )
00285 throw thread_thread_error( errVal, "pthread_sigmask() failed", __FILE__, __LINE__);
00286
00287 myThreadObj->returnValue = myThreadObj->myRunable->run( myThreadObj);
00288 myThreadObj->isTerminated = true;
00289
00290 return reinterpret_cast<void*>(myThreadObj->returnValue);
00291 }
00292
00293