Computer Chess Club Archives


Search

Terms

Messages

Subject: WaitforSingleObject in linux (source code)

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.