OSDN Git Service

ThreadPool callbacks provide more parameters
authorGlenn Kasten <gkasten@google.com>
Sun, 10 Jul 2011 17:59:19 +0000 (10:59 -0700)
committerGlenn Kasten <gkasten@google.com>
Mon, 11 Jul 2011 17:17:15 +0000 (10:17 -0700)
Now allows up to two void * and two int parameters.

This will be needed by deferred application-level callbacks

Change-Id: Ie388169439b2e3ab95d053007bcdc674b875fa67

wilhelm/src/ThreadPool.c
wilhelm/src/ThreadPool.h
wilhelm/src/itf/IDynamicInterfaceManagement.c
wilhelm/src/itf/IObject.c

index 587d260..da9cf7e 100644 (file)
@@ -27,15 +27,40 @@ static void *ThreadPool_start(void *context)
     for (;;) {
         Closure *pClosure = ThreadPool_remove(tp);
         // closure is NULL when thread pool is being destroyed
-        if (NULL == pClosure)
+        if (NULL == pClosure) {
             break;
-        void (*handler)(void *, int);
-        handler = pClosure->mHandler;
-        void *context = pClosure->mContext;
-        int parameter = pClosure->mParameter;
+        }
+        // make a copy of parameters, then free the parameters
+        const Closure closure = *pClosure;
         free(pClosure);
-        assert(NULL != handler);
-        (*handler)(context, parameter);
+        // extract parameters and call the right method depending on kind
+        ClosureKind kind = closure.mKind;
+        void *context1 = closure.mContext1;
+        void *context2 = closure.mContext2;
+        int parameter1 = closure.mParameter1;
+        switch (kind) {
+        case CLOSURE_KIND_PPI:
+            {
+            ClosureHandler_ppi handler_ppi;
+            handler_ppi = closure.mHandler.mHandler_ppi;
+            assert(NULL != handler_ppi);
+            (*handler_ppi)(context1, context2, parameter1);
+            }
+            break;
+        case CLOSURE_KIND_PPII:
+            {
+            ClosureHandler_ppii handler_ppii;
+            handler_ppii = closure.mHandler.mHandler_ppii;
+            assert(NULL != handler_ppii);
+            int parameter2 = closure.mParameter2;
+            (*handler_ppii)(context1, context2, parameter1, parameter2);
+            }
+            break;
+        default:
+            SL_LOGE("Unexpected callback kind %d", kind);
+            assert(false);
+            break;
+        }
     }
     return NULL;
 }
@@ -213,17 +238,25 @@ void ThreadPool_deinit(ThreadPool *tp)
     ThreadPool_deinit_internal(tp, tp->mInitialized, tp->mMaxThreads);
 }
 
-// Enqueue a closure to be executed later by a worker thread
-SLresult ThreadPool_add(ThreadPool *tp, void (*handler)(void *, int), void *context, int parameter)
+// Enqueue a closure to be executed later by a worker thread.
+// Note that this raw interface requires an explicit "kind" and full parameter list.
+// There are convenience methods below that make this easier to use.
+SLresult ThreadPool_add(ThreadPool *tp, ClosureKind kind, ClosureHandler_ppii handler,
+        void *context1, void *context2, int parameter1, int parameter2)
 {
     assert(NULL != tp);
     assert(NULL != handler);
     Closure *closure = (Closure *) malloc(sizeof(Closure));
-    if (NULL == closure)
+    if (NULL == closure) {
         return SL_RESULT_RESOURCE_ERROR;
-    closure->mHandler = handler;
-    closure->mContext = context;
-    closure->mParameter = parameter;
+    }
+    closure->mKind = kind;
+    // note this will automagically assign to mHandler_ppi also
+    closure->mHandler.mHandler_ppii = handler;
+    closure->mContext1 = context1;
+    closure->mContext2 = context2;
+    closure->mParameter1 = parameter1;
+    closure->mParameter2 = parameter2;
     int ok;
     ok = pthread_mutex_lock(&tp->mMutex);
     assert(0 == ok);
@@ -315,3 +348,20 @@ Closure *ThreadPool_remove(ThreadPool *tp)
     assert(0 == ok);
     return pClosure;
 }
+
+// Convenience methods for applications
+SLresult ThreadPool_add_ppi(ThreadPool *tp, ClosureHandler_ppi handler,
+        void *context1, void *context2, int parameter1)
+{
+    // function pointers are the same size so this is a safe cast
+    return ThreadPool_add(tp, CLOSURE_KIND_PPI, (ClosureHandler_ppii) handler,
+            context1, context2, parameter1, 0);
+}
+
+SLresult ThreadPool_add_ppii(ThreadPool *tp, ClosureHandler_ppii handler,
+        void *context1, void *context2, int parameter1, int parameter2)
+{
+    // note that no cast is needed for handler because it is already the right type
+    return ThreadPool_add(tp, CLOSURE_KIND_PPII, handler, context1, context2, parameter1,
+            parameter2);
+}
index 3dcb318..5da7fa9 100644 (file)
 
 /** \file ThreadPool.h ThreadPool interface */
 
