Re: Using MIG RPC between 2 threads inside a process
Re: Using MIG RPC between 2 threads inside a process
- Subject: Re: Using MIG RPC between 2 threads inside a process
- From: Godfrey van der Linden <email@hidden>
- Date: Thu, 16 Sep 2004 11:18:12 -0700
Basically the solution is to use an internal queue protected by the
mutex and when there is no work to do you use a condition to block the
thread. (This is exactly what we do in the kernel a whole lot ;-)
It is most common to write the queue mechanism in a new class, if you
are doing OO. These queues are extraordinarily easy to write. This
general model is not only efficient but if you do it write the locks on
the queues are the only locks you need in your entire design.
I recommend that you don't allocate any storage in the queue insert
structure, rather your queue is only appending the argument data
structure on the end of a linked list. I usually use the
<kern/queue.h> macros for this, you can copy and paste the macros into
your new class from
/System/Library/Frameworks/Kernel.framework/Headers/kern/queue.h
Below is a rough cut at the implementation of the ObjC class for queues
based upon pthread locking and <kern/queue.h>.
@interface fr_grame_letz_Queue
{
pthread_mutex_t queueLock;
pthread_condition_t queueSleeper;
queue_head_t queueHead;
}
void enqueue: (queue_entry_t) record;
queue_entry_t dequeueAndBlock: (BOOL) block;
@end
@implementation fr_grame_letz_Queue
void enqueue: (queue_entry_t) record
{
// Note no allocation to hold us up - it is assumed that the client
has done the allocation itself
pthread_mutex_lock(&queueLock);
enqueue(&queueHead, record);
pthread_mutex_unlock(&queueLock);
}
queue_entry_t dequeueAndBlock: (BOOL) block
{
queue_entry_t ret = 0;
pthread_mutex_lock(&queueLock)
while (queue_empty(&queueHead)) {
if (!block)
goto abortDequeue;
pthread_cond_wait(&queueSleeper, &queueLock);
}
ret = dequeue(&queueHead);
abortDequeue:
pthread_mutex_unlock(&queueLock);
return 0;
}
@end
The above code is the guts of a queuer but you still have to write the
intialisation and teardown code. This basic model is very, very common
in the kernel and is remarkably efficient.
It works best when you combine the queue with the concept of
'ownership'. That is your 'client' thread allocates the 'record',
initialises it and enqueues it. It agrees that it is not allowed to
deal with the record until it gets returned to it on it's own queue,
the only function that is allowed to operate on it is an 'abort'
function if that is meaninngful.
HTH
Godfrey
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden