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.