kqueue/kevent already support that via EVFILT_USER, and Apple's GCD depends on
this extensively. However, my point from my earlier post still stands and I
think it is the right way to implement something like NT's
WaitForMultipleObjects().
--
John Baldwin
He wants something like 'WaitForMultipleObjects()' in NT. The fact that these
are userland primitives is _precisely_ why I think it belongs in the pthread
library. What I think is that you want a pthread primitive that is a wrapper
around a kqueue. Something like:
/* A lot like a 'struct event' */
struct pthread_event {
};
/* Is actually an int to hold a kqueue fd. */
pthread_event_queue_t;
/* Calls kqueue() to create the event. */
pthread_event_queue_init();
/* Similar to the kevent() call, but works with 'struct pthread_event' arrays
instead of 'struct event' arrays. Internally, it maps 'struct pthread_event'
objects to 'struct event' objects to pass to an internal call to kevent().
This code can take care of mapping requests to wait for a cv or mutex to the
appropriate EVFILT_UMTX w/o exposing the EVFILT_UMTX implementation details to
userland. */
pthread_event_queue_wait();
The user code model would look something like this:
pthread_event_queue_t queue;
struct pthread_event event;
pthread_cond_t cv /* some condition variable */
int fd; /* some socket */
pthread_event_queue_init(&queue);
/* This is like EV_SET, maybe you would have a EVQ_SET? */
event.filter = READ;
event.fd = fd;
event.flags = EV_ADD;
/* Register socket. */
pthread_event_queue_wait(queue, NULL, 0, &event, 1, NULL);
event.filter = CONDVAR;
event.cv = cv;
event.flags = EV_ADD;
/* Register condvar. */
pthread_event_queue_wait(queue, NULL, 0, &event, 1, NULL);
/* Wait for something to happen. */
for (;;) {
pthread_event_queue_wait(queue, &event, 1, NULL, 0, NULL);
switch (event.filter) {
case READ:
/* socket is ready to read */
case CV:
/* cv is signalled */
}
}
To be honest, I find semaphores and mutexes more compelling than condvars for
this sort of thing (you would do a try-lock to acquire the mutex or semaphore
perhaps when it is signalled). If you supported thread objects you could do a
pthread_join() after a thread exits.
--
John Baldwin
>>
>
> kqueue/kevent already support that via EVFILT_USER, and Apple's GCD
> depends on
> this extensively. However, my point from my earlier post still
> stands and I
> think it is the right way to implement something like NT's
> WaitForMultipleObjects().
>
> --
> John Baldwin
> _______________________________________________
> freebsd...@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-threads
> To unsubscribe, send any mail to "freebsd-threa...@freebsd.org
> "
>
John:
Is this being MFC'd to 8?
I have an 8.0 machine at work where I am doing a lot of this userland
stuff.. and the
EVFILT_USER is not present but precisely what I need.
R
------------------------------
Randall Stewart
803-317-4952 (cell)
803-345-0391(direct)
It is in stable/8 I thought, just not 8.0 release.
--
John Baldwin
I guess that didn't exist in my 9.0-current that I looked at, so
I replied privately with something very similar ;-) With this
one could wrap pthread objects, semaphores, etc. The wrapper
functions would have to additionally call kevent() to trigger
the event if the object was being waited on in a kqueue, as in:
typedef struct {
#define MY_MTX_IN_KQUEUE 0x0001
int flags;
pthread_mutex_t mutex;
} my_pthread_mutex_t;
my_pthread_mutex_unlock(my_pthread_mutex_t *m)
{
if (m->flags & MY_MTX_IN_KQUEUE) != 0) {
/* Trigger the event. */
kevent(...);
}
ret = pthread_mutex_unlock(m->mutex);
}
--
DE
I thought about doing something like this, but I think it is both kludgey and
racy. It also doesn't fit in nearly as nicely as in Windows where the
standard system objects can be used with WaitForMultipleObjects().
--
John Baldwin