On 2005-02-23 03:58, Jonathon McKitrick <[EMAIL PROTECTED]> wrote:
>On Tue, Feb 22, 2005 at 02:42:44PM +0200, Giorgos Keramidas wrote:
>:      1) Explicit notification using a condition variable.
>:
>: The first can be accomplished by associating a pthread_cond_t with the
>
> I think this is the approach I will use.  As a matter of fact, I added it
> today for a different, more limited use, and it worked well.  We have an
> instrument that needs firmware ftp'ed to it after a cold start, and I placed
> that into a pthread.  I'll try the data acq thread soon.
>
> The only problem is that pthread_join doesn't seem to have a timeout
> feature.  So if the thread hangs, I have no way of knowing.

True.  I usually get around this by polling on a thread flag until its
state changes as expected or a timeout occurs.

        struct thread_data {
                pthread_mutex_t td_lock;
                pthread_t       td_id;
                int             td_flags;
        };

        #define TDF_SPAWNING    (1<<0)          /* Thread is now spawning   */
        #define TDF_ACTIVE      (1<<1)          /* If set, thread is active */
        #define TDF_CLOSE       (1<<2)          /* If set, thread closes    */
        #define TDF_CLOSING     (1<<3)          /* Thread in close process  */

The main thread that needs to know if a thread is active, keeps a list
of thread_data structures around and passes pointers to these structures
to pthread_create() as the thread 'arg'.

Before calling pthread_create(), the main thread initializes a new
thread_data structure and sets its TDF_SPAWNING flag.  This way, even if
the spawned thread takes a long time to start, the thread_data won't be
ripped off from under its feet while it is still spawning.

Then pthread_create() starts the new thread:

        struct thread_data *td;

        if (pthread_create(&(td->td_id), NULL, thread_main, td) != 0)
                die();

The pthread_main() function takes care of changing the state of the
thread_data from TDF_SPAWNING to TDF_ACTIVE:

        void *
        thread_main(void *arg)
        {
                struct thread_data *td = (struct thread_data *)arg;

                if (td == NULL)
                        return (NULL);
                if (pthread_mutex_lock(&(td->td_lock)) != 0)
                        return (NULL);

                td->td_flags |= TDF_ACTIVE;
                td->td_flags &= ~(TDF_SPAWNING);

                if (pthread_mutex_unlock(&(td->td_lock)) != 0)
                        panic();

Then the thread_main() function can go on doing other things, waiting
for its TDF_CLOSE flag to be set.  That is an indication that the thread
should start cleaning up and stop running.  As soon as the thread
notices TDF_CLOSE is set, it locks thread_data, sets TDF_CLOSING and
clears TDF_CLOSE.  Then thread_data can be unlocked again, the thread
can clean up, eventually ending up at the final part:

        if (pthread_mutex_lock(&(td->td_lock)) != 0)
                error();
        td->td_flags &= ~(TDF_ACTIVE | TDF_CLOSING);
        if (pthread_mutex_unlock(&(td->td_lock)) != 0)
                error();
        return (arg);

Done.  The fact that TDF_ACTIVE is no longer set, means that the thread
has already exited, so its safe to call pthread_join() on its td->td_id
and it won't block indefinitely.

- Giorgos

_______________________________________________
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to