machinarium: use fiber id instead of object pointer

This commit is contained in:
Dmitry Simonenko 2017-03-21 16:32:54 +03:00
parent f9d47b9c89
commit 078376c749
6 changed files with 55 additions and 19 deletions

View File

@ -24,7 +24,6 @@
typedef void (*machine_fiber_function_t)(void *arg);
typedef void* machine_t;
typedef void* machine_fiber_t;
typedef void* machine_io_t;
/* machine control */
@ -46,23 +45,23 @@ machine_active(machine_t);
/* fiber */
MACHINE_API machine_fiber_t
MACHINE_API int64_t
machine_create_fiber(machine_t, machine_fiber_function_t, void *arg);
MACHINE_API void
machine_sleep(machine_t, uint64_t time_ms);
MACHINE_API void
machine_wait(machine_fiber_t);
MACHINE_API int
machine_wait(machine_t, uint64_t);
MACHINE_API void
machine_cancel(machine_fiber_t);
MACHINE_API int
machine_cancel(machine_t, uint64_t);
MACHINE_API int
machine_condition(machine_t, uint64_t time_ms);
MACHINE_API int
machine_signal(machine_fiber_t);
machine_signal(machine_t, uint64_t);
MACHINE_API int
machine_cancelled(machine_t);

View File

@ -65,7 +65,7 @@ machine_free(machine_t obj)
return 0;
}
MACHINE_API machine_fiber_t
MACHINE_API int64_t
machine_create_fiber(machine_t obj,
machine_fiber_function_t function,
void *arg)
@ -74,11 +74,11 @@ machine_create_fiber(machine_t obj,
mm_fiber_t *fiber;
fiber = mm_scheduler_new(&machine->scheduler, function, arg);
if (fiber == NULL)
return NULL;
return -1;
uv_timer_init(&machine->loop, &fiber->timer);
fiber->timer.data = fiber;
fiber->data = machine;
return fiber;
return fiber->id;
}
MACHINE_API void
@ -137,20 +137,28 @@ machine_sleep(machine_t obj, uint64_t time_ms)
mm_call_end(&fiber->call);
}
MACHINE_API void
machine_wait(machine_fiber_t obj)
MACHINE_API int
machine_wait(machine_t obj, uint64_t id)
{
mm_fiber_t *fiber = obj;
mm_t *machine = fiber->data;
mm_t *machine = obj;
mm_fiber_t *fiber = mm_scheduler_find(&machine->scheduler, id);
if (fiber == NULL)
return -1;
mm_fiber_t *waiter = mm_scheduler_current(&machine->scheduler);
mm_scheduler_wait(fiber, waiter);
mm_scheduler_yield(&machine->scheduler);
return 0;
}
MACHINE_API void
machine_cancel(machine_fiber_t obj)
MACHINE_API int
machine_cancel(machine_t obj, uint64_t id)
{
mm_fiber_cancel(obj);
mm_t *machine = obj;
mm_fiber_t *fiber = mm_scheduler_find(&machine->scheduler, id);
if (fiber == NULL)
return -1;
mm_fiber_cancel(fiber);
return 0;
}
static void
@ -193,9 +201,12 @@ machine_condition(machine_t obj, uint64_t time_ms)
}
MACHINE_API int
machine_signal(machine_fiber_t obj)
machine_signal(machine_t obj, uint64_t id)
{
mm_fiber_t *fiber = obj;
mm_t *machine = obj;
mm_fiber_t *fiber = mm_scheduler_find(&machine->scheduler, id);
if (fiber == NULL)
return -1;
if (! fiber->condition)
return -1;
uv_timer_stop(&fiber->timer);

View File

@ -11,6 +11,7 @@
void mm_fiber_init(mm_fiber_t *fiber)
{
memset(fiber, 0, sizeof(mm_fiber_t));
fiber->id = UINT64_MAX;
fiber->state = MM_FIBER_NEW;
fiber->condition = 0;
fiber->condition_status = 0;

View File

@ -19,6 +19,7 @@ typedef enum {
} mm_fiberstate_t;
struct mm_fiber_t {
uint64_t id;
mm_fiberstate_t state;
mm_call_t call;
int cancel;

View File

@ -28,6 +28,7 @@ int mm_scheduler_init(mm_scheduler_t *scheduler, int size_stack, void *data)
mm_list_init(&scheduler->list_ready);
mm_list_init(&scheduler->list_active);
mm_list_init(&scheduler->list_free);
scheduler->id_seq = 0;
scheduler->count_ready = 0;
scheduler->count_active = 0;
scheduler->count_free = 0;
@ -80,6 +81,7 @@ mm_scheduler_new(mm_scheduler_t *scheduler, mm_function_t function, void *arg)
fiber->scheduler = scheduler;
}
mm_context_create(fiber->context, mm_scheduler_main, fiber);
fiber->id = scheduler->id_seq++;
fiber->function = function;
fiber->function_arg = arg;
fiber->data = NULL;
@ -87,6 +89,24 @@ mm_scheduler_new(mm_scheduler_t *scheduler, mm_function_t function, void *arg)
return fiber;
}
mm_fiber_t*
mm_scheduler_find(mm_scheduler_t *scheduler, uint64_t id)
{
mm_fiber_t *fiber;
mm_list_t *i;
mm_list_foreach(&scheduler->list_ready, i) {
fiber = mm_container_of(i, mm_fiber_t, link);
if (fiber->id == id)
return fiber;
}
mm_list_foreach(&scheduler->list_active, i) {
fiber = mm_container_of(i, mm_fiber_t, link);
if (fiber->id == id)
return fiber;
}
return NULL;
}
void
mm_scheduler_set(mm_fiber_t *fiber, mm_fiberstate_t state)
{

View File

@ -19,6 +19,7 @@ struct mm_scheduler_t {
mm_list_t list_active;
mm_list_t list_free;
int size_stack;
uint64_t id_seq;
void *data;
};
@ -38,6 +39,9 @@ void mm_scheduler_free(mm_scheduler_t*);
mm_fiber_t*
mm_scheduler_new(mm_scheduler_t*, mm_function_t, void*);
mm_fiber_t*
mm_scheduler_find(mm_scheduler_t*, uint64_t);
void mm_scheduler_set(mm_fiber_t*, mm_fiberstate_t);
void mm_scheduler_call(mm_fiber_t*);
void mm_scheduler_yield(mm_scheduler_t*);