summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/unix/CPP/Windows/Synchronization.cpp
blob: 8130f9ac37270acbfc6226ad97bfd619a2f6af82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// 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;
}