summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2018-09-23 19:24:30 -0700
committerVito Caputo <vcaputo@pengaru.com>2018-09-23 19:24:30 -0700
commit6d8418dbd0269f2db372902c2d1da7dc1873302b (patch)
treee09f13c04425350c60a020b0b402fae197fa9afe
parent888bc6cc1dbe9433d512224043391d6d051f2b80 (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.c1
-rw-r--r--src/pulp.c31
-rw-r--r--src/pulp.h1
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);
diff --git a/src/pulp.c b/src/pulp.c
index 4459a2c..7f69a4a 100644
--- a/src/pulp.c
+++ b/src/pulp.c
@@ -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;
diff --git a/src/pulp.h b/src/pulp.h
index 0f4ba0d..39a5b67 100644
--- a/src/pulp.h
+++ b/src/pulp.h
@@ -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);
© All Rights Reserved