+/** Kind of closure */
+
+typedef enum {
+    CLOSURE_KIND_PPI,   // void *, void *, int
+    CLOSURE_KIND_PPII   // void *, void *, int, int
+} ClosureKind;
+
+/** Closure handlers */
+
+typedef void (*ClosureHandler_ppi)(void *context1, void *context2, int parameter1);
+typedef void (*ClosureHandler_ppii)(void *context1, void *context2, int parameter1, int parameter2);
+
 /** \brief Closure represents a deferred computation */
 
 typedef struct {
-    void (*mHandler)(void *, int);
-    void *mContext;
-    int mParameter;
+    union {
+        ClosureHandler_ppi mHandler_ppi;
+        ClosureHandler_ppii mHandler_ppii;
+    } mHandler;
+    ClosureKind mKind;
+    void *mContext1;
+    void *mContext2;
+    int mParameter1;
+    int mParameter2;
 } Closure;
 
 /** \brief ThreadPool manages a pool of worker threads that execute Closures */
@@ -52,6 +70,11 @@ typedef struct {
 
 extern SLresult ThreadPool_init(ThreadPool *tp, unsigned maxClosures, unsigned maxThreads);
 extern void ThreadPool_deinit(ThreadPool *tp);
-extern SLresult ThreadPool_add(ThreadPool *tp, void (*handler)(void *, int), void *context,
-    int parameter);
+extern SLresult ThreadPool_add(ThreadPool *tp, ClosureKind kind,
+    void (*handler)(void *, void *, int, int), void *context1,
+    void *context2, int parameter1, int parameter2);
 extern Closure *ThreadPool_remove(ThreadPool *tp);
+extern SLresult ThreadPool_add_ppi(ThreadPool *tp, ClosureHandler_ppi handler,
+    void *context1, void *context2, int parameter1);
+extern SLresult ThreadPool_add_ppii(ThreadPool *tp, ClosureHandler_ppii handler,
+    void *context1, void *context2, int parameter1, int parameter2);
index 4511c70..e810c85 100644 (file)
@@ -22,7 +22,7 @@
 // Called by a worker thread to handle an asynchronous AddInterface.
 // Parameter self is the DynamicInterface, and MPH specifies which interface to add.
 
-static void HandleAdd(void *self, int MPH)
+static void HandleAdd(void *self, void *ignored, int MPH)
 {
 
     // validate input parameters
@@ -135,8 +135,8 @@ static SLresult IDynamicInterfaceManagement_AddInterface(SLDynamicInterfaceManag
                     object_unlock_exclusive(thisObject);
 
                     // this section runs with mutex unlocked
-                    result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleAdd, thiz,
-                        MPH);
+                    result = ThreadPool_add_ppi(&thisObject->mEngine->mThreadPool, HandleAdd, thiz,
+                        NULL, MPH);
                     if (SL_RESULT_SUCCESS != result) {
                         // Engine was destroyed during add, or insufficient memory,
                         // so restore mInterfaceStates state to prior value
@@ -278,7 +278,7 @@ static SLresult IDynamicInterfaceManagement_RemoveInterface(
 // Called by a worker thread to handle an asynchronous ResumeInterface.
 // Parameter self is the DynamicInterface, and MPH specifies which interface to resume.
 
-static void HandleResume(void *self, int MPH)
+static void HandleResume(void *self, void *ignored, int MPH)
 {
 
     // validate input parameters
@@ -383,8 +383,8 @@ static SLresult IDynamicInterfaceManagement_ResumeInterface(SLDynamicInterfaceMa
                     object_unlock_exclusive(thisObject);
 
                     // this section runs with mutex unlocked
-                    result = ThreadPool_add(&thisObject->mEngine->mThreadPool, HandleResume, thiz,
-                        MPH);
+                    result = ThreadPool_add_ppi(&thisObject->mEngine->mThreadPool, HandleResume,
+                        thiz, NULL, MPH);
                     if (SL_RESULT_SUCCESS != result) {
                         // Engine was destroyed during resume, or insufficient memory,
                         // so restore mInterfaceStates state to prior value
index 9257c75..f87c941 100644 (file)
@@ -22,7 +22,7 @@
 // Called by a worker thread to handle an asynchronous Object.Realize.
 // Parameter self is the Object.
 
-static void HandleRealize(void *self, int unused)
+static void HandleRealize(void *self, void *ignored, int unused)
 {
 
     // validate input parameters
@@ -123,7 +123,7 @@ static SLresult IObject_Realize(SLObjectItf self, SLboolean async)
         switch (state) {
         case SL_OBJECT_STATE_REALIZING_1: // asynchronous on non-Engine
             assert(async);
-            result = ThreadPool_add(&thiz->mEngine->mThreadPool, HandleRealize, thiz, 0);
+            result = ThreadPool_add_ppi(&thiz->mEngine->mThreadPool, HandleRealize, thiz, NULL, 0);
             if (SL_RESULT_SUCCESS != result) {
                 // Engine was destroyed during realize, or insufficient memory
                 object_lock_exclusive(thiz);
@@ -165,7 +165,7 @@ static SLresult IObject_Realize(SLObjectItf self, SLboolean async)
 // Called by a worker thread to handle an asynchronous Object.Resume.
 // Parameter self is the Object.
 
-static void HandleResume(void *self, int unused)
+static void HandleResume(void *self, void *ignored, int unused)
 {
 
     // valid input parameters
@@ -251,7 +251,7 @@ static SLresult IObject_Resume(SLObjectItf self, SLboolean async)
         switch (state) {
         case SL_OBJECT_STATE_RESUMING_1: // asynchronous
             assert(async);
-            result = ThreadPool_add(&thiz->mEngine->mThreadPool, HandleResume, thiz, 0);
+            result = ThreadPool_add_ppi(&thiz->mEngine->mThreadPool, HandleResume, thiz, NULL, 0);
             if (SL_RESULT_SUCCESS != result) {
                 // Engine was destroyed during resume, or insufficient memory
                 object_lock_exclusive(thiz);