From db748a0000c57e60c6ff4762f8d4eb2c79d18e65 Mon Sep 17 00:00:00 2001 From: Craig Dowell Date: Tue, 15 Jul 2008 15:59:57 -0700 Subject: [PATCH] add system threads and synchronization primitives --- src/core/system-condition.h | 106 +++++++++++++++ src/core/system-mutex.h | 120 +++++++++++++++++ src/core/system-thread.h | 156 ++++++++++++++++++++++ src/core/unix-system-condition.cc | 212 ++++++++++++++++++++++++++++++ src/core/unix-system-mutex.cc | 131 ++++++++++++++++++ src/core/unix-system-thread.cc | 138 +++++++++++++++++++ src/core/wscript | 16 ++- 7 files changed, 877 insertions(+), 2 deletions(-) create mode 100644 src/core/system-condition.h create mode 100644 src/core/system-mutex.h create mode 100644 src/core/system-thread.h create mode 100644 src/core/unix-system-condition.cc create mode 100644 src/core/unix-system-mutex.cc create mode 100644 src/core/unix-system-thread.cc diff --git a/src/core/system-condition.h b/src/core/system-condition.h new file mode 100644 index 000000000..eb3d78b0e --- /dev/null +++ b/src/core/system-condition.h @@ -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 */ + + diff --git a/src/core/system-mutex.h b/src/core/system-mutex.h new file mode 100644 index 000000000..2bb411ab0 --- /dev/null +++ b/src/core/system-mutex.h @@ -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 + */ + +#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 */ diff --git a/src/core/system-thread.h b/src/core/system-thread.h new file mode 100644 index 000000000..2ec613b40 --- /dev/null +++ b/src/core/system-thread.h @@ -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 + */ + +#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 st = Create ( + * 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 myPtr = Create (); + * Ptr st = Create ( + * 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 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 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 */ + + diff --git a/src/core/unix-system-condition.cc b/src/core/unix-system-condition.cc new file mode 100644 index 000000000..b2bfa11d7 --- /dev/null +++ b/src/core/unix-system-condition.cc @@ -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 +#include +#include +#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 diff --git a/src/core/unix-system-mutex.cc b/src/core/unix-system-mutex.cc new file mode 100644 index 000000000..359ffa74d --- /dev/null +++ b/src/core/unix-system-mutex.cc @@ -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 + */ + +#include +#include +#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 diff --git a/src/core/unix-system-thread.cc b/src/core/unix-system-thread.cc new file mode 100644 index 000000000..9fbd7a73e --- /dev/null +++ b/src/core/unix-system-thread.cc @@ -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 + */ + +#include +#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 callback); + + void Start (void); + void Join (void); + +private: + static void *DoRun (void *arg); + Callback m_callback; + pthread_t m_thread; + void * m_ret; +}; + +SystemThreadImpl::SystemThreadImpl (Callback 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 (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 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 diff --git a/src/core/wscript b/src/core/wscript index 9646b06c7..2e4a18c91 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -21,10 +21,15 @@ def configure(conf): e.define = 'HAVE_SIGNAL_H' e.run() + 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') core.source = [ @@ -60,6 +65,7 @@ def build(bld): 'trace-source-accessor.cc', 'config.cc', ] + core.uselib = 'RT' if sys.platform == 'win32': core.source.extend([ @@ -67,12 +73,18 @@ def build(bld): ]) 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',