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);
+}