threading.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /*
  2. * Copyright (c) 2013 Hugh Bailey <[email protected]>
  3. *
  4. * Permission to use, copy, modify, and distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  9. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  11. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  13. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  14. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #pragma once
  17. /*
  18. * Allows posix thread usage on windows as well as other operating systems.
  19. * Use this header if you want to make your code more platform independent.
  20. *
  21. * Also provides a custom platform-independent "event" handler via
  22. * pthread conditional waits.
  23. */
  24. #include "c99defs.h"
  25. #ifdef _MSC_VER
  26. #include "../../deps/w32-pthreads/pthread.h"
  27. #include "../../deps/w32-pthreads/semaphore.h"
  28. #else
  29. #include <errno.h>
  30. #include <pthread.h>
  31. #include <semaphore.h>
  32. #endif
  33. #ifdef __cplusplus
  34. extern "C" {
  35. #endif
  36. /* this may seem strange, but you can't use it unless it's an initializer */
  37. static inline void pthread_mutex_init_value(pthread_mutex_t *mutex)
  38. {
  39. pthread_mutex_t init_val = PTHREAD_MUTEX_INITIALIZER;
  40. *mutex = init_val;
  41. }
  42. struct event_data {
  43. pthread_mutex_t mutex;
  44. pthread_cond_t cond;
  45. bool signalled;
  46. bool manual;
  47. };
  48. enum event_type {
  49. EVENT_TYPE_AUTO,
  50. EVENT_TYPE_MANUAL
  51. };
  52. typedef struct event_data event_t;
  53. static inline int event_init(event_t *event, enum event_type type)
  54. {
  55. int code = 0;
  56. if ((code = pthread_mutex_init(&event->mutex, NULL)) < 0)
  57. return code;
  58. if ((code = pthread_cond_init(&event->cond, NULL)) < 0)
  59. pthread_mutex_destroy(&event->mutex);
  60. event->manual = (type == EVENT_TYPE_MANUAL);
  61. event->signalled = false;
  62. return code;
  63. }
  64. static inline void event_destroy(event_t *event)
  65. {
  66. if (event) {
  67. pthread_mutex_destroy(&event->mutex);
  68. pthread_cond_destroy(&event->cond);
  69. }
  70. }
  71. static inline int event_wait(event_t *event)
  72. {
  73. int code = 0;
  74. pthread_mutex_lock(&event->mutex);
  75. if (event->signalled ||
  76. (code = pthread_cond_wait(&event->cond, &event->mutex)) == 0) {
  77. if (!event->manual)
  78. event->signalled = false;
  79. pthread_mutex_unlock(&event->mutex);
  80. }
  81. return code;
  82. }
  83. static inline int event_try(event_t *event)
  84. {
  85. pthread_mutex_lock(&event->mutex);
  86. if (event->signalled) {
  87. if (!event->manual)
  88. event->signalled = false;
  89. pthread_mutex_unlock(&event->mutex);
  90. return 0;
  91. }
  92. pthread_mutex_unlock(&event->mutex);
  93. return EAGAIN;
  94. }
  95. static inline int event_signal(event_t *event)
  96. {
  97. int code = 0;
  98. pthread_mutex_lock(&event->mutex);
  99. code = pthread_cond_signal(&event->cond);
  100. event->signalled = true;
  101. pthread_mutex_unlock(&event->mutex);
  102. return code;
  103. }
  104. static inline void event_reset(event_t *event)
  105. {
  106. pthread_mutex_lock(&event->mutex);
  107. event->signalled = false;
  108. pthread_mutex_unlock(&event->mutex);
  109. }
  110. #ifdef __cplusplus
  111. }
  112. #endif