00001
00002
00003 #ifndef ACE_TIMEPROBE_T_CPP
00004 #define ACE_TIMEPROBE_T_CPP
00005
00006 #include "ace/config-all.h"
00007
00008 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00009 # pragma once
00010 #endif
00011
00012 #if defined (ACE_COMPILE_TIMEPROBES)
00013
00014 #include "ace/Timeprobe.h"
00015 #include "ace/High_Res_Timer.h"
00016 #include "ace/OS_NS_string.h"
00017
00018 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00019
00020 template <class ACE_LOCK, class ALLOCATOR>
00021 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::ACE_Timeprobe_Ex (u_long size)
00022 : timeprobes_ (0),
00023 lock_ (),
00024 max_size_ (size),
00025 current_size_ (0),
00026 report_buffer_full_ (0),
00027 allocator_ (0)
00028 {
00029 ACE_timeprobe_t *temp;
00030
00031 ACE_NEW_MALLOC_ARRAY (temp,
00032 (ACE_timeprobe_t *) this->allocator ()->
00033 malloc (this->max_size_*sizeof(ACE_timeprobe_t)),
00034 ACE_timeprobe_t,
00035 this->max_size_);
00036
00037 this->timeprobes_ = temp;
00038
00039 }
00040
00041 template <class ACE_LOCK, class ALLOCATOR>
00042 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::
00043 ACE_Timeprobe_Ex (ALLOCATOR *allocator,
00044 u_long size)
00045 : timeprobes_ (0),
00046 lock_ (),
00047 max_size_ (size),
00048 current_size_ (0),
00049 report_buffer_full_ (0),
00050 allocator_ (allocator)
00051 {
00052 ACE_timeprobe_t *temp = 0;
00053
00054 ACE_NEW_MALLOC_ARRAY (temp,
00055 (ACE_timeprobe_t *) this->allocator ()->
00056 malloc (this->max_size_*sizeof(ACE_timeprobe_t)),
00057 ACE_timeprobe_t,
00058 this->max_size_);
00059
00060 this->timeprobes_ = temp;
00061
00062 }
00063
00064 template <class ACE_LOCK, class ALLOCATOR>
00065 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::ACE_Timeprobe_Ex (const ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR> &)
00066 {
00067
00068
00069
00070
00071 ACE_ERROR ((LM_ERROR,
00072 ACE_TEXT ("ACE_NOTSUP: %N, line %l\n")));
00073 errno = ENOTSUP;
00074 }
00075
00076 template <class ACE_LOCK, class ALLOCATOR>
00077 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::~ACE_Timeprobe_Ex (void)
00078 {
00079 ACE_DES_ARRAY_FREE ((ACE_timeprobe_t *) (this->timeprobes_),
00080 this->max_size_,
00081 this->allocator ()->free,
00082 ACE_timeprobe_t);
00083 }
00084
00085 template <class ACE_LOCK, class ALLOCATOR> void
00086 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (u_long event)
00087 {
00088 ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
00089
00090 this->timeprobes_[this->current_size_].event_.event_number_ = event;
00091 this->timeprobes_[this->current_size_].event_type_ = ACE_timeprobe_t::NUMBER;
00092 this->timeprobes_[this->current_size_].time_ = ACE_OS::gethrtime ();
00093 this->timeprobes_[this->current_size_].thread_ = ACE_OS::thr_self ();
00094
00095 ++this->current_size_;
00096
00097 #if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
00098
00099 if (this->current_size_ >= this->max_size_)
00100 {
00101 this->current_size_ = 0;
00102 this->report_buffer_full_ = 1;
00103 }
00104 #endif
00105
00106 ACE_ASSERT (this->current_size_ < this->max_size_);
00107 }
00108
00109 template <class ACE_LOCK, class ALLOCATOR> void
00110 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (const char *event)
00111 {
00112 ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
00113
00114 this->timeprobes_[this->current_size_].event_.event_description_ = event;
00115 this->timeprobes_[this->current_size_].event_type_ = ACE_timeprobe_t::STRING;
00116 this->timeprobes_[this->current_size_].time_ = ACE_OS::gethrtime ();
00117 this->timeprobes_[this->current_size_].thread_ = ACE_OS::thr_self ();
00118
00119 ++this->current_size_;
00120
00121 #if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
00122
00123 if (this->current_size_ >= this->max_size_)
00124 {
00125 this->current_size_ = 0;
00126 this->report_buffer_full_ = 1;
00127 }
00128 #endif
00129
00130 ACE_ASSERT (this->current_size_ < this->max_size_);
00131 }
00132
00133 template <class ACE_LOCK, class ALLOCATOR> void
00134 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::reset (void)
00135 {
00136 ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
00137
00138 this->current_size_ = 0;
00139 this->report_buffer_full_ = 0;
00140 }
00141
00142 template <class ACE_LOCK, class ALLOCATOR> void
00143 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::increase_size (u_long size)
00144 {
00145 ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
00146
00147 if (size > this->max_size_)
00148 {
00149 ACE_timeprobe_t *temp = 0;
00150
00151 ACE_NEW_MALLOC_ARRAY (temp,
00152 (ACE_timeprobe_t *) this->allocator ()->
00153 malloc (this->max_size_
00154 * sizeof (ACE_timeprobe_t)),
00155 ACE_timeprobe_t,
00156 size);
00157
00158
00159 if (this->max_size_ > 0)
00160 {
00161 ACE_OS::memcpy (temp,
00162 this->timeprobes_,
00163 this->max_size_ * sizeof (ACE_timeprobe_t));
00164
00165
00166
00167
00168 ACE_DES_ARRAY_FREE ((ACE_timeprobe_t *)(this->timeprobes_),
00169 this->max_size_,
00170 this->allocator ()->free,
00171 ACE_timeprobe_t);
00172 }
00173 this->timeprobes_ = temp;
00174 this->max_size_ = size;
00175 }
00176 }
00177
00178 template <class ACE_LOCK, class ALLOCATOR> ACE_Unbounded_Set<ACE_Event_Descriptions> &
00179 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::event_descriptions (void)
00180 {
00181 return this->event_descriptions_;
00182 }
00183
00184 template <class ACE_LOCK, class ALLOCATOR> ACE_Unbounded_Set<ACE_Event_Descriptions> &
00185 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::sorted_event_descriptions (void)
00186 {
00187 return this->sorted_event_descriptions_;
00188 }
00189
00190 template <class ACE_LOCK, class ALLOCATOR> ACE_timeprobe_t *
00191 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobes (void)
00192 {
00193 return this->timeprobes_;
00194 }
00195
00196 template <class ACE_LOCK, class ALLOCATOR> ACE_LOCK &
00197 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::lock (void)
00198 {
00199 return this->lock_;
00200 }
00201
00202 template <class ACE_LOCK, class ALLOCATOR> u_long
00203 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::max_size (void)
00204 {
00205 return this->max_size_;
00206 }
00207
00208 template <class ACE_LOCK, class ALLOCATOR> u_long
00209 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::current_size (void)
00210 {
00211 return this->current_size_;
00212 }
00213
00214 template <class ACE_LOCK, class ALLOCATOR> int
00215 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::event_descriptions (const char **descriptions,
00216 u_long minimum_id)
00217 {
00218 ACE_GUARD_RETURN (ACE_LOCK, ace_mon, this->lock_, -1);
00219
00220 ACE_Event_Descriptions events;
00221 events.descriptions_ = descriptions;
00222 events.minimum_id_ = minimum_id;
00223
00224 this->event_descriptions_.insert (events);
00225
00226 return 0;
00227 }
00228
00229 template <class ACE_LOCK, class ALLOCATOR> void
00230 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_times (void)
00231 {
00232 ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
00233
00234
00235 this->sort_event_descriptions_i ();
00236
00237 u_long size = this->report_buffer_full_ ? this->max_size_
00238 : this->current_size_;
00239
00240 ACE_DEBUG ((LM_DEBUG,
00241 "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
00242 size));
00243
00244 if (size == 0)
00245 return;
00246
00247 ACE_DEBUG ((LM_DEBUG,
00248 "\n%-50.50s %8.8s %13.13s\n\n",
00249 "Event",
00250 "thread",
00251 "usec"));
00252
00253 double gsf = ACE_High_Res_Timer::global_scale_factor ();
00254 u_long i, j;
00255
00256
00257 i = this->report_buffer_full_ ? this->current_size_ : 0;
00258
00259 ACE_DEBUG ((LM_DEBUG,
00260 "%-50.50s %8.8x %13.13s\n",
00261 this->find_description_i (i),
00262 this->timeprobes_[i].thread_,
00263 "START"));
00264
00265 if (size == 1)
00266 return;
00267
00268 bool has_timestamp_inversion = false;
00269
00270 j = i;
00271 i = (i + 1) % this->max_size_;
00272
00273 do
00274 {
00275
00276
00277
00278
00279
00280
00281
00282
00283 double time_difference =
00284 (ACE_INT64) (this->timeprobes_[i].time_ - this->timeprobes_[j].time_);
00285
00286 if (time_difference < 0)
00287 has_timestamp_inversion = true;
00288
00289
00290 time_difference /= gsf;
00291
00292 ACE_DEBUG ((LM_DEBUG,
00293 "%-50.50s %8.8x %14.3f\n",
00294 this->find_description_i (i),
00295 this->timeprobes_[i].thread_,
00296 time_difference));
00297
00298 j = i;
00299 i = (i + 1) % this->max_size_;
00300 }
00301 while (i != this->current_size_);
00302
00303 static bool inversion_warning_printed = false;
00304 if (!inversion_warning_printed && has_timestamp_inversion)
00305 {
00306 inversion_warning_printed = true;
00307 ACE_DEBUG ((LM_DEBUG,
00308 "\nWARNING: The timestamps recorded by gethrtime() on"
00309 " this platform are\n"
00310 "not monotonic across different threads.\n"));
00311 }
00312 }
00313
00314 template <class ACE_LOCK, class ALLOCATOR> void
00315 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_absolute_times (void)
00316 {
00317 ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
00318
00319
00320 this->sort_event_descriptions_i ();
00321
00322 u_long size = this->report_buffer_full_ ? this->max_size_
00323 : this->current_size_;
00324
00325 ACE_DEBUG ((LM_DEBUG,
00326 "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
00327 size));
00328
00329 if (size == 0)
00330 return;
00331
00332 ACE_DEBUG ((LM_DEBUG,
00333 "\n%-50.50s %8.8s %13.13s\n\n",
00334 "Event",
00335 "thread",
00336 "stamp"));
00337
00338 u_long i = this->report_buffer_full_ ? this->current_size_ : 0;
00339
00340 ACE_Time_Value tv;
00341 do
00342 {
00343 ACE_High_Res_Timer::hrtime_to_tv (tv, this->timeprobes_ [i].time_);
00344
00345 ACE_DEBUG ((LM_DEBUG,
00346 "%-50.50s %8.8x %12.12u\n",
00347 this->find_description_i (i),
00348 this->timeprobes_ [i].thread_,
00349 tv.sec () * 1000000
00350 + tv.usec ()));
00351
00352
00353 i = (i + 1) % this->max_size_;
00354 }
00355 while (i != this->current_size_);
00356 }
00357
00358 template <class ACE_LOCK, class ALLOCATOR> const char *
00359 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::find_description_i (u_long i)
00360 {
00361 if (this->timeprobes_[i].event_type_ == ACE_timeprobe_t::STRING)
00362 return this->timeprobes_[i].event_.event_description_;
00363 else
00364 {
00365 EVENT_DESCRIPTIONS::iterator iterator = this->sorted_event_descriptions_.begin ();
00366 for (u_long j = 0;
00367 j < this->sorted_event_descriptions_.size () - 1;
00368 iterator++, j++)
00369 {
00370 EVENT_DESCRIPTIONS::iterator next_event_descriptions = iterator;
00371 ++next_event_descriptions;
00372
00373 if (this->timeprobes_[i].event_.event_number_ < (*next_event_descriptions).minimum_id_)
00374 break;
00375 }
00376 return (*iterator).descriptions_[this->timeprobes_[i].event_.event_number_ - (*iterator).minimum_id_];
00377 }
00378 }
00379
00380 template <class ACE_LOCK, class ALLOCATOR> void
00381 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::sort_event_descriptions_i (void)
00382 {
00383 size_t total_elements = this->event_descriptions_.size ();
00384
00385 for (size_t i = 0;
00386 i < total_elements;
00387 i++)
00388 {
00389 EVENT_DESCRIPTIONS::iterator iterator = this->event_descriptions_.begin ();
00390 ACE_Event_Descriptions min_entry = *iterator;
00391
00392 for (;
00393 iterator != this->event_descriptions_.end ();
00394 iterator++)
00395 if ((*iterator).minimum_id_ < min_entry.minimum_id_)
00396 min_entry = *iterator;
00397
00398 this->sorted_event_descriptions_.insert (min_entry);
00399 this->event_descriptions_.remove (min_entry);
00400 }
00401 }
00402
00403 template <class ACE_LOCK, class ALLOCATOR> ALLOCATOR *
00404 ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::allocator (void)
00405 {
00406 return allocator_ ? allocator_ : ACE_Singleton<ALLOCATOR, ACE_LOCK>::instance ();
00407 }
00408
00409 template <class Timeprobe>
00410 ACE_Function_Timeprobe<Timeprobe>::ACE_Function_Timeprobe (Timeprobe &timeprobe,
00411 u_long event)
00412 : timeprobe_ (timeprobe),
00413 event_ (event)
00414 {
00415 this->timeprobe_.timeprobe (this->event_);
00416 }
00417
00418 template <class Timeprobe>
00419 ACE_Function_Timeprobe<Timeprobe>::~ACE_Function_Timeprobe (void)
00420 {
00421 this->timeprobe_.timeprobe (this->event_ + 1);
00422 }
00423
00424 ACE_END_VERSIONED_NAMESPACE_DECL
00425
00426 #endif
00427 #endif