1 #ifndef ACE_TIMEPROBE_T_CPP
2 #define ACE_TIMEPROBE_T_CPP
4 #include "ace/config-all.h"
6 #if !defined (ACE_LACKS_PRAGMA_ONCE)
8 #endif /* ACE_LACKS_PRAGMA_ONCE */
10 #if defined (ACE_COMPILE_TIMEPROBES)
12 #include "ace/Timeprobe.h"
13 #include "ace/High_Res_Timer.h"
14 #include "ace/OS_NS_string.h"
16 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
18 template <class ACE_LOCK
, class ALLOCATOR
>
19 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::ACE_Timeprobe_Ex (u_long size
)
24 report_buffer_full_ (0),
27 ACE_timeprobe_t
*temp
;
28 //FUZZ: disable check_for_lack_ACE_OS
29 ACE_NEW_MALLOC_ARRAY (temp
,
30 (ACE_timeprobe_t
*) this->allocator ()->
31 malloc (this->max_size_
*sizeof(ACE_timeprobe_t
)),
34 //FUZZ: enable check_for_lack_ACE_OS
35 this->timeprobes_
= temp
;
38 template <class ACE_LOCK
, class ALLOCATOR
>
39 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::
40 ACE_Timeprobe_Ex (ALLOCATOR
*allocator
,
46 report_buffer_full_ (0),
47 allocator_ (allocator
)
49 ACE_timeprobe_t
*temp
= 0;
50 //FUZZ: disable check_for_lack_ACE_OS
51 ACE_NEW_MALLOC_ARRAY (temp
,
52 (ACE_timeprobe_t
*) this->allocator ()->
53 malloc (this->max_size_
*sizeof(ACE_timeprobe_t
)),
56 //FUZZ: enable check_for_lack_ACE_OS
57 this->timeprobes_
= temp
;
60 template <class ACE_LOCK
, class ALLOCATOR
>
61 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::ACE_Timeprobe_Ex (const ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
> &)
64 // Stupid MSVC is forcing me to define this; please don't use it.
67 ACELIB_ERROR ((LM_ERROR
,
68 ACE_TEXT ("ACE_NOTSUP: %N, line %l\n")));
72 template <class ACE_LOCK
, class ALLOCATOR
>
73 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::~ACE_Timeprobe_Ex ()
75 ACE_DES_ARRAY_FREE ((ACE_timeprobe_t
*) (this->timeprobes_
),
77 this->allocator ()->free
,
81 template <class ACE_LOCK
, class ALLOCATOR
> void
82 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::timeprobe (u_long event
)
84 ACE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
86 this->timeprobes_
[this->current_size_
].event_
.event_number_
= event
;
87 this->timeprobes_
[this->current_size_
].event_type_
= ACE_timeprobe_t::NUMBER
;
88 this->timeprobes_
[this->current_size_
].time_
= ACE_OS::gethrtime ();
89 this->timeprobes_
[this->current_size_
].thread_
= ACE_OS::thr_self ();
91 ++this->current_size_
;
93 #if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
94 // wrap around to the beginning on overflow
95 if (this->current_size_
>= this->max_size_
)
97 this->current_size_
= 0;
98 this->report_buffer_full_
= 1;
100 #endif /* ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
102 ACE_ASSERT (this->current_size_
< this->max_size_
);
105 template <class ACE_LOCK
, class ALLOCATOR
> void
106 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::timeprobe (const char *event
)
108 ACE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
110 this->timeprobes_
[this->current_size_
].event_
.event_description_
= event
;
111 this->timeprobes_
[this->current_size_
].event_type_
= ACE_timeprobe_t::STRING
;
112 this->timeprobes_
[this->current_size_
].time_
= ACE_OS::gethrtime ();
113 this->timeprobes_
[this->current_size_
].thread_
= ACE_OS::thr_self ();
115 ++this->current_size_
;
117 #if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
118 // wrap around to the beginning on overflow
119 if (this->current_size_
>= this->max_size_
)
121 this->current_size_
= 0;
122 this->report_buffer_full_
= 1;
124 #endif /* ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
126 ACE_ASSERT (this->current_size_
< this->max_size_
);
129 template <class ACE_LOCK
, class ALLOCATOR
> void
130 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::reset ()
132 ACE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
134 this->current_size_
= 0;
135 this->report_buffer_full_
= 0;
138 template <class ACE_LOCK
, class ALLOCATOR
> void
139 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::increase_size (u_long size
)
141 ACE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
143 if (size
> this->max_size_
)
145 ACE_timeprobe_t
*temp
= 0;
146 //FUZZ: disable check_for_lack_ACE_OS
147 ACE_NEW_MALLOC_ARRAY (temp
,
148 (ACE_timeprobe_t
*) this->allocator ()->
149 malloc (this->max_size_
150 * sizeof (ACE_timeprobe_t
)),
153 //FUZZ: enable check_for_lack_ACE_OS
155 if (this->max_size_
> 0)
157 ACE_OS::memcpy (temp
,
159 this->max_size_
* sizeof (ACE_timeprobe_t
));
161 // Iterates over the array explicitly calling the destructor for
162 // each probe instance, then deallocates the memory
164 ACE_DES_ARRAY_FREE ((ACE_timeprobe_t
*)(this->timeprobes_
),
166 this->allocator ()->free
,
169 this->timeprobes_
= temp
;
170 this->max_size_
= size
;
174 template <class ACE_LOCK
, class ALLOCATOR
> ACE_Unbounded_Set
<ACE_Event_Descriptions
> &
175 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::event_descriptions ()
177 return this->event_descriptions_
;
180 template <class ACE_LOCK
, class ALLOCATOR
> ACE_Unbounded_Set
<ACE_Event_Descriptions
> &
181 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::sorted_event_descriptions ()
183 return this->sorted_event_descriptions_
;
186 template <class ACE_LOCK
, class ALLOCATOR
> ACE_timeprobe_t
*
187 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::timeprobes ()
189 return this->timeprobes_
;
192 template <class ACE_LOCK
, class ALLOCATOR
> ACE_LOCK
&
193 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::lock ()
198 template <class ACE_LOCK
, class ALLOCATOR
> u_long
199 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::max_size ()
201 return this->max_size_
;
204 template <class ACE_LOCK
, class ALLOCATOR
> u_long
205 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::current_size ()
207 return this->current_size_
;
210 template <class ACE_LOCK
, class ALLOCATOR
> int
211 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::event_descriptions (const char **descriptions
,
214 ACE_GUARD_RETURN (ACE_LOCK
, ace_mon
, this->lock_
, -1);
216 ACE_Event_Descriptions events
;
217 events
.descriptions_
= descriptions
;
218 events
.minimum_id_
= minimum_id
;
220 this->event_descriptions_
.insert (events
);
225 template <class ACE_LOCK
, class ALLOCATOR
> void
226 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::print_times ()
228 ACE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
230 // Sort the event descriptions
231 this->sort_event_descriptions_i ();
233 u_long size
= this->report_buffer_full_
? this->max_size_
234 : this->current_size_
;
236 ACELIB_DEBUG ((LM_DEBUG
,
237 "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
243 ACELIB_DEBUG ((LM_DEBUG
,
244 "\n%-50.50s %8.8s %13.13s\n\n",
249 ACE_High_Res_Timer::global_scale_factor_type gsf
=
250 ACE_High_Res_Timer::global_scale_factor ();
254 i
= this->report_buffer_full_
? this->current_size_
: 0;
256 ACELIB_DEBUG ((LM_DEBUG
,
257 "%-50.50s %8.8x %13.13s\n",
258 this->find_description_i (i
),
259 this->timeprobes_
[i
].thread_
,
265 bool has_timestamp_inversion
= false;
268 i
= (i
+ 1) % this->max_size_
;
272 // When reusing the same ACE_Timeprobe from multiple threads
273 // with Linux on Intel SMP, it sometimes happens that the
274 // recorded times go backward in time if they are recorded from
275 // different threads (see bugzilla #2342). To obtain the
276 // correct signed difference between consecutive recorded times,
277 // one has to cast the time difference to an intermediate signed
278 // integral type of the same size as ACE_hrtime_t.
280 double time_difference
=
281 (ACE_INT64
) (this->timeprobes_
[i
].time_
- this->timeprobes_
[j
].time_
);
283 if (time_difference
< 0)
284 has_timestamp_inversion
= true;
286 // Convert to microseconds.
287 time_difference
/= gsf
;
289 ACELIB_DEBUG ((LM_DEBUG
,
290 "%-50.50s %8.8x %14.3f\n",
291 this->find_description_i (i
),
292 this->timeprobes_
[i
].thread_
,
296 i
= (i
+ 1) % this->max_size_
;
298 while (i
!= this->current_size_
);
300 static bool inversion_warning_printed
= false;
301 if (!inversion_warning_printed
&& has_timestamp_inversion
)
303 inversion_warning_printed
= true;
304 ACELIB_DEBUG ((LM_DEBUG
,
305 "\nWARNING: The timestamps recorded by gethrtime() on"
306 " this platform are\n"
307 "not monotonic across different threads.\n"));
311 template <class ACE_LOCK
, class ALLOCATOR
> void
312 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::print_absolute_times ()
314 ACE_GUARD (ACE_LOCK
, ace_mon
, this->lock_
);
316 // Sort the event descriptions
317 this->sort_event_descriptions_i ();
319 u_long size
= this->report_buffer_full_
? this->max_size_
320 : this->current_size_
;
322 ACELIB_DEBUG ((LM_DEBUG
,
323 "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
329 ACELIB_DEBUG ((LM_DEBUG
,
330 "\n%-50.50s %8.8s %13.13s\n\n",
335 u_long i
= this->report_buffer_full_
? this->current_size_
: 0;
337 ACE_Time_Value tv
; // to convert ACE_hrtime_t
340 ACE_High_Res_Timer::hrtime_to_tv (tv
, this->timeprobes_
[i
].time_
);
342 ACELIB_DEBUG ((LM_DEBUG
,
343 "%-50.50s %8.8x %12.12u\n",
344 this->find_description_i (i
),
345 this->timeprobes_
[i
].thread_
,
349 // Modulus increment: loops around at the end.
350 i
= (i
+ 1) % this->max_size_
;
352 while (i
!= this->current_size_
);
355 template <class ACE_LOCK
, class ALLOCATOR
> const char *
356 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::find_description_i (u_long i
)
358 if (this->timeprobes_
[i
].event_type_
== ACE_timeprobe_t::STRING
)
359 return this->timeprobes_
[i
].event_
.event_description_
;
362 EVENT_DESCRIPTIONS::iterator iterator
= this->sorted_event_descriptions_
.begin ();
364 j
< this->sorted_event_descriptions_
.size () - 1;
367 EVENT_DESCRIPTIONS::iterator next_event_descriptions
= iterator
;
368 ++next_event_descriptions
;
370 if (this->timeprobes_
[i
].event_
.event_number_
< (*next_event_descriptions
).minimum_id_
)
373 return (*iterator
).descriptions_
[this->timeprobes_
[i
].event_
.event_number_
- (*iterator
).minimum_id_
];
377 template <class ACE_LOCK
, class ALLOCATOR
> void
378 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::sort_event_descriptions_i ()
380 size_t total_elements
= this->event_descriptions_
.size ();
386 EVENT_DESCRIPTIONS::iterator iterator
= this->event_descriptions_
.begin ();
387 ACE_Event_Descriptions min_entry
= *iterator
;
390 iterator
!= this->event_descriptions_
.end ();
392 if ((*iterator
).minimum_id_
< min_entry
.minimum_id_
)
393 min_entry
= *iterator
;
395 this->sorted_event_descriptions_
.insert (min_entry
);
396 this->event_descriptions_
.remove (min_entry
);
400 template <class ACE_LOCK
, class ALLOCATOR
> ALLOCATOR
*
401 ACE_Timeprobe_Ex
<ACE_LOCK
, ALLOCATOR
>::allocator ()
403 return allocator_
? allocator_
: ACE_Singleton
<ALLOCATOR
, ACE_LOCK
>::instance ();
406 template <class Timeprobe
>
407 ACE_Function_Timeprobe
<Timeprobe
>::ACE_Function_Timeprobe (Timeprobe
&timeprobe
,
409 : timeprobe_ (timeprobe
),
412 this->timeprobe_
.timeprobe (this->event_
);
415 template <class Timeprobe
>
416 ACE_Function_Timeprobe
<Timeprobe
>::~ACE_Function_Timeprobe ()
418 this->timeprobe_
.timeprobe (this->event_
+ 1);
421 ACE_END_VERSIONED_NAMESPACE_DECL
423 #endif /* ACE_COMPILE_TIMEPROBES */
424 #endif /* ACE_TIMEPROBE_T_CPP */