Check/prepare/idle for windows. No tests yes, so bugs are likely.
This commit is contained in:
parent
8caf485516
commit
6d8aa96ab6
192
oio-win.c
192
oio-win.c
@ -126,6 +126,7 @@ static LPFN_TRANSMITFILE pTransmitFile;
|
|||||||
#define OIO_HANDLE_CONNECTION 0x0010
|
#define OIO_HANDLE_CONNECTION 0x0010
|
||||||
#define OIO_HANDLE_CONNECTED 0x0020
|
#define OIO_HANDLE_CONNECTED 0x0020
|
||||||
#define OIO_HANDLE_READING 0x0040
|
#define OIO_HANDLE_READING 0x0040
|
||||||
|
#define OIO_HANDLE_ACTIVE 0x0040
|
||||||
#define OIO_HANDLE_EOF 0x0080
|
#define OIO_HANDLE_EOF 0x0080
|
||||||
#define OIO_HANDLE_SHUTTING 0x0100
|
#define OIO_HANDLE_SHUTTING 0x0100
|
||||||
#define OIO_HANDLE_SHUT 0x0200
|
#define OIO_HANDLE_SHUT 0x0200
|
||||||
@ -148,6 +149,17 @@ RB_PROTOTYPE_STATIC(oio_timer_s, oio_req_s, tree_entry, oio_timer_compare);
|
|||||||
static struct oio_timer_s oio_timers_ = RB_INITIALIZER(oio_timers_);
|
static struct oio_timer_s oio_timers_ = RB_INITIALIZER(oio_timers_);
|
||||||
|
|
||||||
|
|
||||||
|
/* Lists of active oio_prepare / oio_check / oio_idle watchers */
|
||||||
|
static oio_handle* oio_prepare_handles_ = NULL;
|
||||||
|
static oio_handle* oio_check_handles_ = NULL;
|
||||||
|
static oio_handle* oio_idle_handles_ = NULL;
|
||||||
|
|
||||||
|
/* This pointer will refer to the prepare/check/idle handle whose callback */
|
||||||
|
/* is scheduled to be called next. This is needed to allow safe removal */
|
||||||
|
/* from one of the lists above while that list being iterated. */
|
||||||
|
static oio_handle* oio_next_loop_handle_ = NULL;
|
||||||
|
|
||||||
|
|
||||||
/* Head of a single-linked list of closed handles */
|
/* Head of a single-linked list of closed handles */
|
||||||
static oio_handle* oio_endgame_handles_ = NULL;
|
static oio_handle* oio_endgame_handles_ = NULL;
|
||||||
|
|
||||||
@ -496,6 +508,20 @@ static void oio_tcp_endgame(oio_handle* handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void oio_loop_endgame(oio_handle* handle) {
|
||||||
|
if (handle->flags & OIO_HANDLE_CLOSING) {
|
||||||
|
assert(!(handle->flags & OIO_HANDLE_CLOSED));
|
||||||
|
handle->flags |= OIO_HANDLE_CLOSED;
|
||||||
|
|
||||||
|
if (handle->close_cb) {
|
||||||
|
handle->close_cb(handle, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
oio_refs_--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void oio_call_endgames() {
|
static void oio_call_endgames() {
|
||||||
oio_handle* handle;
|
oio_handle* handle;
|
||||||
|
|
||||||
@ -510,6 +536,12 @@ static void oio_call_endgames() {
|
|||||||
oio_tcp_endgame(handle);
|
oio_tcp_endgame(handle);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OIO_PREPARE:
|
||||||
|
case OIO_CHECK:
|
||||||
|
case OIO_IDLE:
|
||||||
|
oio_loop_endgame(handle);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
@ -542,6 +574,21 @@ static int oio_close_error(oio_handle* handle, oio_err e) {
|
|||||||
oio_want_endgame(handle);
|
oio_want_endgame(handle);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
case OIO_PREPARE:
|
||||||
|
oio_prepare_stop(handle);
|
||||||
|
oio_want_endgame(handle);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case OIO_CHECK:
|
||||||
|
oio_check_stop(handle);
|
||||||
|
oio_want_endgame(handle);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case OIO_IDLE:
|
||||||
|
oio_idle_stop(handle);
|
||||||
|
oio_want_endgame(handle);
|
||||||
|
return 0;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Not supported */
|
/* Not supported */
|
||||||
assert(0);
|
assert(0);
|
||||||
@ -936,6 +983,137 @@ int64_t oio_now() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_loop_init(oio_handle* handle, oio_close_cb cb, void* data) {
|
||||||
|
handle->data = data;
|
||||||
|
handle->flags = 0;
|
||||||
|
handle->error = oio_ok_;
|
||||||
|
|
||||||
|
oio_refs_++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int oio_loop_start(oio_handle* handle, oio_loop_cb loop_cb,
|
||||||
|
oio_handle** list) {
|
||||||
|
oio_handle* old_head;
|
||||||
|
|
||||||
|
if (handle->flags & OIO_HANDLE_ACTIVE)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
old_head = *list;
|
||||||
|
|
||||||
|
handle->loop_next = old_head;
|
||||||
|
handle->loop_prev = NULL;
|
||||||
|
|
||||||
|
if (old_head) {
|
||||||
|
old_head->loop_prev = handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
*list = handle;
|
||||||
|
|
||||||
|
handle->loop_cb = loop_cb;
|
||||||
|
handle->flags |= OIO_HANDLE_ACTIVE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int oio_loop_stop(oio_handle* handle, oio_handle** list) {
|
||||||
|
if (!(handle->flags & OIO_HANDLE_ACTIVE))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Update loop head if needed */
|
||||||
|
if (*list == handle) {
|
||||||
|
*list = handle->loop_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the iterator-next pointer of needed */
|
||||||
|
if (oio_next_loop_handle_ == handle) {
|
||||||
|
oio_next_loop_handle_ = handle->loop_next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (handle->loop_prev) {
|
||||||
|
handle->loop_prev->loop_next = handle->loop_next;
|
||||||
|
}
|
||||||
|
if (handle->loop_next) {
|
||||||
|
handle->loop_next->loop_prev = handle->loop_prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle->flags &= ~OIO_HANDLE_ACTIVE;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void oio_loop_invoke(oio_handle* list) {
|
||||||
|
oio_handle *handle;
|
||||||
|
|
||||||
|
oio_next_loop_handle_ = list;
|
||||||
|
|
||||||
|
while (oio_next_loop_handle_ != NULL) {
|
||||||
|
handle = oio_next_loop_handle_;
|
||||||
|
oio_next_loop_handle_ = handle->loop_next;
|
||||||
|
|
||||||
|
((oio_loop_cb)handle->loop_cb)(handle, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_prepare_init(oio_handle* handle, oio_close_cb close_cb, void* data) {
|
||||||
|
handle->type = OIO_PREPARE;
|
||||||
|
return oio_loop_init(handle, close_cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_check_init(oio_handle* handle, oio_close_cb close_cb, void* data) {
|
||||||
|
handle->type = OIO_CHECK;
|
||||||
|
return oio_loop_init(handle, close_cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_idle_init(oio_handle* handle, oio_close_cb close_cb, void* data) {
|
||||||
|
handle->type = OIO_IDLE;
|
||||||
|
return oio_loop_init(handle, close_cb, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_prepare_start(oio_handle* handle, oio_loop_cb loop_cb) {
|
||||||
|
assert(handle->type == OIO_PREPARE);
|
||||||
|
return oio_loop_start(handle, loop_cb, &oio_prepare_handles_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_check_start(oio_handle* handle, oio_loop_cb loop_cb) {
|
||||||
|
assert(handle->type == OIO_CHECK);
|
||||||
|
return oio_loop_start(handle, loop_cb, &oio_check_handles_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_idle_start(oio_handle* handle, oio_loop_cb loop_cb) {
|
||||||
|
assert(handle->type == OIO_IDLE);
|
||||||
|
return oio_loop_start(handle, loop_cb, &oio_idle_handles_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_prepare_stop(oio_handle* handle) {
|
||||||
|
assert(handle->type == OIO_PREPARE);
|
||||||
|
return oio_loop_stop(handle, &oio_prepare_handles_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_check_stop(oio_handle* handle) {
|
||||||
|
assert(handle->type == OIO_CHECK);
|
||||||
|
return oio_loop_stop(handle, &oio_check_handles_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int oio_idle_stop(oio_handle* handle) {
|
||||||
|
assert(handle->type == OIO_IDLE);
|
||||||
|
return oio_loop_stop(handle, &oio_idle_handles_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void oio_poll() {
|
static void oio_poll() {
|
||||||
BOOL success;
|
BOOL success;
|
||||||
DWORD bytes;
|
DWORD bytes;
|
||||||
@ -955,6 +1133,8 @@ static void oio_poll() {
|
|||||||
if (oio_refs_ == 0)
|
if (oio_refs_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
oio_loop_invoke(oio_prepare_handles_);
|
||||||
|
|
||||||
oio_update_time();
|
oio_update_time();
|
||||||
|
|
||||||
/* Check if there are any running timers */
|
/* Check if there are any running timers */
|
||||||
@ -982,8 +1162,12 @@ static void oio_poll() {
|
|||||||
&overlapped,
|
&overlapped,
|
||||||
timeout);
|
timeout);
|
||||||
|
|
||||||
/* Call timer callbacks */
|
|
||||||
oio_update_time();
|
oio_update_time();
|
||||||
|
|
||||||
|
/* Call check callbacks */
|
||||||
|
oio_loop_invoke(oio_check_handles_);
|
||||||
|
|
||||||
|
/* Call timer callbacks */
|
||||||
for (req = RB_MIN(oio_timer_s, &oio_timers_);
|
for (req = RB_MIN(oio_timer_s, &oio_timers_);
|
||||||
req != NULL && req->due <= oio_now_;
|
req != NULL && req->due <= oio_now_;
|
||||||
req = RB_MIN(oio_timer_s, &oio_timers_)) {
|
req = RB_MIN(oio_timer_s, &oio_timers_)) {
|
||||||
@ -1134,6 +1318,12 @@ static void oio_poll() {
|
|||||||
oio_want_endgame(handle);
|
oio_want_endgame(handle);
|
||||||
}
|
}
|
||||||
} /* if (overlapped) */
|
} /* if (overlapped) */
|
||||||
|
|
||||||
|
/* Call idle callbacks */
|
||||||
|
while (oio_idle_handles_) {
|
||||||
|
oio_loop_invoke(oio_idle_handles_);
|
||||||
|
oio_call_endgames();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -76,10 +76,16 @@ typedef struct oio_buf {
|
|||||||
struct { oio_tcp_server_fields }; \
|
struct { oio_tcp_server_fields }; \
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define oio_loop_fields \
|
||||||
|
oio_handle* loop_prev; \
|
||||||
|
oio_handle* loop_next; \
|
||||||
|
void* loop_cb;
|
||||||
|
|
||||||
#define oio_handle_private_fields \
|
#define oio_handle_private_fields \
|
||||||
oio_handle* endgame_next; \
|
oio_handle* endgame_next; \
|
||||||
unsigned int flags; \
|
unsigned int flags; \
|
||||||
oio_err error; \
|
oio_err error; \
|
||||||
union { \
|
union { \
|
||||||
struct { oio_tcp_fields }; \
|
struct { oio_tcp_fields }; \
|
||||||
|
struct { oio_loop_fields }; \
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user