diff options
author | Vito Caputo <vcaputo@pengaru.com> | 2018-09-23 19:24:30 -0700 |
---|---|---|
committer | Vito Caputo <vcaputo@pengaru.com> | 2018-09-23 19:24:30 -0700 |
commit | 6d8418dbd0269f2db372902c2d1da7dc1873302b (patch) | |
tree | e09f13c04425350c60a020b0b402fae197fa9afe | |
parent | 888bc6cc1dbe9433d512224043391d6d051f2b80 (diff) |
libpulp: introduce pulp_init()
Rather than having pulp_tick() on win32 always fiberize/unfiberize the
thread at the start/end of the tick, just fiberize once at library
initialization time.
The old approach was problematic with nested pulp instances. As in,
when a fiber called pulp_tick() on another pulp_t, in scenarios where
the programmer has arranged for a fiber heirarchy of sorts, the nested
pulp_tick() would once again fiberize the already fiberized thread,
then unfiberize, and poof the magic smoke comes out.
Rather than maintaining some kind of reference count and transparently
fiberize vs. getcurrentfiber in pulp_tick(), I'm just introducing the
explicit initialization to address this limitation. This way
pulp_tick() can just always get the current fiber for the calling
context on win32.
The initializer currently does nothing on *nix/ucontext.h systems,
this is just a win32 issue.
-rw-r--r-- | src/example.c | 1 | ||||
-rw-r--r-- | src/pulp.c | 31 | ||||
-rw-r--r-- | src/pulp.h | 1 |
3 files changed, 19 insertions, 14 deletions
diff --git a/src/example.c b/src/example.c index 87c8b73..8c1d3cb 100644 --- a/src/example.c +++ b/src/example.c @@ -58,6 +58,7 @@ int main(int argc, char *argv[]) { pulp_t *p; + pulp_init(); p = pulp_new(); (void) pulp_fiber_new(p, 0, THUNK(foo(p, 40, 100))); pulp_run(p); @@ -311,6 +311,20 @@ static pulp_usec_t now(void) } +/* initialize the pulp library */ +/* Call this prior to calling any other pulp functions. + * Returns 0 on success, negative value on error. + */ +int pulp_init(void) +{ +#ifdef __WIN32__ + if (!ConvertThreadToFiber(NULL)) + return -1; +#endif + return 0; +} + + /* create a new pulp scheduler instance */ pulp_t * pulp_new(void) { @@ -415,21 +429,10 @@ int pulp_tick(pulp_t *pulp, unsigned *next_tick_delay_us) expire_alarms(pulp); #ifdef __WIN32__ - /* XXX: Hopefully it's not too expensive on win32 to become fiberized - * then unfiberized on every tick. I'm doing it this way because - * employing multiple pulp_t instances in the same process is a use - * case I wish to support. There's value in being able to have e.g. - * a set of fibers for one game context which are only ticked when that - * context is active/visible, but otherwise has its state kept around - * in stasis while any number of other pulp_t intances get ticked when - * active. - */ - pulp->caller_context.win32_fiber = ConvertThreadToFiber(NULL); - swap_context(&pulp->caller_context, &pulp->trampoline_context); - ConvertFiberToThread(); -#else - swap_context(&pulp->caller_context, &pulp->trampoline_context); + /* TODO: maybe just move to win32 swap_context()? */ + pulp->caller_context.win32_fiber = GetCurrentFiber(); #endif + swap_context(&pulp->caller_context, &pulp->trampoline_context); if (pulp->exited) return -1; @@ -30,6 +30,7 @@ typedef struct pulp_mailbox_t { void *slots[]; } pulp_mailbox_t; +int pulp_init(void); pulp_t * pulp_new(void); void pulp_free(pulp_t *pulp); int pulp_tick(pulp_t *pulp, unsigned *next_tick_delay_us); |