mirror of https://github.com/yandex/odyssey.git
101 lines
2.2 KiB
C
101 lines
2.2 KiB
C
|
|
/*
|
|
* machinarium.
|
|
*
|
|
* cooperative multitasking engine.
|
|
*/
|
|
|
|
#include <machinarium.h>
|
|
#include <machinarium_private.h>
|
|
|
|
static void
|
|
mm_call_timer_cb(mm_timer_t *handle)
|
|
{
|
|
mm_call_t *call = handle->arg;
|
|
call->timedout = 1;
|
|
call->status = ETIMEDOUT;
|
|
if (call->coroutine)
|
|
mm_scheduler_wakeup(&mm_self->scheduler, call->coroutine);
|
|
}
|
|
|
|
static void
|
|
mm_call_cancel_cb(void *obj, void *arg)
|
|
{
|
|
mm_call_t *call = arg;
|
|
(void)obj;
|
|
call->status = ECANCELED;
|
|
if (call->coroutine)
|
|
mm_scheduler_wakeup(&mm_self->scheduler, call->coroutine);
|
|
}
|
|
|
|
void mm_call(mm_call_t *call, mm_calltype_t type, uint32_t time_ms)
|
|
{
|
|
mm_scheduler_t *scheduler;
|
|
scheduler = &mm_self->scheduler;
|
|
mm_clock_t *clock;
|
|
clock = &mm_self->loop.clock;
|
|
|
|
mm_coroutine_t *coroutine;
|
|
coroutine = mm_scheduler_current(scheduler);
|
|
|
|
coroutine->call_ptr = call;
|
|
call->coroutine = coroutine;
|
|
call->type = type;
|
|
call->cancel_function = mm_call_cancel_cb;
|
|
call->arg = call;
|
|
call->timedout = 0;
|
|
call->status = 0;
|
|
if (mm_coroutine_is_cancelled(coroutine)) {
|
|
call->status = ECANCELED;
|
|
call->type = MM_CALL_NONE;
|
|
call->timedout = 0;
|
|
call->coroutine = NULL;
|
|
call->cancel_function = NULL;
|
|
call->arg = NULL;
|
|
coroutine->call_ptr = NULL;
|
|
return;
|
|
}
|
|
|
|
mm_timer_init(&call->timer, mm_call_timer_cb, call, time_ms);
|
|
if (time_ms != UINT32_MAX)
|
|
mm_timer_start(clock, &call->timer);
|
|
mm_scheduler_yield(scheduler);
|
|
mm_timer_stop(&call->timer);
|
|
|
|
call->type = MM_CALL_NONE;
|
|
call->coroutine = NULL;
|
|
call->cancel_function = NULL;
|
|
call->arg = NULL;
|
|
coroutine->call_ptr = NULL;
|
|
|
|
mm_errno_set(call->status);
|
|
}
|
|
|
|
void mm_call_fast(mm_call_t *call, mm_calltype_t type,
|
|
void (*function)(void*),
|
|
void *arg)
|
|
{
|
|
mm_scheduler_t *scheduler;
|
|
scheduler = &mm_self->scheduler;
|
|
|
|
mm_coroutine_t *coroutine;
|
|
coroutine = mm_scheduler_current(scheduler);
|
|
|
|
coroutine->call_ptr = call;
|
|
call->coroutine = NULL; /* not set */
|
|
call->type = type;
|
|
call->cancel_function = mm_call_cancel_cb;
|
|
call->arg = call;
|
|
call->timedout = 0;
|
|
call->status = 0;
|
|
|
|
function(arg);
|
|
|
|
call->type = MM_CALL_NONE;
|
|
call->cancel_function = NULL;
|
|
call->arg = NULL;
|
|
coroutine->call_ptr = NULL;
|
|
|
|
mm_errno_set(call->status);
|
|
}
|