123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- #pragma once
- //simple thread library
- //primary rationale is that std::thread does not support custom stack sizes
- //this is highly critical in certain applications such as threaded web servers
- //an added bonus is that it avoids licensing issues on Windows
- //win32-pthreads (needed for std::thread) is licensed under the GPL only
- #include <nall/platform.hpp>
- #include <nall/function.hpp>
- #include <nall/intrinsics.hpp>
- #if defined(API_POSIX)
- #include <pthread.h>
- namespace nall {
- struct thread {
- inline auto join() -> void;
- static inline auto create(const function<void (uintptr)>& callback, uintptr parameter = 0, uint stacksize = 0) -> thread;
- static inline auto detach() -> void;
- static inline auto exit() -> void;
- struct context {
- function<auto (uintptr) -> void> callback;
- uintptr parameter = 0;
- };
- private:
- pthread_t handle;
- };
- inline auto _threadCallback(void* parameter) -> void* {
- auto context = (thread::context*)parameter;
- context->callback(context->parameter);
- delete context;
- return nullptr;
- }
- auto thread::join() -> void {
- pthread_join(handle, nullptr);
- }
- auto thread::create(const function<void (uintptr)>& callback, uintptr parameter, uint stacksize) -> thread {
- thread instance;
- auto context = new thread::context;
- context->callback = callback;
- context->parameter = parameter;
- pthread_attr_t attr;
- pthread_attr_init(&attr);
- if(stacksize) pthread_attr_setstacksize(&attr, max(PTHREAD_STACK_MIN, stacksize));
- pthread_create(&instance.handle, &attr, _threadCallback, (void*)context);
- return instance;
- }
- auto thread::detach() -> void {
- pthread_detach(pthread_self());
- }
- auto thread::exit() -> void {
- pthread_exit(nullptr);
- }
- }
- #elif defined(API_WINDOWS)
- namespace nall {
- struct thread {
- inline ~thread();
- inline auto join() -> void;
- static inline auto create(const function<void (uintptr)>& callback, uintptr parameter = 0, uint stacksize = 0) -> thread;
- static inline auto detach() -> void;
- static inline auto exit() -> void;
- struct context {
- function<auto (uintptr) -> void> callback;
- uintptr parameter = 0;
- };
- private:
- HANDLE handle = 0;
- };
- inline auto WINAPI _threadCallback(void* parameter) -> DWORD {
- auto context = (thread::context*)parameter;
- context->callback(context->parameter);
- delete context;
- return 0;
- }
- thread::~thread() {
- if(handle) {
- CloseHandle(handle);
- handle = 0;
- }
- }
- auto thread::join() -> void {
- if(handle) {
- WaitForSingleObject(handle, INFINITE);
- CloseHandle(handle);
- handle = 0;
- }
- }
- auto thread::create(const function<void (uintptr)>& callback, uintptr parameter, uint stacksize) -> thread {
- thread instance;
- auto context = new thread::context;
- context->callback = callback;
- context->parameter = parameter;
- instance.handle = CreateThread(nullptr, stacksize, _threadCallback, (void*)context, 0, nullptr);
- return instance;
- }
- auto thread::detach() -> void {
- //Windows threads do not use this concept:
- //~thread() frees resources via CloseHandle()
- //thread continues to run even after handle is closed
- }
- auto thread::exit() -> void {
- ExitThread(0);
- }
- }
- #endif
|