00001 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2008 INRIA 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation; 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 * 00018 * Author: Mathieu Lacage <mathieu.lacage.inria.fr> 00019 */ 00020 00021 #ifndef SYSTEM_THREAD_H 00022 #define SYSTEM_THREAD_H 00023 00024 #include "callback.h" 00025 00026 namespace ns3 { 00027 00028 class SystemThreadImpl; 00029 00030 /** 00031 * @brief A class which provides a relatively platform-independent thread 00032 * primitive. 00033 * 00034 * This class allows for creation of multiple threads of execution in a 00035 * process. The exact implementation of the thread functionality is 00036 * operating system dependent, but typically in ns-3 one is using an 00037 * environment in which Posix Threads are supported (either navively or 00038 * in the case of Windows via Cygwin's implementation of pthreads on the 00039 * Win32 API. In either case we expect that these will be kernel-level 00040 * threads and therefore a system with multiple CPUs will see truly concurrent 00041 * execution. 00042 * 00043 * Synchronization between threads is provided via the SystemMutex class. 00044 */ 00045 class SystemThread 00046 { 00047 public: 00048 /** 00049 * @brief Create a SystemThread object. 00050 * 00051 * A system thread object is not created running. A thread of execution 00052 * must be explicitly started by calling the Start method. When the 00053 * Start method is called, it will spawn a thread of execution and cause 00054 * that thread to call out into the callback function provided here as 00055 * a parameter. 00056 * 00057 * Like all ns-3 callbacks, the provided callback may refer to a function 00058 * or a method of an object depending on how the MakeCallback function is 00059 * used. 00060 * 00061 * The most common use is expected to be creating a thread of execution in 00062 * a method. In this case you would use code similar to, 00063 * 00064 * MyClass myObject; 00065 * Ptr<SystemThread> st = Create<SystemThread> ( 00066 * MakeCallback (&MyClass::MyMethod, &myObject)); 00067 * st->Start (); 00068 * 00069 * The SystemThread is passed a callback that calls out to the function 00070 * MyClass::MyMethod. When this function is called, it is called as an 00071 * object method on the myObject object. Essentially what you are doing 00072 * is asking the SystemThread to call object->MyMethod () in a new thread 00073 * of execution. 00074 * 00075 * Remember that if you are invoking a callback on an object that is 00076 * managed by a smart pointer, you need to call PeekPointer. 00077 * 00078 * Ptr<MyClass> myPtr = Create<MyClass> (); 00079 * Ptr<SystemThread> st = Create<SystemThread> ( 00080 * MakeCallback (&MyClass::MyMethod, PeekPointer (myPtr))); 00081 * st->Start (); 00082 * 00083 * Just like any thread, you can synchronize with its termination. The 00084 * method provided to do this is Join (). If you call Join() you will block 00085 * until the SystemThread run method returns. 00086 * 00087 * @warning The SystemThread uses SIGALRM to wake threads that are possibly 00088 * blocked on IO. 00089 * @see Shutdown 00090 * 00091 * @warning I've made the system thread class look like a normal ns3 object 00092 * with smart pointers, and living in the heap. This makes it very easy to 00093 * manage threads from a single master thread context. You should be very 00094 * aware though that I have not made Ptr multithread safe! This means that 00095 * if you pass Ptr<SystemThread> around in a multithreaded environment, it is 00096 * possible that the reference count will get messed up since it is not an 00097 * atomic operation. CREATE AND MANAGE YOUR THREADS IN ONE PLACE -- LEAVE 00098 * THE PTR THERE. 00099 */ 00100 SystemThread(Callback<void> callback); 00101 00102 /** 00103 * @brief Destroy a SystemThread object. 00104 * 00105 */ 00106 ~SystemThread(); 00107 00108 /** 00109 * Increment the reference count. This method should not be called 00110 * by user code. Object instances are expected to be used in conjunction 00111 * of the Ptr template which would make calling Ref unecessary and 00112 * dangerous. 00113 */ 00114 inline void Ref (void) const; 00115 00116 /** 00117 * Decrement the reference count. This method should not be called 00118 * by user code. Object instances are expected to be used in conjunction 00119 * of the Ptr template which would make calling Ref unecessary and 00120 * dangerous. 00121 */ 00122 inline void Unref (void) const; 00123 00124 /** 00125 * @brief Start a thread of execution, running the provided callback. 00126 */ 00127 void Start (void); 00128 00129 /** 00130 * @brief Suspend the caller until the thread of execution, running the 00131 * provided callback, finishes. 00132 */ 00133 void Join (void); 00134 00135 /** 00136 * @brief Indicates to a managed thread doing cooperative multithreading that 00137 * its managing thread wants it to exit. 00138 * 00139 * It is often the case that we want a thread to be off doing work until such 00140 * time as its job is done (typically when the simulation is done). We then 00141 * want the thread to exit itself. This method provides a consistent way for 00142 * the managing thread to communicate with the managed thread. After the 00143 * manager thread calls this method, the Break() method will begin returning 00144 * true, telling the managed thread to exit. 00145 * 00146 * This alone isn't really enough to merit these events, but in Unix, if a 00147 * worker thread is doing blocking IO, it will need to be woken up from that 00148 * read somehow. This method also provides that functionality, by sending a 00149 * SIGALRM signal to the possibly blocked thread. 00150 * 00151 * @warning Uses SIGALRM to notifiy threads possibly blocked on IO. Beware 00152 * if you are using signals. 00153 * @see Break 00154 */ 00155 void Shutdown (void); 00156 00157 /** 00158 * @brief Indicates to a thread doing cooperative multithreading that 00159 * its managing thread wants it to exit. 00160 * 00161 * It is often the case that we want a thread to be off doing work until such 00162 * time as its job is done. We then want the thread to exit itself. This 00163 * method allows a thread to query whether or not it should be running. 00164 * Typically, the worker thread is running in a forever-loop, and will need to 00165 * "break" out of that loop to exit -- thus the name. 00166 * 00167 * @see Shutdown 00168 * @returns true if thread is expected to exit (break out of the forever-loop) 00169 */ 00170 bool Break (void); 00171 00172 private: 00173 SystemThreadImpl * m_impl; 00174 mutable uint32_t m_count; 00175 bool m_break; 00176 }; 00177 00178 void 00179 SystemThread::Ref (void) const 00180 { 00181 m_count++; 00182 } 00183 00184 void 00185 SystemThread::Unref (void) const 00186 { 00187 m_count--; 00188 if (m_count == 0) 00189 { 00190 delete this; 00191 } 00192 } 00193 00194 } //namespace ns3 00195 00196 #endif /* SYSTEM_THREAD_H */ 00197 00198