ThreadPool callbacks provide more parameters
Now allows up to two void * and two int parameters.
This will be needed by deferred application-level callbacks
Change-Id: Ie388169439b2e3ab95d053007bcdc674b875fa67
diff --git a/src/ThreadPool.c b/src/ThreadPool.c
index 587d260..da9cf7e 100644
--- a/src/ThreadPool.c
+++ b/src/ThreadPool.c
@@ -27,15 +27,40 @@
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 @@
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 @@
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);
+}
diff --git a/src/ThreadPool.h b/src/ThreadPool.h
index 3dcb318..5da7fa9 100644
--- a/src/ThreadPool.h
+++ b/src/ThreadPool.h
@@ -16,12 +16,30 @@
/** \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 @@
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);
diff --git a/src/itf/IDynamicInterfaceManagement.c b/src/itf/IDynamicInterfaceManagement.c
index 4511c70..e810c85 100644
--- a/src/itf/IDynamicInterfaceManagement.c
+++ b/src/itf/IDynamicInterfaceManagement.c
@@ -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 @@
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 @@
// 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 @@
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
diff --git a/src/itf/IObject.c b/src/itf/IObject.c
index 9257c75..f87c941 100644
--- a/src/itf/IObject.c
+++ b/src/itf/IObject.c
@@ -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 @@
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 @@
// 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 @@
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);