Best way to share data between threads

2005-02-21 Thread Jonathon McKitrick

Hi all,

I'm porting some libraries from Win32 to BSD/Linux.  In the original code, I
receive a Windows event with an attached COM object.

Under *nix, what is the best way to copy this?  A message, followed by
accessing shared memory between threads?

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


Re: Best way to share data between threads

2005-02-21 Thread Giorgos Keramidas
On 2005-02-22 05:50, Jonathon McKitrick <[EMAIL PROTECTED]> wrote:
>
> Hi all,
> I'm porting some libraries from Win32 to BSD/Linux.  In the original
> code, I receive a Windows event with an attached COM object.
>
> Under *nix, what is the best way to copy this?  A message, followed
> by accessing shared memory between threads?

Does the message really have to be shared across many threads?  I'm
only asking because thread-specific message queues are not that hard
to build with pthreads.  You will only need a per-thread queue to hold
messages and a master thread that 'dispatches' messages to the proper
thread/queue.

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


Re: Best way to share data between threads

2005-02-22 Thread Jonathon McKitrick
On Tue, Feb 22, 2005 at 08:38:11AM +0200, Giorgos Keramidas wrote:
: On 2005-02-22 05:50, Jonathon McKitrick <[EMAIL PROTECTED]> wrote:
: >
: > Hi all,
: > I'm porting some libraries from Win32 to BSD/Linux.  In the original
: > code, I receive a Windows event with an attached COM object.
: >
: > Under *nix, what is the best way to copy this?  A message, followed
: > by accessing shared memory between threads?
: 
: Does the message really have to be shared across many threads?  I'm
: only asking because thread-specific message queues are not that hard
: to build with pthreads.  You will only need a per-thread queue to hold
: messages and a master thread that 'dispatches' messages to the proper
: thread/queue.

Well, there will be a data acquisition thread, that when finished, will need
to signal the main processing thread that a new data object has arrived.

Jonathon McKitrick
--
My other computer is your Windows box.
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "[EMAIL PROTECTED]"


Re: Best way to share data between threads

2005-02-22 Thread Giorgos Keramidas
On 2005-02-22 12:19, Jonathon McKitrick <[EMAIL PROTECTED]> wrote:
>On Tue, Feb 22, 2005 at 08:38:11AM +0200, Giorgos Keramidas wrote:
>:On 2005-02-22 05:50, Jonathon McKitrick <[EMAIL PROTECTED]> wrote:
>:>
>:> Hi all,
>:> I'm porting some libraries from Win32 to BSD/Linux.  In the
>:> original code, I receive a Windows event with an attached COM
>:> object.
>:>
>:> Under *nix, what is the best way to copy this?  A message,
>:> followed by accessing shared memory between threads?
>:
>: Does the message really have to be shared across many threads?  I'm
>: only asking because thread-specific message queues are not that
>: hard to build with pthreads.  You will only need a per-thread queue
>: to hold messages and a master thread that 'dispatches' messages to
>: the proper thread/queue.
>
> Well, there will be a data acquisition thread, that when finished,
> will need to signal the main processing thread that a new data
> object has arrived.

There are a couple of ways to do the notification:

1) Explicit notification using a condition variable.

2) No notification at all, but restructuring of the thread
   code to use message queues.

The first can be accomplished by associating a pthread_cond_t with the
data storage area and explicit signalling of the processing thread.
Every time the processing thread has nothing to do (i.e. no data being
processed at the time), it blocks on the condition variable and waits
until the data acquisition thread awakes it.

The second way to solve this is to use minimal synchronization (i.e. a
mutex to protect a common message queue) and a queue of currently
pending messages.  The data acquisition thread gets a copy of the data
and pushes it on the queue, leaving all further work to the processing
thread.  The processing threads awakes periodically, "polling" for new
messages in the queue.  When one is found, it is immediately processed.
When no message is found, the processing thread sleeps for a small
amount of time.

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


Re: Best way to share data between threads

2005-02-22 Thread Jonathon McKitrick
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.


Jonathon McKitrick
--
My other computer is your Windows box.
___
freebsd-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "[EMAIL PROTECTED]"


Re: Best way to share data between threads

2005-02-22 Thread Giorgos Keramidas
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]"