src/core/unix-system-condition.cc
author Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
Sat, 04 Jul 2009 08:15:48 +0200
changeset 4654 2eaebe77d66b
parent 3425 c69779f5e51e
permissions -rw-r--r--
Added tag ns-3.5 for changeset c975274c9707
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /*
     3  * Copyright (c) 2008 University of Washington
     4  *
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  */
    18 
    19 #include <pthread.h>
    20 #include <errno.h>
    21 #include <sys/time.h>
    22 #include "fatal-error.h"
    23 #include "system-condition.h"
    24 #include "log.h"
    25 
    26 NS_LOG_COMPONENT_DEFINE ("SystemCondition");
    27 
    28 namespace ns3 {
    29 
    30 class SystemConditionPrivate {    
    31 public: 
    32   static const uint64_t NS_PER_SEC = (uint64_t)1000000000;
    33 
    34   SystemConditionPrivate ();
    35   ~SystemConditionPrivate ();
    36 	
    37   void SetCondition (bool condition);
    38   bool GetCondition (void);
    39   void Signal (void);
    40   void Broadcast (void);
    41   void Wait (void);
    42   bool TimedWait (uint64_t ns);
    43 
    44 private:
    45   pthread_mutex_t m_mutex;
    46   pthread_cond_t  m_cond;
    47   bool m_condition;
    48 };
    49 
    50 SystemConditionPrivate::SystemConditionPrivate ()
    51 {
    52   NS_LOG_FUNCTION_NOARGS ();
    53 
    54   m_condition = false;
    55 
    56   pthread_mutexattr_t mAttr;
    57   pthread_mutexattr_init (&mAttr);
    58 //
    59 // Linux and OS X (at least) have, of course chosen different names for the 
    60 // error checking flags just to make life difficult.
    61 //
    62 #if defined (PTHREAD_MUTEX_ERRORCHECK_NP)
    63   pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_ERRORCHECK_NP);
    64 #else
    65   pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_ERRORCHECK);
    66 #endif
    67   pthread_mutex_init (&m_mutex, &mAttr);
    68 
    69   pthread_condattr_t cAttr;
    70   pthread_condattr_init (&cAttr);
    71   pthread_condattr_setpshared (&cAttr, PTHREAD_PROCESS_PRIVATE);
    72   pthread_cond_init (&m_cond, &cAttr);
    73 }
    74     
    75 SystemConditionPrivate::~SystemConditionPrivate() 
    76 {
    77   NS_LOG_FUNCTION_NOARGS ();
    78   pthread_mutex_destroy (&m_mutex);
    79   pthread_cond_destroy (&m_cond);
    80 }
    81 	
    82   void 
    83 SystemConditionPrivate::SetCondition (bool condition)
    84 {
    85   NS_LOG_FUNCTION_NOARGS ();
    86   m_condition = condition;
    87 }
    88 	
    89   bool
    90 SystemConditionPrivate::GetCondition (void)
    91 {
    92   NS_LOG_FUNCTION_NOARGS ();
    93   return m_condition;
    94 }
    95 	
    96   void 
    97 SystemConditionPrivate::Signal (void)
    98 {
    99   NS_LOG_FUNCTION_NOARGS ();
   100 
   101   pthread_mutex_lock (&m_mutex);
   102   pthread_cond_signal (&m_cond);
   103   pthread_mutex_unlock (&m_mutex);
   104 }
   105 	
   106   void 
   107 SystemConditionPrivate::Broadcast (void)
   108 {
   109   NS_LOG_FUNCTION_NOARGS ();
   110 
   111   pthread_mutex_lock (&m_mutex);
   112   pthread_cond_broadcast (&m_cond);
   113   pthread_mutex_unlock (&m_mutex);
   114 }
   115 
   116   void 
   117 SystemConditionPrivate::Wait (void)
   118 {
   119   NS_LOG_FUNCTION_NOARGS ();
   120 
   121   pthread_mutex_lock (&m_mutex);
   122   m_condition = false;
   123   while (m_condition == false)
   124     {
   125       pthread_cond_wait (&m_cond, &m_mutex);
   126     }
   127   pthread_mutex_unlock (&m_mutex);
   128 }
   129 
   130   bool
   131 SystemConditionPrivate::TimedWait (uint64_t ns)
   132 {
   133   NS_LOG_FUNCTION_NOARGS ();
   134 
   135   struct timespec ts;
   136   ts.tv_sec = ns / NS_PER_SEC;
   137   ts.tv_nsec = ns % NS_PER_SEC;
   138 
   139   struct timeval tv;
   140   gettimeofday(&tv, NULL);
   141 
   142   ts.tv_sec += tv.tv_sec;
   143   ts.tv_nsec += tv.tv_usec * 1000;
   144   if (ts.tv_nsec > (int64_t)NS_PER_SEC)
   145     {
   146       ++ts.tv_sec;
   147       ts.tv_nsec %= NS_PER_SEC;
   148     }
   149 
   150   int rc;
   151 
   152   pthread_mutex_lock (&m_mutex);
   153   while (m_condition == false)
   154     {
   155       rc = pthread_cond_timedwait (&m_cond, &m_mutex, &ts);
   156       if (rc == ETIMEDOUT)
   157         {
   158           pthread_mutex_unlock (&m_mutex); 
   159          return true;
   160         }
   161     }
   162   pthread_mutex_unlock (&m_mutex);
   163   return false;
   164 }
   165 	
   166 SystemCondition::SystemCondition() 
   167   : m_priv (new SystemConditionPrivate ())
   168 {
   169   NS_LOG_FUNCTION_NOARGS ();
   170 }
   171 
   172 SystemCondition::~SystemCondition () 
   173 {
   174   NS_LOG_FUNCTION_NOARGS ();
   175   delete m_priv;
   176 }
   177 
   178   void 
   179 SystemCondition::SetCondition (bool condition) 
   180 {
   181   NS_LOG_FUNCTION_NOARGS ();
   182   m_priv->SetCondition (condition);
   183 }
   184 
   185   bool
   186 SystemCondition::GetCondition (void) 
   187 {
   188   NS_LOG_FUNCTION_NOARGS ();
   189   return m_priv->GetCondition ();
   190 }
   191 
   192   void 
   193 SystemCondition::Signal (void) 
   194 {
   195   NS_LOG_FUNCTION_NOARGS ();
   196   m_priv->Signal ();
   197 }
   198 
   199   void 
   200 SystemCondition::Broadcast (void) 
   201 {
   202   NS_LOG_FUNCTION_NOARGS ();
   203   m_priv->Broadcast ();
   204 }  
   205 
   206   void 
   207 SystemCondition::Wait (void) 
   208 {
   209   NS_LOG_FUNCTION_NOARGS ();
   210   m_priv->Wait ();
   211 }  
   212 
   213   bool
   214 SystemCondition::TimedWait (uint64_t ns) 
   215 {
   216   NS_LOG_FUNCTION_NOARGS ();
   217   return m_priv->TimedWait (ns);
   218 }  
   219 
   220 } // namespace ns3