00001 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2008 University of Washington 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 00019 #ifndef SYNCHRONIZER_H 00020 #define SYNCHRONIZER_H 00021 00022 #include <stdint.h> 00023 #include "nstime.h" 00024 #include "ns3/object.h" 00025 00026 namespace ns3 { 00027 00028 /** 00029 * @brief Base class used for synchronizing the simulation events to some 00030 * real time "wall clock." 00031 * 00032 * The simulation clock is maintained as a 64-bit integer in a unit specified 00033 * by the user through the TimeStepPrecision::Set function. This means that 00034 * it is not possible to specify event expiration times with anything better 00035 * than this user-specified accuracy. We use this clock for the simulation 00036 * time. 00037 * 00038 * The real-time clock is maintained as a 64-bit integer count of nanoseconds. 00039 * 00040 * The synchronization between the simulation clock and the real-time clock 00041 * is maintained using a combination of sleep-waiting, busy-waiting and a 00042 * feedback loop. 00043 */ 00044 class Synchronizer : public Object 00045 { 00046 public: 00047 static TypeId GetTypeId (void); 00048 00049 Synchronizer (); 00050 virtual ~Synchronizer (); 00051 00052 /** 00053 * @brief Return true if this synchronizer is actually synchronizing to a 00054 * realtime clock. The simulator sometimes needs to know this. 00055 * @returns True if locked with realtime, false if not. 00056 */ 00057 bool Realtime (void); 00058 00059 /** 00060 * @brief Retrieve the value of the origin of the underlying normalized wall 00061 * clock time in simulator timestep units. 00062 * 00063 * @returns The normalized wall clock time (in simulator timestep units). 00064 * @see TimeStepPrecision::Get 00065 * @see Synchronizer::SetOrigin 00066 */ 00067 uint64_t GetCurrentRealtime (void); 00068 00069 /** 00070 * @brief Establish a correspondence between a simulation time and the 00071 * synchronizer real time. 00072 * 00073 * This method is expected to be called at the "instant" before simulation 00074 * begins. At this point, simulation time = 0, and a 00075 * set = 0 in this method. We then associate this time with the current 00076 * value of the real time clock that will be used to actually perform the 00077 * synchronization. 00078 * 00079 * Subclasses are expected to implement the corresponding DoSetOrigin pure 00080 * virtual method to do the actual real-time-clock-specific work of making the 00081 * correspondence mentioned above. 00082 * 00083 * @param ts The simulation time we should use as the origin (in simulator 00084 * timestep units). 00085 * @see TimeStepPrecision::Get 00086 * @see TimeStepPrecision::DoSetOrigin 00087 */ 00088 void SetOrigin (uint64_t ts); 00089 00090 /** 00091 * @brief Retrieve the value of the origin of the simulation time in 00092 * simulator timestep units. 00093 * 00094 * @returns The simulation time used as the origin (in simulator timestep 00095 * units). 00096 * @see TimeStepPrecision::Get 00097 * @see Synchronizer::SetOrigin 00098 */ 00099 uint64_t GetOrigin (void); 00100 00101 /** 00102 * @brief Retrieve the difference between the real time clock used to 00103 * synchronize the simulation and the simulation time (in simulator timestep 00104 * units). 00105 * 00106 * @param ts Simulation timestep from the simulator interpreted as current time 00107 * in the simulator. 00108 * @returns Simulation timestep (in simulator timestep units) minus origin 00109 * time (stored internally in nanosecond units). 00110 * @see TimeStepPrecision::Get 00111 * @see Synchronizer::SetOrigin 00112 * @see Synchronizer::DoGetDrift 00113 */ 00114 int64_t GetDrift (uint64_t ts); 00115 00116 /** 00117 * @brief Wait until the real time is in sync with the specified simulation 00118 * time or until the synchronizer is Sigalled. 00119 * 00120 * This is where the real work of synchronization is done. The Time passed 00121 * in as a parameter is the simulation time. The job of Synchronize is to 00122 * translate from simulation time to synchronizer time (in a perfect world 00123 * this is the same time) and then figure out how long in real-time it needs 00124 * to wait until that synchronizer / simulation time comes around. 00125 * 00126 * Subclasses are expected to implement the corresponding DoSynchronize pure 00127 * virtual method to do the actual real-time-clock-specific work of waiting 00128 * (either busy-waiting or sleeping, or some combination thereof) until the 00129 * requested simulation time. 00130 * 00131 * @param tsCurrent The current simulation time (in simulator timestep units). 00132 * @param tsDelay The simulation time we need to wait for (in simulator 00133 * timestep units). 00134 * @returns True if the function ran to completion, false if it was interrupted 00135 * by a Signal. 00136 * @see TimeStepPrecision::Get 00137 * @see Synchronizer::DoSynchronize 00138 * @see Synchronizer::Signal 00139 */ 00140 bool Synchronize (uint64_t tsCurrent, uint64_t tsDelay); 00141 00142 /** 00143 * @brief Tell a posible simulator thread waiting in the Synchronize method 00144 * that an event has happened which demands a reevaluation of the wait time. 00145 * This will cause the thread to wake and return to the simulator proper 00146 * where it can get its bearings. 00147 * 00148 * @see Synchronizer::Synchronize 00149 * @see Synchronizer::DoSignal 00150 */ 00151 void Signal (void); 00152 00153 /** 00154 * @brief Set the condition variable that tells a posible simulator thread 00155 * waiting in the Synchronize method that an event has happened which demands 00156 * a reevaluation of the wait time. 00157 * 00158 * @see Synchronizer::Signal 00159 */ 00160 void SetCondition (bool); 00161 00162 /** 00163 * @brief Ask the synchronizer to remember what time it is. Typically used 00164 * with EventEnd to determine the real execution time of a simulation event. 00165 * 00166 * @see Synchronizer::EventEnd 00167 * @see TimeStepPrecision::Get 00168 */ 00169 void EventStart (void); 00170 00171 /** 00172 * @brief Ask the synchronizer to return the time step between the instant 00173 * remembered during EventStart and now. Used in conjunction with EventStart 00174 * to determine the real execution time of a simulation event. 00175 * 00176 * @see Synchronizer::EventStart 00177 * @see TimeStepPrecision::Get 00178 */ 00179 uint64_t EventEnd (void); 00180 00181 protected: 00182 /** 00183 * @brief Establish a correspondence between a simulation time and a 00184 * wall-clock (real) time. 00185 * 00186 * @internal 00187 * 00188 * There are three timelines involved here: the simulation time, the 00189 * (absolute) wall-clock time and the (relative) synchronizer real time. 00190 * Calling this method makes a correspondence between the origin of the 00191 * synchronizer time and the current wall-clock time. 00192 * 00193 * This method is expected to be called at the "instant" before simulation 00194 * begins. At this point, simulation time = 0, and synchronizer time is 00195 * set = 0 in this method. We then associate this time with the current 00196 * value of the real time clock that will be used to actually perform the 00197 * synchronization. 00198 * 00199 * Subclasses are expected to implement this method to do the actual 00200 * real-time-clock-specific work of making the correspondence mentioned above. 00201 * for example, this is where the differences between Time parameters and 00202 * parameters to clock_nanosleep would be dealt with. 00203 * 00204 * @param ns The simulation time we need to use as the origin (normalized to 00205 * nanosecond units). 00206 * @see Synchronizer::SetOrigin 00207 * @see TimeStepPrecision::Get 00208 */ 00209 virtual void DoSetOrigin (uint64_t ns) = 0; 00210 00211 /** 00212 * @brief Return true if this synchronizer is actually synchronizing to a 00213 * realtime clock. The simulator sometimes needs to know this. 00214 * 00215 * @internal 00216 * 00217 * Subclasses are expected to implement this method to tell the outside world 00218 * whether or not they are synchronizing to a realtime clock. 00219 * 00220 * @returns True if locked with realtime, false if not. 00221 */ 00222 virtual bool DoRealtime (void) = 0; 00223 00224 /** 00225 * @brief Retrieve the value of the origin of the underlying normalized wall 00226 * clock time in simulator timestep units. 00227 * 00228 * @internal 00229 * 00230 * Subclasses are expected to implement this method to do the actual 00231 * real-time-clock-specific work of getting the current time. 00232 * 00233 * @returns The normalized wall clock time (in nanosecond units). 00234 * @see TimeStepPrecision::Get 00235 * @see Synchronizer::SetOrigin 00236 */ 00237 virtual uint64_t DoGetCurrentRealtime (void) = 0; 00238 00239 /** 00240 * @brief Wait until the real time is in sync with the specified simulation 00241 * time. 00242 * 00243 * @internal 00244 * 00245 * This is where the real work of synchronization is done. The Time passed 00246 * in as a parameter is the simulation time. The job of Synchronize is to 00247 * translate from simulation time to synchronizer time (in a perfect world 00248 * this is the same time) and then figure out how long in real-time it needs 00249 * to wait until that synchronizer / simulation time comes around. 00250 * 00251 * Subclasses are expected to implement this method to do the actual 00252 * real-time-clock-specific work of waiting (either busy-waiting or sleeping, 00253 * or some combination) until the requested simulation time. 00254 * 00255 * @param nsCurrent The current simulation time (normalized to nanosecond 00256 * units). 00257 * @param nsDelay The simulation time we need to wait for (normalized to 00258 * nanosecond units). 00259 * @returns True if the function ran to completion, false if it was interrupted 00260 * by a Signal. 00261 * @see Synchronizer::Synchronize 00262 * @see TimeStepPrecision::Get 00263 * @see Synchronizer::Signal 00264 */ 00265 virtual bool DoSynchronize (uint64_t nsCurrent, uint64_t nsDelay) = 0; 00266 00267 /** 00268 * @brief Declaration of the method used to tell a posible simulator thread 00269 * waiting in the DoSynchronize method that an event has happened which 00270 * demands a reevaluation of the wait time. 00271 * 00272 * @see Synchronizer::Signal 00273 */ 00274 virtual void DoSignal (void) = 0; 00275 00276 /** 00277 * @brief Declaration of the method used to set the condition variable that 00278 * tells a posible simulator thread waiting in the Synchronize method that an 00279 * event has happened which demands a reevaluation of the wait time. 00280 * 00281 * @see Synchronizer::SetCondition 00282 */ 00283 virtual void DoSetCondition (bool) = 0; 00284 00285 /** 00286 * @brief Declaration of method used to retrieve drift between the real time 00287 * clock used to synchronize the simulation and the current simulation time. 00288 * 00289 * @internal 00290 * 00291 * @param ns Simulation timestep from the simulator normalized to nanosecond 00292 * steps. 00293 * @returns Drift in nanosecond units. 00294 * @see TimeStepPrecision::Get 00295 * @see Synchronizer::SetOrigin 00296 * @see Synchronizer::GetDrift 00297 */ 00298 virtual int64_t DoGetDrift (uint64_t ns) = 0; 00299 00300 virtual void DoEventStart (void) = 0; 00301 virtual uint64_t DoEventEnd (void) = 0; 00302 00303 uint64_t m_realtimeOriginNano; 00304 uint64_t m_simOriginNano; 00305 00306 private: 00307 /** 00308 * @brief Convert a simulator time step (which can be steps of time in a 00309 * user-specified unit) to a normalized time step in nanosecond units. 00310 * 00311 * @internal 00312 * 00313 * @param ts The simulation time step to be normalized. 00314 * @returns The simulation time step normalized to nanosecond units. 00315 * @see TimeStepPrecision::Get 00316 */ 00317 uint64_t TimeStepToNanosecond (uint64_t ts); 00318 00319 /** 00320 * @brief Convert a normalized nanosecond count into a simulator time step 00321 * (which can be steps of time in a user-specified unit). 00322 * 00323 * @internal 00324 * 00325 * @param ns The nanosecond count step to be converted 00326 * @returns The simulation time step to be interpreted in appropriate units. 00327 * @see TimeStepPrecision::Get 00328 */ 00329 uint64_t NanosecondToTimeStep (uint64_t ns); 00330 }; 00331 00332 }; // namespace ns3 00333 00334 #endif /* SYNCHRONIZER_H */