ecere/ECON: Fixed ECON parser expecting members in specific order
[sdk] / ecere / src / sys / Mutex.ec
1 #define _Noreturn
2
3 #if defined(__ANDROID__)
4 #include <android/log.h>
5
6 #define printf(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
7 #endif
8
9 namespace sys;
10
11 #undef _GNU_SOURCE
12 #undef __USE_UNIX98
13 #define _GNU_SOURCE
14 #define __USE_UNIX98
15 // Platform includes
16 #define uint _uint
17 #define set _set
18 #define String _String
19 #if defined(__WIN32__)
20 #define WIN32_LEAN_AND_MEAN
21 #include <windows.h>
22 #else
23 #include <pthread.h>
24 #endif
25 #undef uint
26 #undef set
27 #undef String
28
29 import "instance"
30
31 // Moved this here from Thread.ec to make compiling ecereCOM in Debug easier
32 public int64 GetCurrentThreadID()
33 {
34 #if defined(__WIN32__)
35    return (int64)GetCurrentThreadId();
36 #else
37    return (int64)pthread_self();
38 #endif
39 }
40
41 public class Mutex : struct
42 {
43 #if !defined(__EMSCRIPTEN__)
44
45 //   class_fixed
46 #if defined(__WIN32__)
47 #ifdef _DEBUG
48    HANDLE mutex;
49 #else
50    CRITICAL_SECTION mutex;
51 #endif
52 #else
53    pthread_mutex_t mutex;
54 #endif
55 #endif
56
57 //#ifdef _DEBUG
58    int64 _owningThread;
59 //#endif
60    int _lockCount;
61
62    Mutex()
63    {
64 #if !defined(__EMSCRIPTEN__)
65 #if defined(__WIN32__)
66 #ifdef _DEBUG
67       mutex = CreateMutex(null, FALSE, null);
68 #else
69       InitializeCriticalSection(&mutex);
70 #endif
71 #else
72       pthread_mutexattr_t attr;
73       pthread_mutexattr_init(&attr);
74
75       // settype is available on Linux now, and hopefully _GNU_SOURCE should ensure it is
76 #if 0 // def __linux__
77       pthread_mutexattr_setkind_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
78 #else
79       pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
80 #endif
81
82       pthread_mutex_init(&mutex, &attr);
83       pthread_mutexattr_destroy(&attr);
84 #endif
85 #endif
86
87       _lockCount = 0;
88 //#ifdef _DEBUG
89       _owningThread = 0;
90 //#endif
91       return true;
92    }
93
94    ~Mutex()
95    {
96 #if !defined(__EMSCRIPTEN__)
97 #if defined(__WIN32__)
98 #ifdef _DEBUG
99       CloseHandle(mutex);
100 #else
101       DeleteCriticalSection(&mutex);
102 #endif
103 #else
104       pthread_mutex_destroy(&mutex);
105 #endif
106 #endif
107    }
108
109 public:
110    void Wait(void)
111    {
112       if(this)
113       {
114 #if !defined(__EMSCRIPTEN__)
115          /*
116          if(this == globalSystem.fileMonitorMutex)
117             printf("[%d] Waiting on Mutex %x\n", (int)GetCurrentThreadID(), this);
118          */
119 #if defined(__WIN32__)
120 #ifdef _DEBUG
121          if(WaitForSingleObject(mutex, INFINITE /*2000*/) == WAIT_TIMEOUT)
122             PrintLn("Deadlock?");
123 #else
124          EnterCriticalSection(&mutex);
125 #endif
126 #else
127 #ifdef _DEBUG
128          {
129             int e;
130             e = pthread_mutex_lock(&mutex);
131             if(e)
132                PrintLn("pthread_mutex_lock returned ", e);
133          }
134 #else
135          pthread_mutex_lock(&mutex);
136 #endif
137 #endif
138
139 #endif
140
141 //#ifdef _DEBUG
142          _owningThread = GetCurrentThreadID();
143 //#endif
144          _lockCount++;
145       }
146    }
147
148    void Release(void)
149    {
150       if(this)
151       {
152 #if !defined(__EMSCRIPTEN__)
153          /*
154          if(this == globalSystem.fileMonitorMutex)
155             printf("[%d] Releasing Mutex %x\n", (int)GetCurrentThreadID(), this);
156          */
157 #ifdef _DEBUG
158          if(_lockCount && _owningThread != GetCurrentThreadID())
159             PrintLn("WARNING: Not in owning thread!!");
160 #endif
161
162          if(!--_lockCount)
163          {
164 //#ifdef _DEBUG
165             _owningThread = 0;
166 //#endif
167          }
168 #if defined(__WIN32__)
169 #ifdef _DEBUG
170          ReleaseMutex(mutex);
171 #else
172          LeaveCriticalSection(&mutex);
173 #endif
174 #else
175 #ifdef _DEBUG
176          {
177             int e;
178             e = pthread_mutex_unlock(&mutex);
179             if(e)
180                PrintLn("pthread_mutex_unlock returned ", e);
181          }
182 #else
183          pthread_mutex_unlock(&mutex);
184 #endif
185 #endif
186 #endif
187
188 #ifdef _DEBUG
189          if(_lockCount < 0)
190             PrintLn("WARNING: lockCount < 0");
191 #endif
192       }
193    }
194
195    property int lockCount { get { return _lockCount; } }
196    property int64 owningThread { get { return _owningThread; } }
197 };