[libdispatch-dev] libdispatch's thread model
Mark Heily
mark at heily.com
Wed Jan 27 19:32:32 PST 2010
Mario Schwalbe wrote:
> I know that Apple's non-posix extension to pthread isn't available.
> Nevertheless, it should be possible to at least use a bounded number of
> worker threads less than MAX_THREAD_COUNT (255). What about dynamically
> setting MAX_THREAD_COUNT (or a similar variable) to the number of
> processors
> instead?
>
A more useful solution would be to create a portable implementation of the
Apple's pthread_workqueue interfaces [1]. This has been on my TODO list for
some time, and I filed a Trac issue about this problem [2].
I don't really want to reinvent the wheel, so my first attempt will use the
APR thread pool routines [3]. To prevent deadlock, each workqueue will be
serviced by a separate thread pool. This won't scale to large numbers of
workqueues, and makes it impossible to implement priority levels, but it
should be simple and work better than creating a new thread for each task.
Stacy Son has kindly documented the pthread_workqueue(3) API which should be
very helpful to get the correct semantics [4]. I have taken a stab at
implementing the most important functions, and it looks promising [5].
Regards,
- Mark
[1]
datatypes:
pthread_workqueue_t
pthread_workqueue_attr_t
functions:
pthread_workqueue_init_np
pthread_workqueue_attr_init_np
pthread_workqueue_attr_destroy_np
pthread_workqueue_attr_setqueuepriority_np
pthread_workqueue_attr_setovercommit_np
pthread_workqueue_create_np
pthread_workqueue_additem_np
[2] http://libdispatch.macosforge.org/trac/ticket/2
[3] http://apr.apache.org/docs/apr/trunk/group___a_p_r___util___t_p.html
[4]
http://people.freebsd.org/~sson/thrworkq/pthread_workqueue_2009_12_14.diff
[5]
#include <pthread.h>
#include <apr-1.0/apr_thread_pool.h>
#define pthread_workqueue_t apr_thread_pool_t
static pthread_once_t init_once = PTHREAD_ONCE_INIT;
static apr_pool_t *mpool;
static int
_pthread_workqueue_init(void)
{
return (apr_pool_create(&mpool, NULL) == APR_OK ? 0 : -1);
}
int
pthread_workqueue_init_np(void)
{
pthread_once(_pthread_workqueue_init, init_once);
}
int
pthread_workqueue_create_np(
pthread_workqueue_t *workqp,
const pthread_workqueue_attr_t *attr)
{
return (apr_thread_pool_create(workqp, 1, 255, mpool) == APR_OK ? 0 : -1);
}
int
pthread_workqueue_additem_np(
pthread_workqueue_t workq,
void ( *workitem_func)(void *),
void * workitem_arg,
pthread_workitem_handle_t * itemhandlep,
unsigned int *gencountp)
{
int rv;
rv = apr_thread_pool_push(workq, workitem_func, workitem_arg,
APR_THREAD_TASK_PRIORITY_NORMAL, NULL);
/* FIXME - Hope these aren't actually used :) */
*itemhandlep = NULL;
*gencountp = 0;
return (rv == APR_OK ? 0 : -1);
}
More information about the libdispatch-dev
mailing list