158 lines
5.7 KiB
C++
158 lines
5.7 KiB
C++
// Windows/Synchronization.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "Synchronization.h"
|
|
|
|
// #define TRACEN(u) u;
|
|
#define TRACEN(u) /* */
|
|
|
|
#define MAGIC 0x1234CAFE
|
|
class CSynchroTest
|
|
{
|
|
int _magic;
|
|
public:
|
|
CSynchroTest() {
|
|
_magic = MAGIC;
|
|
}
|
|
void testConstructor() {
|
|
if (_magic != MAGIC) {
|
|
printf("ERROR : no constructors called during loading of plugins (please look at LINK_SHARED in makefile.machine)\n");
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
}
|
|
};
|
|
|
|
static CSynchroTest gbl_synchroTest;
|
|
|
|
extern "C" void sync_TestConstructor(void) {
|
|
gbl_synchroTest.testConstructor();
|
|
}
|
|
|
|
|
|
namespace NWindows {
|
|
namespace NSynchronization {
|
|
|
|
|
|
#ifndef ENV_BEOS
|
|
#ifdef DEBUG_SYNCHRO
|
|
void CSynchro::dump_error(int ligne,int ret,const char *text,void *param)
|
|
{
|
|
printf("\n##T%d#ERROR2 (l=%d) %s : param=%p ret = %d (%s)##\n",(int)pthread_self(),ligne,text,param,ret,strerror(ret));
|
|
// abort();
|
|
}
|
|
CSynchro::CSynchro() {
|
|
TRACEN((printf("\nT%d : E1-CSynchro(this=%p,m=%p,cond=%p)\n",(int)pthread_self(),(void *)this,(void *)&_object,(void *)&_cond)))
|
|
_isValid = false;
|
|
}
|
|
|
|
void CSynchro::Create() {
|
|
TRACEN((printf("\nT%d : E1-CSynchro::Create(this=%p,m=%p,cond=%p)\n",(int)pthread_self(),(void *)this,(void *)&_object,(void *)&_cond)))
|
|
pthread_mutexattr_t mutexattr;
|
|
memset(&mutexattr,0,sizeof(mutexattr));
|
|
int ret = pthread_mutexattr_init(&mutexattr);
|
|
if (ret != 0) {
|
|
dump_error(__LINE__,ret,"pthread_mutexattr_init",&mutexattr);
|
|
}
|
|
ret = pthread_mutexattr_settype(&mutexattr,PTHREAD_MUTEX_ERRORCHECK);
|
|
if (ret != 0) dump_error(__LINE__,ret,"pthread_mutexattr_settype",&mutexattr);
|
|
ret = ::pthread_mutex_init(&_object,&mutexattr);
|
|
if (ret != 0) dump_error(__LINE__,ret,"pthread_mutex_init",&_object);
|
|
ret = ::pthread_cond_init(&_cond,0);
|
|
if (ret != 0) dump_error(__LINE__,ret,"pthread_cond_init",&_cond);
|
|
TRACEN((printf("\nT%d : E2-CSynchro::Create(m=%p,cond=%p)\n",(int)pthread_self(),(void *)&_object,(void *)&_cond)))
|
|
}
|
|
CSynchro::~CSynchro() {
|
|
TRACEN((printf("\nT%d : E1-~CSynchro(this=%p,m=%p,cond=%p)\n",(int)pthread_self(),(void *)this,(void *)&_object,(void *)&_cond)))
|
|
if (_isValid) {
|
|
int ret = ::pthread_mutex_destroy(&_object);
|
|
if (ret != 0) dump_error(__LINE__,ret,"pthread_mutex_destroy",&_object);
|
|
ret = ::pthread_cond_destroy(&_cond);
|
|
if (ret != 0) dump_error(__LINE__,ret,"pthread_cond_destroy",&_cond);
|
|
TRACEN((printf("\nT%d : E2-~CSynchro(m=%p,cond=%p)\n",(int)pthread_self(),(void *)&_object,(void *)&_cond)))
|
|
}
|
|
_isValid = false;
|
|
}
|
|
void CSynchro::Enter() {
|
|
TRACEN((printf("\nT%d : E1-CSynchro::Enter(%p)\n",(int)pthread_self(),(void *)&_object)))
|
|
int ret = ::pthread_mutex_lock(&_object);
|
|
if (ret != 0) {
|
|
dump_error(__LINE__,ret,"CSynchro::Enter-pthread_mutex_lock",&_object);
|
|
}
|
|
TRACEN((printf("\nT%d : E2-CSynchro::Enter(%p)\n",(int)pthread_self(),(void *)&_object)))
|
|
}
|
|
void CSynchro::Leave() {
|
|
TRACEN((printf("\nT%d : E1-CSynchro::Leave(%p)\n",(int)pthread_self(),(void *)&_object)))
|
|
int ret = ::pthread_mutex_unlock(&_object);
|
|
if (ret != 0) dump_error(__LINE__,ret,"Leave::pthread_mutex_unlock",&_object);
|
|
TRACEN((printf("\nT%d : E2-CSynchro::Leave(%p)\n",(int)pthread_self(),(void *)&_object)))
|
|
}
|
|
void CSynchro::WaitCond() {
|
|
TRACEN((printf("\nT%d : E1-CSynchro::WaitCond(%p,%p)\n",(int)pthread_self(),(void *)&_cond,(void *)&_object)))
|
|
int ret = ::pthread_cond_wait(&_cond, &_object);
|
|
if (ret != 0) dump_error(__LINE__,ret,"pthread_cond_wait",&_cond);
|
|
TRACEN((printf("\nT%d : E2-CSynchro::WaitCond(%p,%p)\n",(int)pthread_self(),(void *)&_cond,(void *)&_object)))
|
|
}
|
|
void CSynchro::LeaveAndSignal() {
|
|
TRACEN((printf("\nT%d : E1-CSynchro::LeaveAndSignal(%p)\n",(int)pthread_self(),(void *)&_cond)))
|
|
int ret = ::pthread_cond_broadcast(&_cond);
|
|
if (ret != 0) dump_error(__LINE__,ret,"pthread_cond_broadcast",&_cond);
|
|
TRACEN((printf("\nT%d : E2-CSynchro::LeaveAndSignal(%p)\n",(int)pthread_self(),(void *)&_object)))
|
|
ret = ::pthread_mutex_unlock(&_object);
|
|
if (ret != 0) dump_error(__LINE__,ret,"LeaveAndSignal::pthread_mutex_unlock",&_object);
|
|
TRACEN((printf("\nT%d : E3-CSynchro::LeaveAndSignal(%p)\n",(int)pthread_self(),(void *)&_cond)))
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
}}
|
|
|
|
DWORD WINAPI WaitForMultipleObjects( DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout )
|
|
{
|
|
TRACEN((printf("\nT%d : E1-WaitForMultipleObjects(%d)\n",(int)pthread_self(),(int)count)))
|
|
if (wait_all != FALSE) {
|
|
printf("\n\n INTERNAL ERROR - WaitForMultipleObjects(...) wait_all(%d) != FALSE\n\n",(unsigned)wait_all);
|
|
abort();
|
|
}
|
|
|
|
if (timeout != INFINITE) {
|
|
printf("\n\n INTERNAL ERROR - WaitForMultipleObjects(...) timeout(%u) != INFINITE\n\n",(unsigned)timeout);
|
|
abort();
|
|
}
|
|
|
|
if (count < 1) {
|
|
printf("\n\n INTERNAL ERROR - WaitForMultipleObjects(...) count(%u) < 1\n\n",(unsigned)count);
|
|
abort();
|
|
}
|
|
|
|
NWindows::NSynchronization::CSynchro *synchro = handles[0]->_sync;
|
|
|
|
TRACEN((printf("\nT%d : E2-WaitForMultipleObjects(%d)\n",(int)pthread_self(),(int)count)))
|
|
synchro->Enter();
|
|
TRACEN((printf("\nT%d : E3-WaitForMultipleObjects(%d)\n",(int)pthread_self(),(int)count)))
|
|
|
|
#ifdef DEBUG_SYNCHRO
|
|
for(DWORD i=1;i<count;i++) {
|
|
if (synchro != handles[i]->_sync) {
|
|
printf("\n\n INTERNAL ERROR - WaitForMultipleObjects(...) synchro(%p) != handles[%d]->_sync(%p)\n\n",
|
|
synchro,(unsigned)i,handles[i]->_sync);
|
|
abort();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
while(1) {
|
|
for(DWORD i=0;i<count;i++) {
|
|
if (handles[i]->IsSignaledAndUpdate()) {
|
|
synchro->Leave();
|
|
TRACEN((printf("\nT%d : E4-WaitForMultipleObjects(%d)\n",(int)pthread_self(),(int)count)))
|
|
return WAIT_OBJECT_0+i;
|
|
}
|
|
}
|
|
synchro->WaitCond();
|
|
}
|
|
synchro->Leave();
|
|
return ETIMEDOUT; // WAIT_TIMEOUT;
|
|
}
|
|
|