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