Check/prepare/idle for windows. No tests yes, so bugs are likely.

This commit is contained in:
Bert Belder 2011-05-08 00:27:12 +02:00
parent 8caf485516
commit 6d8aa96ab6
2 changed files with 197 additions and 1 deletions

192
oio-win.c
View File

@ -126,6 +126,7 @@ static LPFN_TRANSMITFILE pTransmitFile;
#define OIO_HANDLE_CONNECTION 0x0010
#define OIO_HANDLE_CONNECTED 0x0020
#define OIO_HANDLE_READING 0x0040
#define OIO_HANDLE_ACTIVE 0x0040
#define OIO_HANDLE_EOF 0x0080
#define OIO_HANDLE_SHUTTING 0x0100
#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_);
/* 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 */
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() {
oio_handle* handle;
@ -510,6 +536,12 @@ static void oio_call_endgames() {
oio_tcp_endgame(handle);
break;
case OIO_PREPARE:
case OIO_CHECK:
case OIO_IDLE:
oio_loop_endgame(handle);
break;
default:
assert(0);
break;
@ -542,6 +574,21 @@ static int oio_close_error(oio_handle* handle, oio_err e) {
oio_want_endgame(handle);
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:
/* Not supported */
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() {
BOOL success;
DWORD bytes;
@ -955,6 +1133,8 @@ static void oio_poll() {
if (oio_refs_ == 0)
return;
oio_loop_invoke(oio_prepare_handles_);
oio_update_time();
/* Check if there are any running timers */
@ -982,8 +1162,12 @@ static void oio_poll() {
&overlapped,
timeout);
/* Call timer callbacks */
oio_update_time();
/* Call check callbacks */
oio_loop_invoke(oio_check_handles_);
/* Call timer callbacks */
for (req = RB_MIN(oio_timer_s, &oio_timers_);
req != NULL && req->due <= oio_now_;
req = RB_MIN(oio_timer_s, &oio_timers_)) {
@ -1134,6 +1318,12 @@ static void oio_poll() {
oio_want_endgame(handle);
}
} /* if (overlapped) */
/* Call idle callbacks */
while (oio_idle_handles_) {
oio_loop_invoke(oio_idle_handles_);
oio_call_endgames();
}
}

View File

@ -76,10 +76,16 @@ typedef struct oio_buf {
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 \
oio_handle* endgame_next; \
unsigned int flags; \
oio_err error; \
union { \
struct { oio_tcp_fields }; \
struct { oio_loop_fields }; \
};