diff --git a/src/core/system-thread.h b/src/core/system-thread.h index 2ec613b40..07f519267 100644 --- a/src/core/system-thread.h +++ b/src/core/system-thread.h @@ -84,6 +84,10 @@ public: * method provided to do this is Join (). If you call Join() you will block * until the SystemThread run method returns. * + * @warning The SystemThread uses SIGALRM to wake threads that are possibly + * blocked on IO. + * @see Shutdown + * * @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 @@ -128,9 +132,46 @@ public: */ void Join (void); + /** + * @brief Indicates to a managed thread doing cooperative multithreading that + * its managing thread wants it to exit. + * + * It is often the case that we want a thread to be off doing work until such + * time as its job is done (typically when the simulation is done). We then + * want the thread to exit itself. This method provides a consistent way for + * the managing thread to communicate with the managed thread. After the + * manager thread calls this method, the Break() method will begin returning + * true, telling the managed thread to exit. + * + * This alone isn't really enough to merit these events, but in Unix, if a + * worker thread is doing blocking IO, it will need to be woken up from that + * read somehow. This method also provides that functionality, by sending a + * SIGALRM signal to the possibly blocked thread. + * + * @see Break + * @returns true if thread is expected to exit + */ + void Shutdown (void); + + /** + * @brief Indicates to a thread doing cooperative multithreading that + * its managing thread wants it to exit. + * + * It is often the case that we want a thread to be off doing work until such + * time as its job is done. We then want the thread to exit itself. This + * method allows a thread to query whether or not it should be running. + * Typically, the worker thread is running in a forever-loop, and will need to + * "break" out of that loop to exit -- thus the name. + * + * @see Shutdown + * @returns true if thread is expected to exit (break out of the forever-loop) + */ + bool Break (void); + private: SystemThreadImpl * m_impl; mutable uint32_t m_count; + bool m_break; }; void diff --git a/src/core/unix-system-thread.cc b/src/core/unix-system-thread.cc index 3e36b5df9..16eb5ff43 100644 --- a/src/core/unix-system-thread.cc +++ b/src/core/unix-system-thread.cc @@ -50,11 +50,14 @@ public: void Start (void); void Join (void); + void Shutdown (void); + bool Break (void); private: static void *DoRun (void *arg); Callback m_callback; pthread_t m_thread; + bool m_break; void * m_ret; }; @@ -91,9 +94,6 @@ SystemThreadImpl::Join (void) { NS_LOG_FUNCTION_NOARGS (); - // send a SIGALRM signal on the target thread to make sure that it - // will unblock. - pthread_kill (m_thread, SIGALRM); void *thread_return; int rc = pthread_join (m_thread, &thread_return); if (rc) @@ -103,6 +103,26 @@ SystemThreadImpl::Join (void) } } + void +SystemThreadImpl::Shutdown (void) +{ + NS_LOG_FUNCTION_NOARGS (); + + m_break = true; + + // send a SIGALRM signal on the target thread to make sure that it + // will unblock. + pthread_kill (m_thread, SIGALRM); +} + + bool +SystemThreadImpl::Break (void) +{ + NS_LOG_FUNCTION_NOARGS (); + + return m_break; +} + void * SystemThreadImpl::DoRun (void *arg) { @@ -147,4 +167,18 @@ SystemThread::Join (void) m_impl->Join (); } + void +SystemThread::Shutdown (void) +{ + NS_LOG_FUNCTION_NOARGS (); + m_impl->Shutdown (); +} + + bool +SystemThread::Break (void) +{ + NS_LOG_FUNCTION_NOARGS (); + return m_impl->Break (); +} + } // namespace ns3