PageRenderTime 44ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/contrib/lib/lxnet/src/event/win32_eventmgr.c

http://ldb.googlecode.com/
C | 292 lines | 216 code | 39 blank | 37 comment | 37 complexity | d151946601bb28d386b732858b0444db MD5 | raw file
Possible License(s): BSD-3-Clause
  1. /*
  2. * Copyright (C) lcinx
  3. * lcinx@163.com
  4. */
  5. #ifdef WIN32
  6. #include "ossome.h"
  7. #include <assert.h>
  8. #include <stdlib.h>
  9. #include "net_eventmgr.h"
  10. #include "socket_internal.h"
  11. #include "_netsocket.h"
  12. #include <process.h>
  13. #include "log.h"
  14. #ifdef _DEBUG_NETWORK
  15. #define debuglog debug_log
  16. #else
  17. #define debuglog(...) ((void) 0)
  18. #endif
  19. /* event type. */
  20. enum e_socket_ioevent
  21. {
  22. e_socket_io_event_read_complete = 0, /* read operate. */
  23. e_socket_io_event_write_end, /* write operate. */
  24. e_socket_io_thread_shutdown, /* stop iocp. */
  25. };
  26. struct iocpmgr
  27. {
  28. bool isinit;
  29. bool isrun;
  30. int threadnum;
  31. HANDLE completeport;
  32. };
  33. static struct iocpmgr s_iocp = {false};
  34. /* add socket to event manager. */
  35. void socket_addto_eventmgr (struct socketer *self)
  36. {
  37. /* socket object point into iocp. */
  38. CreateIoCompletionPort((HANDLE)self->sockfd, s_iocp.completeport, (ULONG_PTR)self, 0);
  39. }
  40. /* remove socket from event manager. */
  41. void socket_removefrom_eventmgr (struct socketer *self)
  42. {
  43. }
  44. /* set recv event. */
  45. void socket_setup_recvevent (struct socketer *self)
  46. {
  47. self->recv_event.m_event = e_socket_io_event_read_complete;
  48. if (!PostQueuedCompletionStatus(s_iocp.completeport, 0, (ULONG_PTR)self, &self->recv_event.m_overlap))
  49. {
  50. socketer_close(self);
  51. if (atom_dec(&self->ref) < 1)
  52. {
  53. log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d, connect:%d, deleted:%d", self, (int)self->recvlock, (int)self->sendlock, self->sockfd, (int)self->ref, CURRENT_THREAD, self->connected, self->deleted);
  54. }
  55. }
  56. /*
  57. socket_recvdata(self, NULL, 0);
  58. */
  59. }
  60. /* set recv data. */
  61. void socket_recvdata (struct socketer *self, char *data, int len)
  62. {
  63. DWORD flags = 0;
  64. DWORD w_length = len;
  65. WSABUF buf;
  66. buf.len = len;
  67. buf.buf = data;
  68. assert(self != NULL);
  69. assert(self->recvlock == 1);
  70. if (self->recvlock != 1)
  71. {
  72. log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d, connect:%d, deleted:%d", self, (int)self->recvlock, (int)self->sendlock, self->sockfd, (int)self->ref, CURRENT_THREAD, self->connected, self->deleted);
  73. }
  74. memset(&self->recv_event, 0, sizeof(self->recv_event));
  75. self->recv_event.m_event = e_socket_io_event_read_complete;
  76. if (WSARecv(self->sockfd, &buf, 1, &w_length, &flags, &self->recv_event.m_overlap, 0) == SOCKET_ERROR)
  77. {
  78. /* overlapped operation failed to start. */
  79. if (WSAGetLastError() != WSA_IO_PENDING)
  80. {
  81. debuglog("socket_setup_recvevent error!, error:%d\n", WSAGetLastError());
  82. socketer_close(self);
  83. if (atom_dec(&self->ref) < 1)
  84. {
  85. log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d, connect:%d, deleted:%d", self, (int)self->recvlock, (int)self->sendlock, self->sockfd, (int)self->ref, CURRENT_THREAD, self->connected, self->deleted);
  86. }
  87. }
  88. }
  89. }
  90. /* set send event. */
  91. void socket_setup_sendevent (struct socketer *self)
  92. {
  93. self->send_event.m_event = e_socket_io_event_write_end;
  94. if (!PostQueuedCompletionStatus(s_iocp.completeport, 0, (ULONG_PTR)self, &self->send_event.m_overlap))
  95. {
  96. socketer_close(self);
  97. if (atom_dec(&self->ref) < 1)
  98. {
  99. log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d, connect:%d, deleted:%d", self, (int)self->recvlock, (int)self->sendlock, self->sockfd, (int)self->ref, CURRENT_THREAD, self->connected, self->deleted);
  100. }
  101. }
  102. /*
  103. socket_senddata(self, NULL, 0);
  104. */
  105. }
  106. /* set send data. */
  107. void socket_senddata (struct socketer *self, char *data, int len)
  108. {
  109. DWORD flags = 0;
  110. DWORD w_length = len;
  111. WSABUF buf;
  112. buf.len = len;
  113. buf.buf = data;
  114. assert(self != NULL);
  115. assert(self->sendlock == 1);
  116. if (self->sendlock != 1)
  117. {
  118. log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d, connect:%d, deleted:%d", self, (int)self->recvlock, (int)self->sendlock, self->sockfd, (int)self->ref, CURRENT_THREAD, self->connected, self->deleted);
  119. }
  120. memset(&self->send_event, 0, sizeof(self->send_event));
  121. self->send_event.m_event = e_socket_io_event_write_end;
  122. if (WSASend(self->sockfd, &buf, 1, &w_length, flags, &self->send_event.m_overlap, 0) == SOCKET_ERROR)
  123. {
  124. /* overlapped operation failed to start. */
  125. if (WSAGetLastError() != WSA_IO_PENDING)
  126. {
  127. debuglog("socket_senddata error!, error:%d\n", WSAGetLastError());
  128. socketer_close(self);
  129. if (atom_dec(&self->ref) < 1)
  130. {
  131. log_error("%x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, thread_id:%d, connect:%d, deleted:%d", self, (int)self->recvlock, (int)self->sendlock, self->sockfd, (int)self->ref, CURRENT_THREAD, self->connected, self->deleted);
  132. }
  133. }
  134. }
  135. }
  136. /* iocp work thread function. */
  137. static void _iocp_thread_run (void *data)
  138. {
  139. struct iocpmgr *mgr = (struct iocpmgr *)data;
  140. HANDLE cp = mgr->completeport; /* complete port handle. */
  141. DWORD len = 0; /* len variable is real transfers byte size. */
  142. ULONG_PTR s = (ULONG_PTR)NULL; /* call = CreateIoCompletionPort((HANDLE), self->sockfd, s_iocp.completeport, (ULONG_PTR)self, 0); transfers self pointer. */
  143. struct overlappedstruct *ov = NULL;
  144. LPOVERLAPPED ol_ptr = NULL; /* ol_ptr variable is io handle the overlap result, this is actually a very important parameter, because it is used for each I/O data operation .*/
  145. BOOL res;
  146. /*
  147. * 10000 --- wait time. ms.
  148. * INFINITE --- wait forever.
  149. * */
  150. while (mgr->isrun)
  151. {
  152. ol_ptr = NULL;
  153. s = 0;
  154. ov = NULL;
  155. len = 0;
  156. res = GetQueuedCompletionStatus(cp, &len, &s, &ol_ptr, INFINITE/*10000*/);
  157. debuglog("res:%d, ol_ptr:%x, s:%x\n", res, ol_ptr, s);
  158. if ((ol_ptr) && (s))
  159. {
  160. ov = CONTAINING_RECORD(ol_ptr, struct overlappedstruct, m_overlap);
  161. switch (ov->m_event)
  162. {
  163. case e_socket_io_event_read_complete: /* recv. */
  164. {
  165. if (((struct socketer *)s)->recvlock != 1)
  166. {
  167. log_error("res:%d, %x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, len:%d, thread_id:%d, error:%d, connect:%d, deleted:%d", res, ((struct socketer *)s), (int)((struct socketer *)s)->recvlock, (int)((struct socketer *)s)->sendlock, ((struct socketer *)s)->sockfd, (int)((struct socketer *)s)->ref, (int)len, CURRENT_THREAD, WSAGetLastError(), ((struct socketer *)s)->connected, ((struct socketer *)s)->deleted);
  168. }
  169. debuglog("read handle complete! line:%d thread_id:%d\n", __LINE__, CURRENT_THREAD);
  170. socketer_on_recv((struct socketer *)s, (int)len);
  171. }
  172. break;
  173. case e_socket_io_event_write_end: /* send. */
  174. {
  175. if (((struct socketer *)s)->sendlock != 1)
  176. {
  177. log_error("res:%d, %x socket recvlock:%d, sendlock:%d, fd:%d, ref:%d, len:%d, thread_id:%d, error:%d, connect:%d, deleted:%d", res, ((struct socketer *)s), (int)((struct socketer *)s)->recvlock, (int)((struct socketer *)s)->sendlock, ((struct socketer *)s)->sockfd, (int)((struct socketer *)s)->ref, (int)len, CURRENT_THREAD, WSAGetLastError(), ((struct socketer *)s)->connected, ((struct socketer *)s)->deleted);
  178. }
  179. debuglog("send handle complete! line:%d thread_id:%d\n", __LINE__, CURRENT_THREAD);
  180. socketer_on_send((struct socketer *)s, (int)len);
  181. }
  182. break;
  183. case e_socket_io_thread_shutdown:
  184. {
  185. Sleep(100);
  186. free((void*)s);
  187. free(ov);
  188. return;
  189. }
  190. break;
  191. default:
  192. {
  193. log_error("unknow type!.");
  194. }
  195. }
  196. }
  197. }
  198. }
  199. /*
  200. * initialize event manager.
  201. * socketnum --- socket total number. must greater than 1.
  202. * threadnum --- thread number, if less than 0, then start by the number of cpu threads
  203. * */
  204. bool eventmgr_init (int socketnum, int threadnum)
  205. {
  206. if (s_iocp.isinit)
  207. return false;
  208. if (socketnum < 1)
  209. return false;
  210. if (threadnum <= 0)
  211. threadnum = get_cpunum();
  212. s_iocp.threadnum = threadnum;
  213. /* create complete port, fourthly parameter is 0. */
  214. s_iocp.completeport = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, (ULONG_PTR)0, 0);
  215. if (!s_iocp.completeport)
  216. return false;
  217. s_iocp.isinit = true;
  218. s_iocp.isrun = true;
  219. /* create iocp work thread. */
  220. for (; threadnum > 0; --threadnum)
  221. _beginthread(_iocp_thread_run, 0, &s_iocp);
  222. /* initialize windows socket dll*/
  223. {
  224. WSADATA ws;
  225. WSAStartup(MAKEWORD(2,2), &ws);
  226. }
  227. return true;
  228. }
  229. /*
  230. * release event manager.
  231. * */
  232. void eventmgr_release ()
  233. {
  234. int i;
  235. if (!s_iocp.isinit)
  236. return;
  237. for (i = 0; i < s_iocp.threadnum; ++i)
  238. {
  239. struct overlappedstruct *cs;
  240. struct socketer *sock;
  241. cs = (struct overlappedstruct *)malloc(sizeof(struct overlappedstruct));
  242. sock = (struct socketer *)malloc(sizeof(struct socketer));
  243. cs->m_event = e_socket_io_thread_shutdown;
  244. /* let iocp work thread exit. */
  245. PostQueuedCompletionStatus(s_iocp.completeport, 0, (ULONG_PTR)sock, &cs->m_overlap);
  246. }
  247. s_iocp.isrun = false;
  248. s_iocp.isinit = false;
  249. Sleep(500);
  250. CloseHandle(s_iocp.completeport);
  251. WSACleanup();
  252. }
  253. #endif