OSDN Git Service

Add temporary callbacked wrapper for module startup
authorZach Johnson <zachoverflow@google.com>
Sun, 28 Sep 2014 22:46:25 +0000 (15:46 -0700)
committerAndre Eisenbach <eisenbach@google.com>
Mon, 16 Mar 2015 23:51:35 +0000 (16:51 -0700)
When all is said and done with the module conversions, all lifecycle functions
will run on the lifecycle managment thread, which can be blocked while waiting
for futures.

This CL means new modules can depend on that fact during start_up, alllowing
newly converted modules to be spliced into the existing startup callback madness
without having to sacrifice clean implementation.

We can add other callbacked lifecycle function variants as necessary.

btcore/include/module.h
btcore/src/module.c

index 2a0cf09..5259bfc 100644 (file)
@@ -21,6 +21,7 @@
 #include <stdbool.h>
 
 #include "future.h"
+#include "thread.h"
 
 typedef future_t *(*module_lifecycle_fn)(void);
 
@@ -53,3 +54,14 @@ void module_shut_down(const module_t *module);
 // If not initialized, does nothing.
 void module_clean_up(const module_t *module);
 
+// Temporary callbacked wrapper for module start up, so real modules can be
+// spliced into the current janky startup sequence. Runs on a separate thread,
+// which terminates when the module start up has finished. When module startup
+// has finished, |callback| is called within the context of |callback_thread|
+// with |FUTURE_SUCCESS| or |FUTURE_FAIL| depending on whether startup succeeded
+// or not.
+void module_start_up_callbacked_wrapper(
+  const module_t *module,
+  thread_t *callback_thread,
+  thread_fn callback
+);
index 1e02f87..494d723 100644 (file)
@@ -168,3 +168,58 @@ static void set_module_state(const module_t *module, module_state_t state) {
 
   *state_ptr = state;
 }
+
+// TODO(zachoverflow): remove when everything modulized
+// Temporary callback-wrapper-related code
+
+typedef struct {
+  const module_t *module;
+  thread_t *lifecycle_thread;
+  thread_t *callback_thread; // we don't own this thread
+  thread_fn callback;
+  bool success;
+} callbacked_wrapper_t;
+
+static void run_wrapped_start_up(void *context);
+static void post_result_to_callback(void *context);
+
+void module_start_up_callbacked_wrapper(
+    const module_t *module,
+    thread_t *callback_thread,
+    thread_fn callback) {
+  callbacked_wrapper_t *wrapper = osi_calloc(sizeof(callbacked_wrapper_t));
+
+  wrapper->module = module;
+  wrapper->lifecycle_thread = thread_new("module_wrapper");
+  wrapper->callback_thread = callback_thread;
+  wrapper->callback = callback;
+
+  // Run the actual module start up
+  thread_post(wrapper->lifecycle_thread, run_wrapped_start_up, wrapper);
+}
+
+static void run_wrapped_start_up(void *context) {
+  assert(context);
+
+  callbacked_wrapper_t *wrapper = context;
+  wrapper->success = module_start_up(wrapper->module);
+
+  // Post the result back to the callback
+  thread_post(wrapper->callback_thread, post_result_to_callback, wrapper);
+}
+
+static void post_result_to_callback(void *context) {
+  assert(context);
+
+  callbacked_wrapper_t *wrapper = context;
+
+  // Save the values we need for callback
+  void *result = wrapper->success ? FUTURE_SUCCESS : FUTURE_FAIL;
+  thread_fn callback = wrapper->callback;
+
+  // Clean up the resources we used
+  thread_stop(wrapper->lifecycle_thread);
+  osi_free(wrapper);
+
+  callback(result);
+}