@@ -11,10 +11,28 @@ * Alternatively, it may be distributed under the terms of the GNU General * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ + +struct thread_ctx { + void (*function)(id object); + id object; +}; + +static void* +function_wrapper(void *data) +{ + struct thread_ctx *ctx = data; + + pthread_cleanup_push(free, data); + + ctx->function(ctx->object); + + pthread_cleanup_pop(1); + return NULL; +} bool of_thread_attr_init(of_thread_attr_t *attr) { pthread_attr_t pattr; @@ -50,20 +68,22 @@ return true; } bool -of_thread_new(of_thread_t *thread, id (*function)(id), id data, +of_thread_new(of_thread_t *thread, void (*function)(id), id object, const of_thread_attr_t *attr) { bool ret; pthread_attr_t pattr; if (pthread_attr_init(&pattr) != 0) return false; @try { + struct thread_ctx *ctx; + if (attr != NULL) { int policy, minPrio, maxPrio; struct sched_param param; if (attr->priority < 0 || attr->priority > 1) @@ -87,13 +107,19 @@ if (pthread_attr_setstacksize(&pattr, attr->stackSize) != 0) return false; } + + if ((ctx = malloc(sizeof(*ctx))) == NULL) + return false; + + ctx->function = function; + ctx->object = object; ret = (pthread_create(thread, &pattr, - (void*(*)(void*))function, (__bridge void*)data) == 0); + function_wrapper, ctx) == 0); } @finally { pthread_attr_destroy(&pattr); } return ret;