machinarium: implement mm_condition/mm_signal functions

This commit is contained in:
Dmitry Simonenko 2017-02-01 15:57:15 +03:00
parent 765d7f0e94
commit 7b08be8d08
3 changed files with 62 additions and 0 deletions

View File

@ -176,3 +176,61 @@ mm_cancel(mm_t envp, uint64_t id)
mm_fiber_cancel(fiber);
return 0;
}
static void
mm_condition_timer_cb(uv_timer_t *handle)
{
mmfiber *fiber = handle->data;
assert(fiber->condition);
fiber->condition_status = -ETIMEDOUT;
mm *f = fiber->data;
mm_wakeup(f, fiber);
}
static inline void
mm_condition_cancel_cb(mmfiber *fiber, void *arg)
{
(void)arg;
uv_timer_stop(&fiber->timer);
uv_handle_t *handle = (uv_handle_t*)&fiber->timer;
if (! uv_is_closing(handle))
uv_close(handle, NULL);
assert(fiber->condition);
fiber->condition_status = -ECANCELED;
mm *f = fiber->data;
mm_wakeup(f, fiber);
}
MM_API int
mm_condition(mm_t envp, uint64_t time_ms)
{
mm *env = envp;
mmfiber *fiber = mm_scheduler_current(&env->scheduler);
if (mm_fiber_is_cancel(fiber))
return -ECANCELED;
fiber->condition = 1;
fiber->condition_status = -1;
uv_timer_start(&fiber->timer, mm_condition_timer_cb, time_ms, 0);
mm_fiber_op_begin(fiber, mm_condition_cancel_cb, NULL);
mm_scheduler_yield(&env->scheduler);
mm_fiber_op_end(fiber);
fiber->condition = 0;
return fiber->condition_status;
}
MM_API int
mm_signal(mm_t envp, uint64_t id)
{
mm *env = envp;
mmfiber *fiber = mm_scheduler_match(&env->scheduler, id);
if (fiber == NULL)
return -1;
if (! fiber->condition)
return -1;
uv_timer_stop(&fiber->timer);
uv_handle_t *handle = (uv_handle_t*)&fiber->timer;
if (! uv_is_closing(handle))
uv_close(handle, NULL);
fiber->condition_status = 0;
mm_wakeup(env, fiber);
return 0;
}

View File

@ -11,6 +11,8 @@ void mm_fiber_init(mmfiber *fiber)
{
memset(fiber, 0, sizeof(mmfiber));
fiber->state = MM_FNEW;
fiber->condition = 0;
fiber->condition_status = 0;
mm_fiber_op_end(fiber);
mm_listinit(&fiber->waiters);
mm_listinit(&fiber->link);

View File

@ -36,6 +36,8 @@ struct mmfiber {
mmcontext context;
mmfiber *resume;
uv_timer_t timer;
int condition;
int condition_status;
void *scheduler;
void *data;
mmlist waiters;