-
Notifications
You must be signed in to change notification settings - Fork 5
prepare,check and idle
paulran edited this page Apr 6, 2016
·
2 revisions
int uv_run(uv_loop_t* loop, uv_run_mode mode) {
int timeout;
int r;
int ran_pending;
r = uv__loop_alive(loop);
if (!r)
uv__update_time(loop);
while (r != 0 && loop->stop_flag == 0) {
uv__update_time(loop);
uv__run_timers(loop);
ran_pending = uv__run_pending(loop);
uv__run_idle(loop);
uv__run_prepare(loop);
timeout = 0;
if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
timeout = uv_backend_timeout(loop);
uv__io_poll(loop, timeout);
uv__run_check(loop);
uv__run_closing_handles(loop);
if (mode == UV_RUN_ONCE) {
/* UV_RUN_ONCE implies forward progress: at least one callback must have
* been invoked when it returns. uv__io_poll() can return without doing
* I/O (meaning: no callbacks) when its timeout expires - which means we
* have pending timers that satisfy the forward progress constraint.
*
* UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from
* the check.
*/
uv__update_time(loop);
uv__run_timers(loop);
}
r = uv__loop_alive(loop);
if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
break;
}
/* The if statement lets gcc compile it to a conditional store. Avoids
* dirtying a cache line.
*/
if (loop->stop_flag != 0)
loop->stop_flag = 0;
return r;
}
Notes:
- uv__run_prepare(loop), uv__run_check(loop) and uv__run_idle(loop) run at different points in time. This allows users to add their own needs callback functions.
- Interface is defined in the file src/unix/loop-watcher.c.
- Reference to Design overview#The I/O loop.
int uv_prepare_init(uv_loop_t* loop, uv_prepare_t* handle)
{
uv__handle_init(loop, (uv_handle_t* )handle, UV_PREPARE);
handle->prepare_cb = NULL;
return 0;
}
int uv_prepare_start(uv_prepare_t* handle, uv_prepare_cb cb)
{
if (uv__is_active(handle))
return 0;
if (cb == NULL)
return -EINVAL;
QUEUE_INSERT_HEAD(&handle->loop->prepare_handles, &handle->queue);
handle->prepare_cb = cb;
uv__handle_start(handle);
return 0;
}
int uv_prepare_stop(uv_prepare_t* handle)
{
if (!uv__is_active(handle))
return 0;
QUEUE_REMOVE(&handle->queue);
uv__handle_stop(handle);
return 0;
}
void uv__run_prepare(uv_loop_t* loop)
{
uv_prepare_t* h;
QUEUE queue;
QUEUE* q;
QUEUE_MOVE(&loop->prepare_handles, &queue);
while (!QUEUE_EMPTY(&queue))
{
q = QUEUE_HEAD(&queue);
h = QUEUE_DATA(q, uv_prepare_t, queue);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->prepare_handles, q);
h->prepare_cb(h);
}
}
void uv__prepare_close(uv_prepare_t* handle)
{
uv_prepare_stop(handle);
}
int uv_check_init(uv_loop_t* loop, uv_check_t* handle)
{
uv__handle_init(loop, (uv_handle_t* )handle, UV_CHECK);
handle->check_cb = NULL;
return 0;
}
int uv_check_start(uv_check_t* handle, uv_check_cb cb)
{
if (uv__is_active(handle))
return 0;
if (cb == NULL)
return -EINVAL;
QUEUE_INSERT_HEAD(&handle->loop->check_handles, &handle->queue);
handle->check_cb = cb;
uv__handle_start(handle);
return 0;
}
int uv_check_stop(uv_check_t* handle)
{
if (!uv__is_active(handle))
return 0;
QUEUE_REMOVE(&handle->queue);
uv__handle_stop(handle);
return 0;
}
void uv__run_check(uv_loop_t* loop)
{
uv_check_t* h;
QUEUE queue;
QUEUE* q;
QUEUE_MOVE(&loop->check_handles, &queue);
while (!QUEUE_EMPTY(&queue))
{
q = QUEUE_HEAD(&queue);
h = QUEUE_DATA(q, uv_check_t, queue);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->check_handles, q);
h->check_cb(h);
}
}
void uv__check_close(uv_check_t* handle)
{
uv_check_stop(handle);
}
int uv_idle_init(uv_loop_t* loop, uv_idle_t* handle)
{
uv__handle_init(loop, (uv_handle_t* )handle, UV_IDLE);
handle->idle_cb = NULL;
return 0;
}
int uv_idle_start(uv_idle_t* handle, uv_idle_cb cb)
{
if (uv__is_active(handle))
return 0;
if (cb == NULL)
return -EINVAL;
QUEUE_INSERT_HEAD(&handle->loop->idle_handles, &handle->queue);
handle->idle_cb = cb;
uv__handle_start(handle);
return 0;
}
int uv_idle_stop(uv_idle_t* handle)
{
if (!uv__is_active(handle))
return 0;
QUEUE_REMOVE(&handle->queue);
uv__handle_stop(handle);
return 0;
}
void uv__run_idle(uv_loop_t* loop)
{
uv_idle_t* h;
QUEUE queue;
QUEUE* q;
QUEUE_MOVE(&loop->idle_handles, &queue);
while (!QUEUE_EMPTY(&queue))
{
q = QUEUE_HEAD(&queue);
h = QUEUE_DATA(q, uv_idle_t, queue);
QUEUE_REMOVE(q);
QUEUE_INSERT_TAIL(&loop->idle_handles, q);
h->idle_cb(h);
}
}
void uv__idle_close(uv_idle_t* handle)
{
uv_idle_stop(handle);
}