1 /************************************************************************
3 * voxelands - 3d voxel world sandbox game
4 * Copyright (C) Lisa 'darkrose' Milne 2016 <lisa@ltmnet.com>
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
18 ************************************************************************/
29 #define IO_THREAD_STOPPED 0
30 #define IO_THREAD_RUNNING 1
31 static thread_t
*threads
= NULL
;
32 static mutex_t
*mutexes
= NULL
;
34 /* create a new thread */
35 thread_t
*thread_create(void *(*func
)(), array_t
*args
)
37 thread_t
*t
= malloc(sizeof(thread_t
));
39 t
->state
= IO_THREAD_RUNNING
;
44 threads
= list_push((void**)&threads
,t
);
47 pthread_attr_init(&t
->attr
);
48 pthread_attr_setdetachstate(&t
->attr
, PTHREAD_CREATE_JOINABLE
);
49 pthread_create(&t
->thread
, &t
->attr
, t
->func
, (void *)t
);
51 t
->thread
= CreateThread(NULL
, 0, t
->func
, (void*)t
, 0, NULL
);
57 /* destroy a thread */
58 void thread_free(thread_t
*t
)
65 pthread_attr_destroy(&t
->attr
);
68 array_free(t
->args
,1);
72 /* exit from a thread */
73 void thread_exit(thread_t
*t
, int state
)
79 t
->state
= IO_THREAD_STOPPED
;
88 void thread_stop(thread_t
*t
)
93 if (t
->state
== IO_THREAD_RUNNING
) {
94 t
->state
= IO_THREAD_STOPPED
;
96 pthread_kill(t
->thread
,SIGKILL
);
98 TerminateThread(t
->thread
,0);
99 CloseHandle(t
->thread
);
104 /* restart a thread */
105 int thread_wake(thread_t
*t
)
110 if (t
->state
== IO_THREAD_RUNNING
) {
112 pthread_kill(t
->thread
,SIGCONT
);
114 ResumeThread(t
->thread
);
117 t
->state
= IO_THREAD_RUNNING
;
119 pthread_create(&t
->thread
, &t
->attr
, t
->func
, (void *)t
);
121 t
->thread
= CreateThread(NULL
, 0, t
->func
, (void*)t
, 0, NULL
);
127 /* wait for a thread to exit */
128 void thread_wait(thread_t
*t
)
133 if (t
->state
== IO_THREAD_RUNNING
) {
135 pthread_join(t
->thread
,NULL
);
137 WaitForSingleObject(t
->thread
, 2000);
138 CloseHandle(t
->thread
);
141 t
->state
= IO_THREAD_STOPPED
;
144 threadid_t
thread_get_current_id()
147 return GetCurrentThreadId();
149 return pthread_self();
154 mutex_t
*mutex_create()
156 mutex_t
*m
= malloc(sizeof(mutex_t
));
159 pthread_mutexattr_init(&m
->attr
);
160 pthread_mutexattr_settype(&m
->attr
, PTHREAD_MUTEX_RECURSIVE
);
161 pthread_mutex_init(&m
->mut
, &m
->attr
);
163 InitializeCriticalSection(&m
->mut
);
166 m
->id
= thread_get_current_id();
169 mutexes
= list_push((void**)&mutexes
,m
);
174 /* destroy a mutex */
175 void mutex_free(mutex_t
*m
)
179 pthread_mutex_destroy(&m
->mut
);
180 pthread_mutexattr_destroy(&m
->attr
);
182 DeleteCriticalSection(&m
->mut
);
185 mutexes
= list_remove((void**)&mutexes
,m
);
190 void mutex_lock(mutex_t
*m
)
192 if (mutex_trylock(m
)) {
193 if (m
->id
== thread_get_current_id())
198 /* try to lock a mutex - return non-zero if not locked */
199 int mutex_trylock(mutex_t
*m
)
202 if (pthread_mutex_trylock(&m
->mut
))
205 if (!TryEnterCriticalSection(&m
->mut
))
208 m
->id
= thread_get_current_id();
215 void mutex_unlock(mutex_t
*m
)
221 pthread_mutex_unlock(&m
->mut
);
223 LeaveCriticalSection(&m
->mut
);
227 static void *mutex_test_lock_t(thread_t
*t
)
229 int r
= mutex_trylock(((mutex_t
**)(t
->args
->data
))[0]);
234 /* try to force a mutex to unlock */
235 void mutex_unlock_complete(mutex_t
*m
)
240 a
= array_create(ARRAY_TYPE_PTR
);
242 t
= thread_create(mutex_test_lock_t
,a
);