thread-nt.c
资源名称:c.rar [点击查看]
上传用户:shmaik
上传日期:2014-06-01
资源大小:45093k
文件大小:7k
源码类别:

VC书籍

开发平台:

C/C++

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <limits.h>
  5. #include <windows.h>
  6. #include <process.h>
  7. #include "assert.h"
  8. #include "mem.h"
  9. #include "thread.h"
  10. #include "sem.h"
  11. static char rcsid[] = "$Id: thread-nt.c,v 1.5 1997/07/29 17:10:25 drh Exp $";
  12. #define T Thread_T
  13. struct T {
  14. DWORD IDThread; /* Win 32 thread identifier */
  15. T handle; /* self pointer */
  16. int code; /* exit code */
  17. HANDLE join; /* join semaphore */
  18. T joinlist; /* threads waiting on join */
  19. T link; /* next thread on this join list */
  20. T next; /* next thread on this hash chain */
  21. int alerted; /* 1 if this thread has been alerted */
  22. int (*apply)(void *); /* initial function for this thread */
  23. void *args; /* argument for apply */
  24. };
  25. const Except_T Thread_Alerted = { "Thread alerted" };
  26. const Except_T Thread_Failed  = { "Thread creation failed" };
  27. static T allthreads[317];
  28. #define HASH(id) ((int)((id)%(sizeof allthreads/sizeof allthreads[0])))
  29. static int nthreads; /* number of threads in allthreads */
  30. static T root;
  31. static HANDLE join0; /* Thread_join(NULL) semaphore */
  32. static int join0count; /* number of threads waiting on join0; always 0 or 1 */
  33. static int critical;
  34. static CRITICAL_SECTION csection;
  35. #define ENTERCRITICAL EnterCriticalSection(&csection); assert(critical == 0); critical++
  36. #define LEAVECRITICAL   critical--; assert(critical == 0); LeaveCriticalSection(&csection)
  37. static T getThreadByID(DWORD id) {
  38. T t;
  39. ENTERCRITICAL;
  40. for (t = allthreads[HASH(id)]; t != NULL; t = t->next)
  41. if (t->IDThread == id)
  42. break;
  43. LEAVECRITICAL;
  44. assert(t);
  45. return t;
  46. }
  47. static void removeThread(T t) {
  48. T *q;
  49. ENTERCRITICAL;
  50. q = &allthreads[HASH(t->IDThread)];
  51. for ( ; *q != NULL && *q != t; q = &(*q)->next)
  52. ;
  53. assert(*q == t);
  54. *q = t->next;
  55. nthreads--;
  56. t->handle = NULL;
  57. LEAVECRITICAL;
  58. }
  59. static void addThread(T t) {
  60. T *q;
  61. ENTERCRITICAL;
  62. q = &allthreads[HASH(t->IDThread)];
  63. t->next = *q;
  64. *q = t;
  65. nthreads++;
  66. t->handle = t;
  67. LEAVECRITICAL;
  68. }
  69. static void testalert(T t) {
  70. ENTERCRITICAL;
  71. if (t->alerted) {
  72. t->alerted = 0;
  73. LEAVECRITICAL;
  74. RAISE(Thread_Alerted);
  75. }
  76. LEAVECRITICAL;
  77. }
  78. int Thread_init(int preempt, ...) {
  79. assert(preempt == 0 || preempt == 1);
  80. assert(root == NULL);
  81. TRY
  82. NEW0(root);
  83. EXCEPT(Mem_Failed)
  84. return -1;
  85. END_TRY;
  86. join0 = CreateSemaphore(NULL, 0, 1, NULL);
  87. if (join0 == NULL)
  88. return -1;
  89. root->join = CreateSemaphore(NULL, 0, INT_MAX, NULL);
  90. if (root->join == NULL) {
  91. BOOL result = CloseHandle(join0);
  92. assert(result == TRUE);
  93. return -1;
  94. }
  95. InitializeCriticalSection(&csection);
  96. root->IDThread = GetCurrentThreadId();
  97. addThread(root);
  98. /* handle preempt == 0 */
  99. return 1;
  100. }
  101. T Thread_self(void) {
  102. assert(root);
  103. return getThreadByID(GetCurrentThreadId());
  104. }
  105. void Thread_pause(void) {
  106. assert(root);
  107. Sleep(0);
  108. }
  109. int Thread_join(T t) {
  110. T current = Thread_self();
  111. assert(root);
  112. assert(t != current);
  113. testalert(current);
  114. if (t != NULL) {
  115. ENTERCRITICAL;
  116. if (t->handle == t) {
  117. HANDLE join = t->join;
  118. DWORD result;
  119. assert(current->link == NULL);
  120. current->link = t->joinlist;
  121. t->joinlist = current;
  122. LEAVECRITICAL;
  123. result = WaitForSingleObject(join, INFINITE);
  124. assert(result != WAIT_FAILED);
  125. testalert(current);
  126. return current->code;
  127. } else {
  128. LEAVECRITICAL;
  129. return -1;
  130. }
  131. }
  132. ENTERCRITICAL;
  133. if (nthreads > 1) {
  134. DWORD result;
  135. assert(join0count == 0);
  136. join0count++;
  137. LEAVECRITICAL;
  138. result = WaitForSingleObject(join0, INFINITE);
  139. assert(result != WAIT_FAILED);
  140. ENTERCRITICAL;
  141. join0count--;
  142. LEAVECRITICAL;
  143. testalert(current);
  144. } else {
  145. assert(join0count == 0);
  146. LEAVECRITICAL;
  147. return 0;
  148. }
  149. }
  150. void Thread_exit(int code) {
  151. BOOL result;
  152. T current = Thread_self();
  153. removeThread(current);
  154. ENTERCRITICAL;
  155. if (current->joinlist != NULL) {
  156. T t, n;
  157. int count = 0;
  158. assert(current->join);
  159. for (t = current->joinlist; t != NULL; t = n) {
  160. t->code = code;
  161. n = t->link;
  162. t->link = NULL;
  163. count++;
  164. }
  165. current->joinlist = NULL;
  166. result = ReleaseSemaphore(current->join, count, NULL);
  167. assert(result == TRUE);
  168. }
  169. result = CloseHandle(current->join);
  170. assert(result == TRUE);
  171. current->join = NULL;
  172. if (join0count > 0 && nthreads == 1) {
  173. assert(join0count == 1);
  174. result = ReleaseSemaphore(join0, 1, NULL);
  175. assert(result == TRUE);
  176. }
  177. if (nthreads == 0) {
  178. result = CloseHandle(join0);
  179. assert(result == TRUE);
  180. }
  181. FREE(current);
  182. LEAVECRITICAL;
  183. _endthreadex(code);
  184. }
  185. void Thread_alert(T t) {
  186. assert(root);
  187. ENTERCRITICAL;
  188. assert(t && t->handle == t);
  189. t->alerted = 1;
  190. LEAVECRITICAL;
  191. }
  192. static unsigned __stdcall start(void *p) {
  193. T t = p;
  194. Except_stack = NULL;
  195. Thread_exit((*t->apply)(t->args));
  196. return 0;
  197. }
  198. T Thread_new(int apply(void *), void *args, int nbytes, ...) {
  199. T t;
  200. HANDLE hThread;
  201. assert(root);
  202. assert(apply);
  203. assert(args && nbytes >= 0 || args == NULL);
  204. if (args == NULL)
  205. nbytes = 0;
  206. TRY
  207. t = ALLOC((sizeof (*t) + nbytes + 15)&~15);
  208. memset(t, '', sizeof *t);
  209. EXCEPT(Mem_Failed)
  210. RAISE(Thread_Failed);
  211. END_TRY;
  212. t->join = CreateSemaphore(NULL, 0, INT_MAX, NULL);
  213. if (t->join == NULL) {
  214. FREE(t);
  215. RAISE(Thread_Failed);
  216. }
  217. if (nbytes > 0) {
  218. t->args = t + 1;
  219. memcpy(t->args, args, nbytes);
  220. } else
  221. t->args = args;
  222. t->apply = apply;
  223. hThread = (HANDLE)_beginthreadex(
  224. NULL, /* default security attributes */
  225. 0, /* default stack size */
  226. start, /* initial function */
  227. t, /* start's argument */
  228. 0, /* default thread creation flags */
  229. &t->IDThread /* where to store the thread id */
  230. );
  231. if (hThread == NULL) {
  232. CloseHandle(t->join);
  233. FREE(t);
  234. RAISE(Thread_Failed);
  235. }
  236. CloseHandle(hThread);
  237. addThread(t);
  238. return t;
  239. }
  240. #undef T
  241. #define T Sem_T
  242. T *Sem_new(int count) {
  243. T *s;
  244. NEW(s);
  245. Sem_init(s, count);
  246. return s;
  247. }
  248. void Sem_init(T *s, int count) {
  249. assert(root);
  250. assert(s);
  251. assert(count >= 0);
  252. s->count = 0;
  253. s->queue = CreateSemaphore(NULL, count, INT_MAX, NULL);
  254. assert(s->queue);
  255. }
  256. void Sem_wait(T *s) {
  257. DWORD result;
  258. Thread_T current = Thread_self();
  259. assert(s);
  260. testalert(current);
  261. result = WaitForSingleObject(s->queue, INFINITE);
  262. assert(result != WAIT_FAILED);
  263. ENTERCRITICAL;
  264. if (current->alerted) {
  265. BOOL result;
  266. current->alerted = 0;
  267. LEAVECRITICAL;
  268. result = ReleaseSemaphore(s->queue, 1, NULL);
  269. assert(result == TRUE);
  270. RAISE(Thread_Alerted);
  271. }
  272. LEAVECRITICAL;
  273. }
  274. void Sem_signal(T *s) {
  275. BOOL result;
  276. assert(root);
  277. assert(s);
  278. result = ReleaseSemaphore(s->queue, 1, NULL);
  279. assert(result == TRUE);
  280. }
  281. #undef T