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