[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