--- a/RELEASE_NOTES Wed Jul 16 10:45:13 2008 +0100
+++ b/RELEASE_NOTES Wed Jul 16 10:46:51 2008 +0100
@@ -3,6 +3,15 @@
This file contains ns-3 release notes (most recent releases first).
+Next Release (in ns-3-dev)
+==========================
+- Kernel thread support (class SystemThread) added;
+- Kernel mutual exclusion support (class SystemMutex) added;
+- Kernel critical section RAII support (class CriticalSection) added;
+- Kernel system condition support (class SystemCondition) added;
+- Move required methods in helper classes to constructors;
+- Change obsolete references to Parameter to Attribute in helpers;
+
Release 3.1 (2008/06/30)
========================
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/system-condition.h Wed Jul 16 10:46:51 2008 +0100
@@ -0,0 +1,106 @@
+/* -*- 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
+ */
+
+#ifndef SYSTEM_CONDITION_H
+#define SYSTEM_CONDITION_H
+
+#include "ptr.h"
+
+namespace ns3 {
+
+class SystemConditionPrivate;
+
+/**
+ * @brief A class which provides a relatively platform-independent
+ * conditional-wait thread synchronization primitive.
+ *
+ * It is often desirable to have a mechanism by which a thread can suspend its
+ * execution and relinquish the process until some condition to becomes true.
+ * We provide platform-independent access to this OS-dependent capability with
+ * the SystemCondition class.
+ *
+ * There are two ways to tell the underlying primitive that the condition has
+ * become true: Signal and Broadcast. Signal will only wake up one thread
+ * waiting on the condition (according to the OS scheduling policy);
+ * Broadcast will wake up all of the threads waiting on the condition
+ * (cf. "The Thundering Herd").
+ *
+ * In order to wait for the underlying condition, you also have two
+ * alternatives: Wait and TimedWait. The Wait call will wait forever for the
+ * condition to become true; but the TimedWait has a timeout.
+ *
+ * The condition underlying this class is a simple boolean variable. It is
+ * set to false in each call to Wait and TimedWait. It is set to true in each
+ * call to Signal and Broadcast. This is a fairly simple-minded condition
+ * designed for
+ *
+ * A typical use case will be to call Wait() or TimedWait() in one thread
+ * context and put the processor to sleep until an event happens somewhere
+ * else that
+ */
+class SystemCondition
+{
+public:
+ SystemCondition ();
+ ~SystemCondition ();
+
+ /**
+ * Set the value of the underlying condition.
+ */
+ void SetCondition (bool condition);
+
+ /**
+ * Get the value of the underlying condition.
+ */
+ bool GetCondition (void);
+
+ /**
+ * Release one thread if waiting for the condition to be true. If you want
+ * a waiting thread to return, you should have done a SetCondition (true)
+ * prior to calling.
+ */
+ void Signal (void);
+
+ /**
+ * Release all threads waiting for the condition to be true. If you want
+ * all waiting threads to return, you should have done a SetCondition (true)
+ * prior to calling.
+ */
+ void Broadcast (void);
+
+ /**
+ * Wait, possibly forever, for the condition to be true.
+ */
+ void Wait (void);
+
+ /**
+ * Wait a maximum of ns nanoseconds for the condition to be true. If the
+ * wait times out, return true else return false.
+ */
+ bool TimedWait (uint64_t ns);
+
+
+private:
+ SystemConditionPrivate * m_priv;
+};
+
+} //namespace ns3
+
+#endif /* SYSTEM_CONDITION_H */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/system-mutex.h Wed Jul 16 10:46:51 2008 +0100
@@ -0,0 +1,120 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
+ */
+
+#ifndef SYSTEM_MUTEX_H
+#define SYSTEM_MUTEX_H
+
+#include "ptr.h"
+
+namespace ns3 {
+
+class SystemMutexPrivate;
+
+/**
+ * @brief A class which provides a relatively platform-independent Mutual
+ * Exclusion thread synchronization primitive.
+ *
+ * When more than one thread needs to access a shared resource (data structure
+ * or device), the system needs to provide a way to serialize access to the
+ * resource. An operating system will typically provide a Mutual Exclusion
+ * primitive to provide that capability. We provide plattorm-independent
+ * access to the OS-dependent capability with the SystemMutex class.
+ *
+ * There are two operations: Lock and Unlock. Lock allows an executing
+ * SystemThread to attempt to acquire ownership of the Mutual Exclusion
+ * object. If the SystemMutex object is not owned by another thread, then
+ * ownership is granted to the calling SystemThread and Lock returns
+ * immediately, However, if the SystemMutex is already owned by another
+ * SystemThread, the calling SystemThread is blocked until the current owner
+ * releases the SystemMutex by calling Unlock.
+ *
+ * @see CriticalSection
+ */
+class SystemMutex
+{
+public:
+ SystemMutex ();
+ ~SystemMutex ();
+
+ /**
+ * Acquire ownership of the Mutual Exclusion object.
+ */
+ void Lock ();
+
+ /**
+ * Release ownership of the Mutual Exclusion object.
+ */
+ void Unlock ();
+
+private:
+ SystemMutexPrivate * m_priv;
+};
+
+/**
+ * @brief A class which provides a simple way to implement a Critical Section.
+ *
+ * When more than one SystemThread needs to access a shared resource, we
+ * conrol access by acquiring a SystemMutex. The CriticalSection class uses
+ * the C++ scoping rules to automatically perform the required Lock and Unlock
+ * operations to implement a Critical Section.
+ *
+ * If one wants to treat an entire method call as a critical section, one would
+ * do something like,
+ *
+ * Class::Method ()
+ * {
+ * CriticalSection cs (mutex);
+ * ...
+ * }
+ *
+ * In this case, the critical section is entered when the CriticalSection
+ * object is created, and the critical section is exited when the
+ * CriticalSection object goes out of scope at the end of the method.
+ *
+ * Finer granularity is achieved by using local scope blocks.
+ *
+ * Class::Method ()
+ * {
+ * ...
+ * {
+ * CriticalSection cs (mutex);
+ * }
+ * ...
+ * }
+ *
+ * Here, the critical section is entered partway through the method when the
+ * CriticalSection object is created in the local scope block (the braces).
+ * The critical section is exited when the CriticalSection object goes out of
+ * scope at the end of block.
+ *
+ * @see SystemMutex
+ */
+class CriticalSection
+{
+public:
+ CriticalSection (SystemMutex &mutex);
+ ~CriticalSection ();
+private:
+ SystemMutex &m_mutex;
+};
+
+} //namespace ns3
+
+#endif /* SYSTEM_MUTEX_H */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/system-thread.h Wed Jul 16 10:46:51 2008 +0100
@@ -0,0 +1,156 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
+ */
+
+#ifndef SYSTEM_THREAD_H
+#define SYSTEM_THREAD_H
+
+#include "callback.h"
+
+namespace ns3 {
+
+class SystemThreadImpl;
+
+/**
+ * @brief A class which provides a relatively platform-independent thread
+ * primitive.
+ *
+ * This class allows for creation of multiple threads of execution in a
+ * process. The exact implementation of the thread functionality is
+ * operating system dependent, but typically in ns-3 one is using an
+ * environment in which Posix Threads are supported (either navively or
+ * in the case of Windows via Cygwin's implementation of pthreads on the
+ * Win32 API. In either case we expect that these will be kernel-level
+ * threads and therefore a system with multiple CPUs will see truly concurrent
+ * execution.
+ *
+ * Synchronization between threads is provided via the SystemMutex class.
+ */
+class SystemThread
+{
+public:
+ /**
+ * @brief Create a SystemThread object.
+ *
+ * A system thread object is not created running. A thread of execution
+ * must be explicitly started by calling the Start method. When the
+ * Start method is called, it will spawn a thread of execution and cause
+ * that thread to call out into the callback function provided here as
+ * a parameter.
+ *
+ * Like all ns-3 callbacks, the provided callback may refer to a function
+ * or a method of an object depending on how the MakeCallback function is
+ * used.
+ *
+ * The most common use is expected to be creating a thread of execution in
+ * a method. In this case you would use code similar to,
+ *
+ * MyClass myObject;
+ * Ptr<SystemThread> st = Create<SystemThread> (
+ * MakeCallback (&MyClass::MyMethod, &myObject));
+ * st->Start ();
+ *
+ * The SystemThread is passed a callback that calls out to the function
+ * MyClass::MyMethod. When this function is called, it is called as an
+ * object method on the myObject object. Essentially what you are doing
+ * is asking the SystemThread to call object->MyMethod () in a new thread
+ * of execution.
+ *
+ * Remember that if you are invoking a callback on an object that is
+ * managed by a smart pointer, you need to call PeekPointer.
+ *
+ * Ptr<MyClass> myPtr = Create<MyClass> ();
+ * Ptr<SystemThread> st = Create<SystemThread> (
+ * MakeCallback (&MyClass::MyMethod, PeekPointer (myPtr)));
+ * st->Start ();
+ *
+ * Just like any thread, you can synchronize with its termination. The
+ * method provided to do this is Join (). If you call Join() you will block
+ * until the SystemThread run method returns.
+ *
+ * @warning I've made the system thread class look like a normal ns3 object
+ * with smart pointers, and living in the heap. This makes it very easy to
+ * manage threads from a single master thread context. You should be very
+ * aware though that I have not made Ptr multithread safe! This means that
+ * if you pass Ptr<SystemThread> around in a multithreaded environment, it is
+ * possible that the reference count will get messed up since it is not an
+ * atomic operation. CREATE AND MANAGE YOUR THREADS IN ONE PLACE -- LEAVE
+ * THE PTR THERE.
+ */
+ SystemThread(Callback<void> callback);
+
+ /**
+ * @brief Destroy a SystemThread object.
+ *
+ */
+ ~SystemThread();
+
+ /**
+ * Increment the reference count. This method should not be called
+ * by user code. Object instances are expected to be used in conjunction
+ * of the Ptr template which would make calling Ref unecessary and
+ * dangerous.
+ */
+ inline void Ref (void) const;
+
+ /**
+ * Decrement the reference count. This method should not be called
+ * by user code. Object instances are expected to be used in conjunction
+ * of the Ptr template which would make calling Ref unecessary and
+ * dangerous.
+ */
+ inline void Unref (void) const;
+
+ /**
+ * @brief Start a thread of execution, running the provided callback.
+ */
+ void Start (void);
+
+ /**
+ * @brief Suspend the caller until the thread of execution, running the
+ * provided callback, finishes.
+ */
+ void Join (void);
+
+private:
+ SystemThreadImpl * m_impl;
+ mutable uint32_t m_count;
+};
+
+ void
+SystemThread::Ref (void) const
+{
+ m_count++;
+}
+
+ void
+SystemThread::Unref (void) const
+{
+ m_count--;
+ if (m_count == 0)
+ {
+ delete this;
+ }
+}
+
+} //namespace ns3
+
+#endif /* SYSTEM_THREAD_H */
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-system-condition.cc Wed Jul 16 10:46:51 2008 +0100
@@ -0,0 +1,212 @@
+/* -*- 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);
+ pthread_mutexattr_settype (&mAttr, PTHREAD_MUTEX_ERRORCHECK_NP);
+ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-system-mutex.cc Wed Jul 16 10:46:51 2008 +0100
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
+ */
+
+#include <pthread.h>
+#include <errno.h>
+#include "fatal-error.h"
+#include "system-mutex.h"
+#include "log.h"
+
+NS_LOG_COMPONENT_DEFINE ("SystemMutex");
+
+namespace ns3 {
+
+class SystemMutexPrivate {
+public:
+ SystemMutexPrivate ();
+ ~SystemMutexPrivate ();
+
+ void Lock (void);
+ void Unlock (void);
+private:
+ pthread_mutex_t m_mutex;
+};
+
+SystemMutexPrivate::SystemMutexPrivate ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_init (&attr);
+//
+// Make this an error checking mutex. This will check to see if the current
+// thread already owns the mutex before trying to lock it. Instead of
+// deadlocking it returns an error. It will also check to make sure a thread
+// has previously called pthread_mutex_lock when it calls pthread_mutex_unlock.
+//
+ pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP);
+ pthread_mutex_init (&m_mutex, &attr);
+}
+
+SystemMutexPrivate::~SystemMutexPrivate()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ pthread_mutex_destroy (&m_mutex);
+}
+
+ void
+SystemMutexPrivate::Lock (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ int rc = pthread_mutex_lock (&m_mutex);
+ if (rc != 0)
+ {
+ NS_FATAL_ERROR ("SystemMutexPrivate::Lock()"
+ "pthread_mutex_lock failed: " << rc << " = \"" <<
+ strerror(rc) << "\"");
+ }
+}
+
+ void
+SystemMutexPrivate::Unlock (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ int rc = pthread_mutex_unlock (&m_mutex);
+ if (rc != 0)
+ {
+ NS_FATAL_ERROR ("SystemMutexPrivate::Unlock()"
+ "pthread_mutex_unlock failed: " << rc << " = \"" <<
+ strerror(rc) << "\"");
+ }
+}
+
+SystemMutex::SystemMutex()
+ : m_priv (new SystemMutexPrivate ())
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+SystemMutex::~SystemMutex()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ delete m_priv;
+}
+
+ void
+SystemMutex::Lock()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_priv->Lock ();
+}
+
+ void
+SystemMutex::Unlock()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_priv->Unlock ();
+}
+
+CriticalSection::CriticalSection (SystemMutex &mutex)
+ : m_mutex(mutex)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_mutex.Lock ();
+}
+
+CriticalSection::~CriticalSection ()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_mutex.Unlock ();
+}
+
+} // namespace ns3
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/core/unix-system-thread.cc Wed Jul 16 10:46:51 2008 +0100
@@ -0,0 +1,138 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2008 INRIA
+ *
+ * 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
+ *
+ * Author: Mathieu Lacage <mathieu.lacage.inria.fr>
+ */
+
+#include <pthread.h>
+#include "fatal-error.h"
+#include "system-thread.h"
+#include "log.h"
+
+NS_LOG_COMPONENT_DEFINE ("SystemThread");
+
+namespace ns3 {
+
+//
+// Private implementation class for the SystemThread class. The deal is
+// that we export the SystemThread class to the user. The header just
+// declares a class and its members. There is a forward declaration for
+// a private implementation class there and a member declaration. Thus
+// there is no knowledge of the implementation in the exported header.
+//
+// We provide an implementation class for each operating system. This is
+// the Unix implementation of the SystemThread.
+//
+// In order to use the SystemThread, you will include "system-thread.h" and
+// get the implementation by linking unix-system-thread.cc (if you are running
+// a Posix system).
+//
+class SystemThreadImpl
+{
+public:
+ SystemThreadImpl (Callback<void> callback);
+
+ void Start (void);
+ void Join (void);
+
+private:
+ static void *DoRun (void *arg);
+ Callback<void> m_callback;
+ pthread_t m_thread;
+ void * m_ret;
+};
+
+SystemThreadImpl::SystemThreadImpl (Callback<void> callback)
+ : m_callback (callback)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+ void
+SystemThreadImpl::Start (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ int rc = pthread_create (&m_thread, NULL, &SystemThreadImpl::DoRun,
+ (void *)this);
+
+ if (rc)
+ {
+ NS_FATAL_ERROR ("pthread_create failed: " << rc << "=\"" <<
+ strerror(rc) << "\".");
+ }
+}
+
+ void
+SystemThreadImpl::Join (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ void *thread_return;
+ int rc = pthread_join (m_thread, &thread_return);
+ if (rc)
+ {
+ NS_FATAL_ERROR ("pthread_join failed: " << rc << "=\"" <<
+ strerror(rc) << "\".");
+ }
+}
+
+ void *
+SystemThreadImpl::DoRun (void *arg)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+
+ SystemThreadImpl *self = static_cast<SystemThreadImpl *> (arg);
+ self->m_callback ();
+
+ return 0;
+}
+
+//
+// Remember that we just export the delcaration of the SystemThread class to
+// the user. There is no code to implement the SystemThread methods. We
+// have to do that here. We just vector the calls to our implementation
+// class above.
+//
+SystemThread::SystemThread (Callback<void> callback)
+ : m_impl (new SystemThreadImpl (callback)),
+ m_count (1)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+}
+
+SystemThread::~SystemThread()
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ delete m_impl;
+}
+
+ void
+SystemThread::Start (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_impl->Start ();
+}
+
+ void
+SystemThread::Join (void)
+{
+ NS_LOG_FUNCTION_NOARGS ();
+ m_impl->Join ();
+}
+
+} // namespace ns3
--- a/src/core/wscript Wed Jul 16 10:45:13 2008 +0100
+++ b/src/core/wscript Wed Jul 16 10:46:51 2008 +0100
@@ -21,9 +21,14 @@
e.define = 'HAVE_SIGNAL_H'
e.run()
- conf.write_config_header('ns3/core-config.h')
+ e = conf.create_library_configurator()
+ e.mandatory = False
+ e.name = 'rt'
+ e.define = 'HAVE_RT'
+ e.uselib = 'RT'
+ e.run()
-
+ conf.write_config_header('ns3/core-config.h')
def build(bld):
core = bld.create_ns3_module('core')
@@ -60,6 +65,7 @@
'trace-source-accessor.cc',
'config.cc',
]
+ core.uselib = 'RT'
if sys.platform == 'win32':
core.source.extend([
@@ -67,12 +73,18 @@
])
else:
core.source.extend([
+ 'unix-system-thread.cc',
+ 'unix-system-mutex.cc',
+ 'unix-system-condition.cc',
'unix-system-wall-clock-ms.cc',
])
headers = bld.create_obj('ns3header')
headers.module = 'core'
headers.source = [
+ 'system-mutex.h',
+ 'system-thread.h',
+ 'system-condition.h',
'system-wall-clock-ms.h',
'empty.h',
'callback.h',