Author: Hristo
Date: 14:34:59 04/25/01
Go up one level in this thread
Following is a code that you can use for locking and or signaling stuff in linux. This is the same as WaitForSingleObject ... Example: // create a locked semaphore // with maximum of 1 lock (non counting) CSISemaphore g_sem(0,1); void thread_func(){ while (1){ // do something // signal the semaphore that we are done // you can unlock it any number of times ... // it is not counting semaphore so nothing bad happens g_sem.unlock(); } } // // int main(){ start_my_thread(thread_func); while(1){ // wait 100 ms for the semaphore to get signaled (unlocked) if (g_sem.lock(100)){ cout << "The semaphore was signaled..." << endl; break; /// .... }else{ cout << "." << flush; } } return 0; } This is the actual header and source stuff that you need. best regards. hristo --- header file --- /** * General purpose semaphore interface * Under unix there we are using mutex and * conditional variable to provide lock with * timeout. Since the lock with timeout is * not supported natively by the OS there are * some special issues that might occur. For * instance if the timeout value is not large * enough the thread might never accuire the * lock. * * @author Hristo Doichev * @version 0.1 */ class CSISemaphore{ public: /** * create a single semaphore. * * @param _initial determines the initial state of the semaphore. * 0 the semaphore is created and locked immediately. * 1 the semaphore is not locked within the constructor. * @return */ explicit CSISemaphore(unsigned int _initial); /** * create a counting Semaphore. * * @param _initial determines the amount of locks that can be applied to this semaphore * after the cnstruction. * 0 the semaphore is completely locked. * n <= _max is the number of loks that can be applied * @param _max the maximum number of locks this semaphore can take * * @return */ explicit CSISemaphore(unsigned int _initial, unsigned int _max); virtual ~CSISemaphore(); virtual bool check(); virtual void lock(); virtual void unlock(); virtual bool lock(unsigned int _time_out); private: pthread_mutex_t m_mut; pthread_cond_t m_con; int m_con_var; int m_max_locks; }; --- source --- #include THE_HEADER_FILE_ABOVE #include <errno.h> #include <unistd.h> #include <sys/time.h> #include <iostream> #define CSI_PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, {0, 0}} /** purpose: create a single lock semaphore */ CSISemaphore::CSISemaphore(unsigned int _initial):m_con_var(_initial),m_max_locks(1) { m_mut.__m_count = 0; m_mut.__m_lock.__spinlock = 0; m_mut.__m_lock.__status = 0; m_mut.__m_owner = 0; m_mut.__m_reserved = 0; m_mut.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; //m_mut = {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, {0, 0}}; pthread_mutex_init(&m_mut, 0); pthread_cond_init(&m_con, 0); } /** purpose: create a counting Semaphore */ CSISemaphore::CSISemaphore(unsigned int _initial, unsigned int _max):m_con_var(_initial),m_max_locks(_max) { m_mut.__m_count = 0; m_mut.__m_lock.__spinlock = 0; m_mut.__m_lock.__status = 0; m_mut.__m_owner = 0; m_mut.__m_reserved = 0; m_mut.__m_kind = PTHREAD_MUTEX_RECURSIVE_NP; //m_mut = {0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, {0, 0}}; pthread_mutex_init(&m_mut, 0); pthread_cond_init(&m_con, 0); if (m_con_var > m_max_locks) { m_con_var = m_max_locks; } } /** */ CSISemaphore::~CSISemaphore(){ pthread_mutex_destroy(&m_mut); pthread_cond_destroy(&m_con); } /** */ bool CSISemaphore::check(){ bool is_not_locked; pthread_mutex_lock(&m_mut); if (m_con_var > 0) { is_not_locked = true; }else{ is_not_locked = false; } pthread_mutex_unlock(&m_mut); return is_not_locked; } /** */ void CSISemaphore::lock(void){ pthread_mutex_lock(&m_mut); if (m_con_var == 0) { do { pthread_cond_wait(&m_con, &m_mut); } while ( m_con_var == 0); } --m_con_var;// = 0; pthread_mutex_unlock(&m_mut); } /** */ void CSISemaphore::unlock(void){ pthread_mutex_lock(&m_mut); ++m_con_var;// = 1; if (m_con_var > m_max_locks) { m_con_var = m_max_locks; } pthread_mutex_unlock(&m_mut); pthread_cond_signal(&m_con); //sched_yield(); } /** * This is perhaps the most complicatied of all sync functions. * The general unix pthread library does not support timeouts on * mutexes and therefore we need to use conditional variables. * However, the conditional variables do not guarantee smooth * execution. There are many conditions which can cause problems. * * _time_out in ms */ bool CSISemaphore::lock(unsigned int _time_out){ bool got_a_lock = false; unsigned int status = 0; struct timespec timeout; struct timeval start_time; // lock the mutex so we can check the predicate pthread_mutex_lock(&m_mut); // if someone has the predicate the wait on the condition variable TRY_TO_WAIT: if (m_con_var == 0) { gettimeofday(&start_time,0); //cout << " sec: " << start_time.tv_sec << ", usec: " << start_time.tv_usec << endl; unsigned int sec_delta = _time_out/1000; timeout.tv_sec = start_time.tv_sec + (sec_delta); timeout.tv_nsec = start_time.tv_usec + (_time_out-(sec_delta*1000))*100000; //cout << "> sec: " << timeout.tv_sec << ", usec: " << timeout.tv_nsec << endl; status = pthread_cond_timedwait(&m_con, &m_mut, &timeout); } if (m_con_var > 0) { --m_con_var;// = 0; got_a_lock = true; }else{ if (status == ETIMEDOUT) { got_a_lock = false; cout << "timed wait status:" << status << endl; }else{ unsigned int temp_time = (time(0) - timeout.tv_sec); if ((_time_out/1000) > temp_time ) { _time_out -= (temp_time*1000); cout << ">> retry lock( " << _time_out << " )" << endl; goto TRY_TO_WAIT; } } } // unlock the mutex so others can do their job (and wait) pthread_mutex_unlock(&m_mut); return got_a_lock; }
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.