ecere/ECON: Fixed ECON parser expecting members in specific order
[sdk] / ecere / src / sys / Thread.ec
1 #define _Noreturn
2
3 namespace sys;
4
5 #define set _set
6 #define uint _uint
7 // Platform includes
8 #if defined(__WIN32__)
9 #define WIN32_LEAN_AND_MEAN
10 #define String String_
11 #define Thread Thread_
12 #include <windows.h>
13 #undef String
14 #undef Thread
15 #else
16 #include <pthread.h>
17 #if !defined(__ANDROID__)
18 #include <signal.h>
19 #endif
20 #endif
21 #undef uint
22 #undef set
23
24 import "instance"
25
26 #if !defined(__WIN32__)
27 import "Semaphore"
28 #endif
29
30 public enum ThreadPriority
31 {
32    normal = 0,
33    aboveNormal = 1,
34    belowNormal = -1,
35    highest = 2,
36    lowest = -2,
37    idle = -15,
38    timeCritical = 15
39 };
40
41 public class Thread
42 {
43    ~Thread()
44    {
45 #if defined(__WIN32__)
46       if(handle)
47          CloseHandle(handle);
48 #endif
49    }
50
51 #if defined(__WIN32__)
52    HANDLE handle;
53    uint id;
54 #elif !defined(__EMSCRIPTEN__)
55    pthread_t id;
56    bool dontDetach;
57    Semaphore sem { };
58 #else
59    uint id;
60 #endif
61
62    uint returnCode;
63    bool started;
64
65 #if !defined(__EMSCRIPTEN__)
66 #if defined(__WIN32__)
67    uint ThreadCallBack()
68 #else
69    void * ThreadCallBack()
70 #endif
71    {
72       uint returnCode = this.returnCode = Main();
73       started = false;
74 #if defined(__WIN32__)
75       CloseHandle(handle);
76       handle = null;
77 #else
78       if(!dontDetach)
79          pthread_detach(id);
80       sem.Release();
81
82 #endif
83       delete this;
84 #if defined(__WIN32__)
85       return returnCode;
86 #else
87       return (void *)(uintptr_t)returnCode;
88 #endif
89    }
90 #endif
91
92 public:
93    virtual uint Main(void);
94
95    void Create()
96    {
97       incref this;
98       if(!started)
99       {
100 #if !defined(__WIN32__) && !defined(__EMSCRIPTEN__)
101          sem.TryWait();
102 #endif
103          started = true;
104          // printf("Creating %s thread\n", _class.name);
105 #if !defined(__EMSCRIPTEN__)
106 #if defined(__WIN32__)
107          if(!handle)
108          {
109             DWORD tID;
110             handle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadCallBack, this, 0, &tID);
111             id = (uint)tID;
112          }
113 #else
114          {
115             int error;
116             /*pthread_attr_t attr;
117             pthread_attr_init(&attr);
118             pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);*/  // Default attribute ???
119             error = pthread_create(&id, null /*&attr*/, ThreadCallBack, this);
120             if(error)
121                printf("Error %d creating a thread\n", error);
122          }
123 #endif
124 #endif
125       }
126    }
127
128    void Kill()
129    {
130 #if !defined(__EMSCRIPTEN__)
131 #if defined(__WIN32__)
132       if(handle)
133       {
134          TerminateThread(handle, 0);
135          handle = null;
136       }
137 #else
138       if(started)
139          pthread_kill(id, SIGQUIT);
140 #endif
141 #endif
142       if(started)
143       {
144          started = false;
145          delete this;
146       }
147    }
148
149    void Wait()
150    {
151 #if !defined(__EMSCRIPTEN__)
152 #if defined(__WIN32__)
153       if(WaitForSingleObject(handle, INFINITE /*2000*/) == WAIT_TIMEOUT)
154          PrintLn("Thread not returning?\n");
155 #else
156
157       /*dontDetach = true;
158       if(started)
159          pthread_join(id, NULL);*/
160
161       if(started)
162          sem.Wait();
163 #endif
164 #endif
165    }
166
167    void SetPriority(ThreadPriority priority)
168    {
169 #if !defined(__EMSCRIPTEN__)
170 #if defined(__WIN32__)
171       SetThreadPriority(handle, priority);
172 #else
173       /*
174       struct sched_param param;
175       int policy = (priority > 0) ? SCHED_RR : SCHED_OTHER;
176       param.sched_priority = (priority > 0) ? (priority * 99 / 15) : 0;
177       pthread_setschedparam(id, policy, &param);
178       */
179 #endif
180 #endif
181    }
182
183    property bool created { get { return started; } };
184 }
185