28 #ifndef HAVE_PTHREAD_MUTEXATTR_SETTYPE 29 extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr,
int __kind)
37 #define TBOLD "\x1B[1m" 39 #define RED "\x1B[31m" 40 #define GREEN "\x1B[32m" 41 #define BLUE "\x1B[34m" 42 #define CYAN "\x1B[36m" 43 #define YELLOW "\x1B[33m" 44 #define MAGENTA "\x1B[35m" 46 #define BGBLUE "\x1B[44m" 47 #define NORMAL "\x1B[0m" 48 #define CLEANS "\x1B[2J" 51 #define MERROR std::cerr << RED << "\r(E)\t"<< GREEN << __FILE__ << "," << __LINE__ << NORMAL << "\t" <<TBOLD<<__FUNCTION__<<NORMAL << "\t" 52 #define MINFO std::cout << BLUE << "\r(I)\t"<< GREEN << __FILE__ << "," << __LINE__ << NORMAL << "\t" <<TBOLD<<__FUNCTION__<<NORMAL << "\t" 53 #define MWARN std::cout << YELLOW << "\r(W)\t"<< GREEN << __FILE__ << "," << __LINE__ << NORMAL << "\t" <<TBOLD<<__FUNCTION__<<NORMAL << "\t" 61 MCS_DEBUG_SETUP(0,
"Synchro");
62 MCS_DEBUG_ENTER(NOARGS);
76 MCS_DEBUG_ENTER(NOARGS);
80 MCS_DEBUG_LEAVE(NOARGS);
91 MCS_DEBUG_ENTER( << isActive);
94 throw MCS_FATAL( MSG_CANT_SET_SYNCHRO_STATE );
96 if ((! isActive) && (setactive)) {
106 #ifdef HAVE_PTHREAD_MUTEX_RECURSIVE_NP 107 #define PTHREAD_MUTEX_RECURSIVE_VALUE PTHREAD_MUTEX_RECURSIVE_NP 108 #elif defined (HAVE_PTHREAD_MUTEX_RECURSIVE) 109 #define PTHREAD_MUTEX_RECURSIVE_VALUE PTHREAD_MUTEX_RECURSIVE 111 #define PTHREAD_MUTEX_RECURSIVE_VALUE PTHREAD_MUTEX_RECURSIVE 112 #error 'Unable to determine pthread mutex recursive value' 115 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_VALUE);
116 #ifdef HAVE_PTHREAD_MUTEXATTR_SETPROTOCOL 117 pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_NONE);
121 pthread_mutex_init(&mutex, NULL);
123 pthread_mutex_init(&mutex, &attr);
133 if ((isActive) && (! setactive)) {
134 int ret = pthread_mutex_destroy(&mutex);
138 isActive = setactive;
139 MCS_DEBUG_LEAVE( << isActive );
147 if (! isActive)
return true;
148 MCS_DEBUG_ENTER(NOARGS);
152 ret = pthread_mutex_lock(&mutex);
155 ret = pthread_mutex_trylock(&mutex);
159 struct timespec timeout;
160 unsigned int millisec, seconds;
161 millisec = to % 1000;
162 seconds = (
unsigned int) floor((
double) (to / 1000.0));
163 gettimeofday(&now, NULL);
164 timeout.tv_sec = now.tv_sec + seconds;
165 timeout.tv_nsec = now.tv_usec * 1000 + millisec * 1000000;
168 #if defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS - 200112L) >= 0L 169 ret = pthread_mutex_timedlock(&mutex, &timeout);
171 ret = pthread_mutex_lock(&mutex);
180 (ret == ETIMEDOUT) );
188 MCS_DEBUG_LEAVE(NOARGS);
196 if (! isActive)
return 0;
197 MCS_DEBUG_ENTER(<< Count);
200 ret = pthread_mutex_unlock(&mutex);
208 MCS_DEBUG_LEAVE(NOARGS);
284 MCS_DEBUG_ENTER(<< lid);
285 if (pthread_self() != lthrID){
295 MCS_DEBUG_LEAVE(<< lid);
320 { ((
Thread*) p)->final(); }
324 {
throw MCS_ERROR(MSG_METHOD_MUST_BE_OVERLOADED,
"Thread::run"); }
330 sprintf(buf,
"%d",
id);
331 string s =
"Notify from " + string(buf);
332 MCS_DEBUG(lid <<
" " << s.c_str());
342 ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
344 ret = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
348 ret = pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
357 ret = pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
359 ret = pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
362 pthread_testcancel();
364 ret = pthread_setcancelstate(old, NULL);
373 selfDelete = selfdelete;
386 MCS_DEBUG_ENTER(<< lid);
390 ret = pthread_create(<hrID, NULL, mcs::Thread::RunThread,
this);
393 throw MCS_FATAL(MSG_CALLING_PTHREAD_CREATE);
397 ret = pthread_detach(lthrID);
400 throw MCS_FATAL(MSG_CALLING_PTHREAD_CREATE);
408 MCS_DEBUG_LEAVE(<< lid);
413 void* mcs::Thread::RunThread(
void* args)
456 pthread_cleanup_pop(0);
469 pthread_detach(thr->
lthrID);
475 MWARN <<
" AUTO delete !!!! " << endl;
479 MWARN <<
" AUTO delete !!!! I survived !!" << endl;
485 if((
long int) thr->
lerror == 1){
486 MERROR <<
"Thread "<< thr->
id() <<
" Ohh lerror is 1? !"<< thr->
lerror << endl;
511 assert(pthread_self() != lthrID);
516 bool wasterminating = checkTerminating();
525 pthread_cancel(lthrID);
527 pthread_join(lthrID, NULL);
534 lparent->notify(lid,
this);
561 this->start_routine1 = start_routine;
562 this->start_routine2 = NULL;
571 this->start_routine1 = NULL;
572 this->start_routine2 = start_routine;
578 void mcs::ThreadFunc::run()
584 ret = (start_routine1)(arg);
587 lerror = (start_routine2)(arg);
594 int mcs::ThreadFunc::retcode()
605 struct timespec tt, tmp;
610 if (millisec >= 1000) {
611 tt.tv_sec = ((
long int) (millisec / 1000.0));
614 tt.tv_nsec = (millisec % 1000) * 1000000;
615 nanosleep(&tt, &tmp);
bool enter(int op=1, unsigned int timeout=0)
Enter, or try to enter a critical section.
bool checkTerminating()
Starting point for the separate thread.
virtual ~Thread()
Destructor.
int lid
General purpose Thread identifier.
bool tryenter(unsigned int timeout=0)
Wrapper around enter(), using op=MCS_SYNCHRO_TRY_LOCK if the parameter is 0, op=MCS_SYNCHRO_TRY_TIMED...
int id()
Returns the Thread object identificator.
virtual void notify(int id, Thread *ref)
A method called from child threads to notify their termination.
void startDetached(bool selfDelete=false)
Start a new thread in the detached state.
virtual void initial()
Initialization method.
void start()
Start a new thread in the joinable state.
void stop()
Stop thread execution.
#define MCS_STATE_END
Thread state: the separate thread had terminated its execution.
static void cleanup_Handler(void *This)
Static wrapper around final().
Event * lerror
Last error.
void synchronize(bool setactive)
Enable or disable the synchronization feature.
Hold informations about an event.
#define MCS_SYNCHRO_TRY_LOCK
To be used with Synchro.enter(): try to enter a critical section.
#define MCS_SYNCHRO_LOCK
To be used with Synchro.enter(): enter a critical section.
Thread * parent()
Returns the address of the parent.
int count()
Return how many times the current thread has locked the section.
pthread_t lthrID
System's thread identifier.
void sleep_ms(unsigned int millisec)
A millisecond resolution sleep function.
#define MCS_ERROR(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Event * error()
Return last error message.
#define MCS_STATE_CREATED
Thread state: the object has been created ut the separate thread has not been started.
#define MCS_SYNCHRO_TRY_TIMED
To be used with Synchro.enter(): try to enter a critical section with timeout facility.
ThreadFunc(int(*start_routine)(void *), void *arg)
Constructor, run a user function in a separate thread.
Thread * lparent
Reference to parent Thread object, if any is given in the constructor.
#define MCS_STATE_TERMINATING
Thread state: the exit() method is executing, the separate thread is going to execute the final() met...
Main include file for all MCS based applications.
int lstate
State of the object, see state() method.
#define MCS_STATE_RUNNING
Thread state: the separate thread is executing the run() method.
virtual void final()
Finalization method.
void set_cancel_state(bool cancel)
Set cancellation state for current thread.
void test_cancel()
Test if a cancellation request is pending.
A class to create separate threads.
bool selfDelete
Tell if the object should delete himself once the thread is terminated.
#define MCS_FATAL(A, rest...)
Facility to easily pass all necessary parameter to an Event constructor.
Thread(int id=0, Thread *parent=NULL)
Declared to avoid using of default copy constructor.
int state()
Return the state of the thread.
virtual void run()
Body of the thread execution.
int leave()
Leave a critical section.
Namespace for MCS library.