| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- /*
- * Copyright (c) 2012-2014 Daniele Bartolini and individual contributors.
- * License: https://github.com/taylor001/crown/blob/master/LICENSE
- */
- #pragma once
- #include "config.h"
- #include "assert.h"
- #include "types.h"
- #include "semaphore.h"
- #if CROWN_PLATFORM_POSIX
- #include <pthread.h>
- #elif CROWN_PLATFORM_WINDOWS
- #include "win_headers.h"
- #include <process.h>
- #endif
- namespace crown
- {
- typedef int32_t (*ThreadFunction)(void*);
- struct Thread
- {
- Thread()
- #if CROWN_PLATFORM_POSIX
- : _handle(0)
- #elif CROWN_PLATFORM_WINDOWS
- : _handle(INVALID_HANDLE_VALUE)
- #endif
- , _function(NULL)
- , _data(NULL)
- , _stack_size(0)
- , _is_running(false)
- {
- }
- ~Thread()
- {
- if (_is_running)
- stop();
- }
- void start(ThreadFunction func, void* data = NULL, size_t stack_size = 0)
- {
- CE_ASSERT(!_is_running, "Thread is already running");
- CE_ASSERT(func != NULL, "Function must be != NULL");
- _function = func;
- _data = data;
- _stack_size = stack_size;
- #if CROWN_PLATFORM_POSIX
- pthread_attr_t attr;
- int result = pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
- CE_ASSERT(result == 0, "pthread_attr_init: errno = %d", result);
- if (_stack_size != 0)
- {
- result = pthread_attr_setstacksize(&attr, _stack_size);
- CE_ASSERT(result == 0, "pthread_attr_setstacksize: errno = %d", result);
- }
- result = pthread_create(&_handle, &attr, thread_proc, this);
- CE_ASSERT(result == 0, "pthread_create: errno = %d", result);
- // Free attr memory
- result = pthread_attr_destroy(&attr);
- CE_ASSERT(result == 0, "pthread_attr_destroy: errno = %d", result);
- CE_UNUSED(result);
- #elif CROWN_PLATFORM_WINDOWS
- _handle = CreateThread(NULL, stack_size, Thread::thread_proc, this, 0, NULL);
- CE_ASSERT(_handle != NULL, "CreateThread: GetLastError = %d", GetLastError());
- #endif
- _is_running = true;
- _sem.wait();
- }
- void stop()
- {
- CE_ASSERT(_is_running, "Thread is not running");
- #if CROWN_PLATFORM_POSIX
- int result = pthread_join(_handle, NULL);
- CE_ASSERT(result == 0, "pthread_join: errno = %d", result);
- CE_UNUSED(result);
- _handle = 0;
- #elif CROWN_PLATFORM_WINDOWS
- WaitForSingleObject(_handle, INFINITE);
- // GetExitCodeThread(_handle, &m_exit_code);
- CloseHandle(_handle);
- _handle = INVALID_HANDLE_VALUE;
- #endif
- _is_running = false;
- }
- bool is_running()
- {
- return _is_running;
- }
- private:
- int32_t run()
- {
- _sem.post();
- return _function(_data);
- }
- #if CROWN_PLATFORM_POSIX
- static void* thread_proc(void* arg)
- {
- static int32_t result = -1;
- result = ((Thread*)arg)->run();
- return (void*)&result;
- }
- #elif CROWN_PLATFORM_WINDOWS
- static DWORD WINAPI thread_proc(void* arg)
- {
- Thread* thread = (Thread*) arg;
- int32_t result = thread->run();
- return result;
- }
- #endif
- private:
- #if CROWN_PLATFORM_POSIX
- pthread_t _handle;
- #elif CROWN_PLATFORM_WINDOWS
- HANDLE _handle;
- #endif
- ThreadFunction _function;
- void* _data;
- Semaphore _sem;
- size_t _stack_size;
- bool _is_running;
- private:
- // Disable copying
- Thread(const Thread&);
- Thread& operator=(const Thread&);
- };
- } // namespace crown
|