title: C++ implementation of a mailbox for inter-thread communication
body: <p>I'm wondering if anyone has previously implemented a mailbox class for interthread communication using the POSIX library. For reference, I'm looking similar to mailboxes used in SystemVerilog: <a href="http://www.asic-world.com/systemverilog/sema_mail_events2.html" rel="nofollow">http://www.asic-world.com/systemverilog/sema_mail_events2.html</a></p>
  
  <p><strong>EDIT</strong>:</p>
  
  <p>My attempt at a mailbox using STL queues, pthread conditions, and mutexes. It tries to copy the behavior of the SystemVerilog mailbox described in the link:</p>
  
  <pre><code>#include &lt;cerrno&gt;
  #include &lt;climits&gt;
  #include &lt;cstdio&gt;
  #include &lt;cstdlib&gt;
  #include &lt;cstring&gt;
  #include &lt;queue&gt;
  
  #include &lt;fcntl.h&gt;
  #include &lt;pthread.h&gt;
  #include &lt;sys/select.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;unistd.h&gt;
  
  using namespace std;
  
  class Mailbox{
  
      private:
          pthread_cond_t  msg_available;  // Message in the mailbox?
          pthread_mutex_t queue_mutex;    // Mutex for queue control
  
          queue&lt;messageT&gt; messages;       // Messages
  
      public:
          // Constructor
          Mailbox(void){
              msg_available = PTHREAD_COND_INITIALIZER;
              queue_mutex = PTHREAD_MUTEX_INITIALIZER;
          }
          // Destructor
          ~Mailbox(void){
              // Nothing to do here
          }
  
          // Put a single message into the mailbox
          void put(messageT msg){
  
              // Lock down queue
              if(pthread_mutex_lock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Lock Error\n");
                  exit(EXIT_FAILURE);
              }
  
              // Push message into mailbox
              messages.push(msg);
  
              // Signal there is a message in the mailbox
              if(pthread_cond_signal(&amp;msg_available)){                    
                  fprintf(stderr, "cond error");
                  exit(EXIT_FAILURE);
              }
  
              // Unlock queue
              if(pthread_mutex_unlock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Unlock Error\n");
                  exit(EXIT_FAILURE);
              }
          }
  
          // Try to put a single message into the mailbox
          int try_put(messageT msg){
  
              // Try to lock down queue
              if(pthread_mutex_trylock(queue_mutex) == 0){
  
                  // Push message into mailbox
                  messages.push(msg);
  
                  // Signal there is a message in the mailbox
                  if(pthread_cond_signal(&amp;msg_available)){                    
                      fprintf(stderr, "cond error");
                      exit(EXIT_FAILURE);
                  }
  
                  // Unlock queue
                  if(pthread_mutex_unlock(queue_mutex)){
                      fprintf(stderr, "Queue Mutex Unlock Error\n");
                      exit(EXIT_FAILURE);
                  }
  
                  return 1;
              }
              // Otherwise, say mailbox is unavailable
              else
                  return 0;
          }
  
          //  Get single message from a mailbox
          void get(mesageT *msg){
  
              // Lock down queue
              if(pthread_mutex_lock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Lock Error\n");
                  exit(EXIT_FAILURE);
              }
  
              // Wait for a message to come in
              while(messages.empty()){
                  // Release hold of the lock until another thread
                  // signals that a message has been placed
                  if(pthread_cond_wait(&amp;msg_available,&amp;queue_mutex)){                 
                      fprintf(stderr, "cond_wait error");
                      exit(EXIT_FAILURE);
                  }
              }
  
              // Pop of least recent message
              *msg = messages.front();
              messages.pop();
  
              // Unlock queue
              if(pthread_mutex_unlock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Unlock Error\n");
                  exit(EXIT_FAILURE);
              }
  
          }
  
          //  Try to get single message from a mailbox
          int try_get(mesageT *msg){
  
              int mailbox_ready = 1;  // Mailbox ready
  
              // Lock down queue
              if(pthread_mutex_lock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Lock Error\n");
                  exit(EXIT_FAILURE);
              }
  
              // Indicate if mailbox is empty
              if(messages.empty())
                  mailbox_ready = 0
              // Otherwise, grab the message
              else {
                  // Pop of least recent message
                  *msg = messages.front();
                  messages.pop();
              }
  
              // Unlock queue
              if(pthread_mutex_unlock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Unlock Error\n");
                  exit(EXIT_FAILURE);
              }
  
              return mailbox_ready;
          }
  
          //  Peek at single message from a mailbox
          void peek(mesageT *msg){
  
              // Lock down queue
              if(pthread_mutex_lock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Lock Error\n");
                  exit(EXIT_FAILURE);
              }
  
              // Wait for a message to come in
              while(messages.empty()){
                  // Release hold of the lock until another thread
                  // signals that a message has been placed
                  if(pthread_cond_wait(&amp;msg_available,&amp;queue_mutex)){                 
                      fprintf(stderr, "cond_wait error");
                      exit(EXIT_FAILURE);
                  }
              }
  
              // Peek at most recent message
              *msg = messages.front();
  
              // Unlock queue
              if(pthread_mutex_unlock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Unlock Error\n");
                  exit(EXIT_FAILURE);
              }
  
          }
  
          //  Try to peek at single message from a mailbox
          int try_peek(mesageT *msg){
  
              int mailbox_ready = 1;  // Mailbox ready
  
              // Lock down queue
              if(pthread_mutex_lock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Lock Error\n");
                  exit(EXIT_FAILURE);
              }
  
              if(messages.empty())    // Indicate if mailbox is empty
                  mailbox_ready = 0
              else                    // Otherwise, grab the message
                  *msg = messages.front();
  
              // Unlock queue
              if(pthread_mutex_unlock(queue_mutex)){
                  fprintf(stderr, "Queue Mutex Unlock Error\n");
                  exit(EXIT_FAILURE);
              }
  
              return mailbox_ready;
          }
  }
  </code></pre>