Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members | Related Pages

LOW_thread_thread_POSIX.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           LOW_thread_thread_POSIX.cpp  -  description
00003                              -------------------
00004     begin                : Thu Oct 2 2003
00005     copyright            : (C) 2003 by Harald Roelle
00006     email                : roelle@informatik.uni-muenchen.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
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 // constructors
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 ) // fill initial attributes with default values
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);     // ignore errors
00094   pthread_join( threadID, NULL); // ignore errors
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 // methods
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); // lock until return
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 // private static methods
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   // synchronize with create() method to ensure everything is set up
00276   LOW_thread_mutex::mutexLock theLock = LOW_thread_mutex::mutexLock( *myThreadObj->createSyncMutex); // lock until return
00277 
00278   // set cancellation parameters
00279   myThreadObj->setCancelAttrib( LOW_thread_Factory::cancelAttrib_async);
00280 
00281   // block all signals in the new thread
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 

Generated on Tue Feb 3 11:30:26 2004 for OneWireLibrary++ by doxygen 1.3.2