static psckt_t * psckt_setup(psckt_t *sock, void *ctx, psckt_cb_t *callback) { sock->callback = callback; sock->ctx = ctx; sock->ready = sock->released = sock->thread = INVALID_HANDLE_VALUE; sock->finished = sock->waiting = 0; sock->next = psckt_list; psckt_list = sock; if (callback) { DWORD thread_id; sock->ready = CreateEvent(0, 1, 0, 0); /* manual reset */ sock->released = CreateEvent(0, 0, 0, 0); /* auto reset */ sock->thread = CreateThread(NULL, 0, psckt_wait_thread, (LPVOID)sock, 0, &thread_id); /* closing the thread handle does not terminate the thread, it merely * permits the thread to fully terminate whenever psckt_wait_thread * returns * however, since the thread accesses sock->finished, ready, released, * we cannot free sock until the thread finishes */ w_add_input(sock->ready, psckt_cb_manager, sock); w_prepoll(psckt_prepoller, sock, 0); } return sock; }
int mfc_stdinit(void (**wout)(char*,long), void (**werr)(char*,long)) { /* we are in worker thread here */ int result = 1; *wout = *werr = 0; w_sending = CreateEvent(0, 1, 0, 0); if (w_sending) { the_boss.m_pMainWnd->SendMessage(ID_CALL_FUNC, (WPARAM)0, (LPARAM)&mfc_term_init); w_add_input(w_sending, mfc_sender, 0); *wout = mfc_stdout; *werr = mfc_stderr; result = 0; } return result; }
static void psckt_stop_thread(psckt_t *sock) { sock->finished = 1; if (sock->ready != INVALID_HANDLE_VALUE) { /* prevent yorick thread (this thread) from waiting for this socket */ w_add_input(sock->ready, 0, sock); w_prepoll(psckt_prepoller, sock, 1); sock->callback = 0; sock->ctx = 0; } /* this sequence probably will cause psckt_wait_thread to complete * however, nothing guarantees that shutdown will cause select to return, * so it remains possible that thread is blocked in select after this * therefore wait until closesocket to reap thread */ if (sock->fd!=INVALID_SOCKET && sock->released!=INVALID_HANDLE_VALUE) { /* wait thread may be blocked on sock->fd select or sock->released wait */ SetEvent(sock->released); /* wake up wait thread, first way */ shutdown(sock->fd, SD_RECEIVE); /* wake up wait thread, second way */ } }