#include "ace/Message_Queue.h"
#include "ace/Thread_Manager.h"
#include "ace/Synch_Traits.h"
typedef ACE_Message_Queue<ACE_MT_SYNCH> MT_Message_Queue;
// Global thread manager.
static ACE_Thread_Manager thr_mgr;
static int producer (MT_Message_Queue *msg_queue)
{
// Insert thread into thr_mgr.
ACE_Thread_Control tc (&thr_mgr);
char buf[BUFSIZ];
for (int n; ; )
{
// Allocate a new message.
ACE_Message_Block *mb = new ACE_Message_Block (BUFSIZ);
n = read (0, mb->rd_ptr (), mb->size ());
if (n <= 0)
{
// Shutdown message to the other
// thread and exit.
mb->length (0);
msg_queue->enqueue_tail (mb);
}
// Send the message to the other thread.
else
{
mb->wr_ptr (n);
msg_queue->enqueue_tail (mb);
}
}
// The destructor of Thread_Control removes
// the exiting thread from the
// Thread_Manager automatically.
return 0;
}
static int consumer(MT_Message_Queue *msg_queue)
{
ACE_Message_Block *mb = 0;
// Insert thread into thr_mgr.
ACE_Thread_Control tc (&thr_mgr);
int result = 0;
// Keep looping, reading a message out
// of the queue, until we timeout or get a
// message with a length == 0, which signals
// us to quit.
for (;;)
{
result = msg_queue->dequeue_head (mb);
if (result == -1)
return -1;
int length = mb->length ();
if (length > 0)
::write (1, mb->rd_ptr (), length);
delete mb;
if (length == 0)
break;
}
// The destructor of Thread_Control removes
// the exiting thread from the
// Thread_Manager automatically.
return 0;
}
int main (int argc, char *argv[])
{
// Use the thread-safe instantiation
// of Message_Queue.
MT_Message_Queue msg_queue;
thr_mgr.spawn (ACE_THR_FUNC (&producer),
(void *) &msg_queue,
THR_NEW_LWP | THR_DETACHED);
thr_mgr.spawn (ACE_THR_FUNC (&consumer),
(void *) &msg_queue,
THR_NEW_LWP | THR_DETACHED);
// Wait for producer/consumer threads to exit.
thr_mgr.wait ();
return 0;
}