blob: f38a10b7cbfd76b124311ea5ddc70aef8bbec946 [file] [log] [blame]
Pierre Ossman687d52c2015-11-12 12:16:08 +01001/* Copyright 2015 Pierre Ossman for Cendio AB
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19#ifdef WIN32
20#include <windows.h>
21#else
22#include <pthread.h>
Pierre Ossman7b63a7c2015-11-13 14:07:52 +010023#include <unistd.h>
Pierre Ossman687d52c2015-11-12 12:16:08 +010024#endif
25
26#include <rdr/Exception.h>
27
28#include <os/Mutex.h>
29#include <os/Thread.h>
30
31using namespace os;
32
33Thread::Thread() : running(false), threadId(NULL)
34{
35 mutex = new Mutex;
36
37#ifdef WIN32
38 threadId = new HANDLE;
39#else
40 threadId = new pthread_t;
41#endif
42}
43
44Thread::~Thread()
45{
46#ifdef WIN32
47 delete (HANDLE*)threadId;
48#else
49 if (isRunning())
50 pthread_cancel(*(pthread_t*)threadId);
51 delete (pthread_t*)threadId;
52#endif
53
54 delete mutex;
55}
56
57void Thread::start()
58{
59 AutoMutex a(mutex);
60
61#ifdef WIN32
62 *(HANDLE*)threadId = CreateThread(NULL, 0, startRoutine, this, 0, NULL);
63 if (*(HANDLE*)threadId == NULL)
64 throw rdr::SystemException("Failed to create thread", GetLastError());
65#else
66 int ret;
67
68 ret = pthread_create((pthread_t*)threadId, NULL, startRoutine, this);
69 if (ret != 0)
70 throw rdr::SystemException("Failed to create thread", ret);
71#endif
72
73 running = true;
74}
75
76void Thread::wait()
77{
78 if (!isRunning())
79 return;
80
81#ifdef WIN32
82 DWORD ret;
83
84 ret = WaitForSingleObject(*(HANDLE*)threadId, INFINITE);
85 if (ret != WAIT_OBJECT_0)
86 throw rdr::SystemException("Failed to join thread", GetLastError());
87#else
88 int ret;
89
90 ret = pthread_join(*(pthread_t*)threadId, NULL);
91 if (ret != 0)
92 throw rdr::SystemException("Failed to join thread", ret);
93#endif
94}
95
96bool Thread::isRunning()
97{
98 AutoMutex a(mutex);
99
100 return running;
101}
102
Pierre Ossman7b63a7c2015-11-13 14:07:52 +0100103size_t Thread::getSystemCPUCount()
104{
105#ifdef WIN32
106 SYSTEM_INFO si;
107 size_t count;
108 DWORD mask;
109
110 GetSystemInfo(&si);
111
112 count = 0;
113 for (mask = si.dwActiveProcessorMask;mask != 0;mask >>= 1) {
114 if (mask & 0x1)
115 count++;
116 }
117
118 if (count > si.dwNumberOfProcessors)
119 count = si.dwNumberOfProcessors;
120
121 return count;
122#else
123 long ret;
124
125 ret = sysconf(_SC_NPROCESSORS_ONLN);
126 if (ret == -1)
127 return 0;
128
129 return ret;
130#endif
131}
132
Pierre Ossman687d52c2015-11-12 12:16:08 +0100133#ifdef WIN32
134long unsigned __stdcall Thread::startRoutine(void* data)
135#else
136void* Thread::startRoutine(void* data)
137#endif
138{
139 Thread *self;
140
141 self = (Thread*)data;
142
143 try {
144 self->worker();
145 } catch(...) {
146 }
147
148 self->mutex->lock();
149 self->running = false;
150 self->mutex->unlock();
151
152 return 0;
153}