src/core/unix-system-condition.cc
author Florian Westphal <fw@strlen.de>
Wed, 03 Sep 2008 23:24:59 +0200
changeset 3595 693faf7f4e9b
parent 3434 ee113f8d83db
permissions -rw-r--r--
nsc: Fix build problem if gtk config store is disabled gtk config store pulled in libdl.so for us, so things fail to link of the config store isn't enabled. This makes nsc pull in libdl itself when its enabled.

/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2008 University of Washington
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation;
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <pthread.h>
#include <errno.h>
#include <sys/time.h>
#include "fatal-error.h"
#include "system-condition.h"
#include "log.h"

NS_LOG_COMPONENT_DEFINE ("SystemCondition");

namespace ns3 {

class SystemConditionPrivate {    
public: 
  static const uint64_t NS_PER_SEC = (uint64_t)1000000000;

  SystemConditionPrivate ();
  ~SystemConditionPrivate ();
	
  void SetCondition (bool condition);
  bool GetCondition (void);
  void Signal (void);
  void Broadcast (void);
  void Wait (void);
  bool TimedWait (uint64_t ns);

private:
  pthread_mutex_t m_mutex;
  pthread_cond_t  m_cond;
  bool m_condition;
};

SystemConditionPrivate::SystemConditionPrivate ()
{
  NS_LOG_FUNCTION_NOARGS ();

  m_condition = false;

  pthread_mutexattr_t mAttr;
  pthread_mutexattr_init (&mAttr);
//
// Linux and OS X (at least) have, of course chosen different names for the 
// error checking flags just to make life difficult.
//
#if defined (PTHREAD_MUTEX_ERRORCHECK_NP)
  pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_ERRORCHECK_NP);
#else
  pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_ERRORCHECK);
#endif
  pthread_mutex_init (&m_mutex, &mAttr);

  pthread_condattr_t cAttr;
  pthread_condattr_init (&cAttr);
  pthread_condattr_setpshared (&cAttr, PTHREAD_PROCESS_PRIVATE);
  pthread_cond_init (&m_cond, &cAttr);
}
    
SystemConditionPrivate::~SystemConditionPrivate() 
{
  NS_LOG_FUNCTION_NOARGS ();
  pthread_mutex_destroy (&m_mutex);
  pthread_cond_destroy (&m_cond);
}
	
  void 
SystemConditionPrivate::SetCondition (bool condition)
{
  NS_LOG_FUNCTION_NOARGS ();
  m_condition = condition;
}
	
  bool
SystemConditionPrivate::GetCondition (void)
{
  NS_LOG_FUNCTION_NOARGS ();
  return m_condition;
}
	
  void 
SystemConditionPrivate::Signal (void)
{
  NS_LOG_FUNCTION_NOARGS ();

  pthread_mutex_lock (&m_mutex);
  pthread_cond_signal (&m_cond);
  pthread_mutex_unlock (&m_mutex);
}
	
  void 
SystemConditionPrivate::Broadcast (void)
{
  NS_LOG_FUNCTION_NOARGS ();

  pthread_mutex_lock (&m_mutex);
  pthread_cond_broadcast (&m_cond);
  pthread_mutex_unlock (&m_mutex);
}

  void 
SystemConditionPrivate::Wait (void)
{
  NS_LOG_FUNCTION_NOARGS ();

  pthread_mutex_lock (&m_mutex);
  m_condition = false;
  while (m_condition == false)
    {
      pthread_cond_wait (&m_cond, &m_mutex);
    }
  pthread_mutex_unlock (&m_mutex);
}

  bool
SystemConditionPrivate::TimedWait (uint64_t ns)
{
  NS_LOG_FUNCTION_NOARGS ();

  struct timespec ts;
  ts.tv_sec = ns / NS_PER_SEC;
  ts.tv_nsec = ns % NS_PER_SEC;

  struct timeval tv;
  gettimeofday(&tv, NULL);

  ts.tv_sec += tv.tv_sec;
  ts.tv_nsec += tv.tv_usec * 1000;
  if (ts.tv_nsec > (int64_t)NS_PER_SEC)
    {
      ++ts.tv_sec;
      ts.tv_nsec %= NS_PER_SEC;
    }

  int rc;

  pthread_mutex_lock (&m_mutex);
  while (m_condition == false)
    {
      rc = pthread_cond_timedwait (&m_cond, &m_mutex, &ts);
      if (rc == ETIMEDOUT)
        {
          pthread_mutex_unlock (&m_mutex); 
         return true;
        }
    }
  pthread_mutex_unlock (&m_mutex);
  return false;
}
	
SystemCondition::SystemCondition() 
  : m_priv (new SystemConditionPrivate ())
{
  NS_LOG_FUNCTION_NOARGS ();
}

SystemCondition::~SystemCondition () 
{
  NS_LOG_FUNCTION_NOARGS ();
  delete m_priv;
}

  void 
SystemCondition::SetCondition (bool condition) 
{
  NS_LOG_FUNCTION_NOARGS ();
  m_priv->SetCondition (condition);
}

  bool
SystemCondition::GetCondition (void) 
{
  NS_LOG_FUNCTION_NOARGS ();
  return m_priv->GetCondition ();
}

  void 
SystemCondition::Signal (void) 
{
  NS_LOG_FUNCTION_NOARGS ();
  m_priv->Signal ();
}

  void 
SystemCondition::Broadcast (void) 
{
  NS_LOG_FUNCTION_NOARGS ();
  m_priv->Broadcast ();
}  

  void 
SystemCondition::Wait (void) 
{
  NS_LOG_FUNCTION_NOARGS ();
  m_priv->Wait ();
}  

  bool
SystemCondition::TimedWait (uint64_t ns) 
{
  NS_LOG_FUNCTION_NOARGS ();
  return m_priv->TimedWait (ns);
}  

} // namespace ns3