thread.hpp 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. #pragma once
  2. //simple thread library
  3. //primary rationale is that std::thread does not support custom stack sizes
  4. //this is highly critical in certain applications such as threaded web servers
  5. //an added bonus is that it avoids licensing issues on Windows
  6. //win32-pthreads (needed for std::thread) is licensed under the GPL only
  7. #include <nall/platform.hpp>
  8. #include <nall/function.hpp>
  9. #include <nall/intrinsics.hpp>
  10. #if defined(API_POSIX)
  11. #include <pthread.h>
  12. namespace nall {
  13. struct thread {
  14. inline auto join() -> void;
  15. static inline auto create(const function<void (uintptr)>& callback, uintptr parameter = 0, uint stacksize = 0) -> thread;
  16. static inline auto detach() -> void;
  17. static inline auto exit() -> void;
  18. struct context {
  19. function<auto (uintptr) -> void> callback;
  20. uintptr parameter = 0;
  21. };
  22. private:
  23. pthread_t handle;
  24. };
  25. inline auto _threadCallback(void* parameter) -> void* {
  26. auto context = (thread::context*)parameter;
  27. context->callback(context->parameter);
  28. delete context;
  29. return nullptr;
  30. }
  31. auto thread::join() -> void {
  32. pthread_join(handle, nullptr);
  33. }
  34. auto thread::create(const function<void (uintptr)>& callback, uintptr parameter, uint stacksize) -> thread {
  35. thread instance;
  36. auto context = new thread::context;
  37. context->callback = callback;
  38. context->parameter = parameter;
  39. pthread_attr_t attr;
  40. pthread_attr_init(&attr);
  41. if(stacksize) pthread_attr_setstacksize(&attr, max(PTHREAD_STACK_MIN, stacksize));
  42. pthread_create(&instance.handle, &attr, _threadCallback, (void*)context);
  43. return instance;
  44. }
  45. auto thread::detach() -> void {
  46. pthread_detach(pthread_self());
  47. }
  48. auto thread::exit() -> void {
  49. pthread_exit(nullptr);
  50. }
  51. }
  52. #elif defined(API_WINDOWS)
  53. namespace nall {
  54. struct thread {
  55. inline ~thread();
  56. inline auto join() -> void;
  57. static inline auto create(const function<void (uintptr)>& callback, uintptr parameter = 0, uint stacksize = 0) -> thread;
  58. static inline auto detach() -> void;
  59. static inline auto exit() -> void;
  60. struct context {
  61. function<auto (uintptr) -> void> callback;
  62. uintptr parameter = 0;
  63. };
  64. private:
  65. HANDLE handle = 0;
  66. };
  67. inline auto WINAPI _threadCallback(void* parameter) -> DWORD {
  68. auto context = (thread::context*)parameter;
  69. context->callback(context->parameter);
  70. delete context;
  71. return 0;
  72. }
  73. thread::~thread() {
  74. if(handle) {
  75. CloseHandle(handle);
  76. handle = 0;
  77. }
  78. }
  79. auto thread::join() -> void {
  80. if(handle) {
  81. WaitForSingleObject(handle, INFINITE);
  82. CloseHandle(handle);
  83. handle = 0;
  84. }
  85. }
  86. auto thread::create(const function<void (uintptr)>& callback, uintptr parameter, uint stacksize) -> thread {
  87. thread instance;
  88. auto context = new thread::context;
  89. context->callback = callback;
  90. context->parameter = parameter;
  91. instance.handle = CreateThread(nullptr, stacksize, _threadCallback, (void*)context, 0, nullptr);
  92. return instance;
  93. }
  94. auto thread::detach() -> void {
  95. //Windows threads do not use this concept:
  96. //~thread() frees resources via CloseHandle()
  97. //thread continues to run even after handle is closed
  98. }
  99. auto thread::exit() -> void {
  100. ExitThread(0);
  101. }
  102. }
  103. #endif