summaryrefslogtreecommitdiff
path: root/ACE/ace
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace')
-rw-r--r--ACE/ace/Acceptor.h35
-rw-r--r--ACE/ace/CDR_Size.cpp6
-rw-r--r--ACE/ace/CDR_Size.inl12
-rw-r--r--ACE/ace/CDR_Stream.cpp25
-rw-r--r--ACE/ace/Containers_T.cpp6
-rw-r--r--ACE/ace/INET_Addr.h26
-rw-r--r--ACE/ace/Log_Msg.cpp12
-rw-r--r--ACE/ace/Logging_Strategy.cpp9
-rw-r--r--ACE/ace/Logging_Strategy.h3
-rw-r--r--ACE/ace/TSS_T.cpp2
-rw-r--r--ACE/ace/Timeprobe_T.cpp196
11 files changed, 197 insertions, 135 deletions
diff --git a/ACE/ace/Acceptor.h b/ACE/ace/Acceptor.h
index ac50a793d34..4b2c236b6f6 100644
--- a/ACE/ace/Acceptor.h
+++ b/ACE/ace/Acceptor.h
@@ -66,17 +66,16 @@ public:
/**
* Open the contained @c PEER_ACCEPTOR object to begin listening, and
- * register with the specified reactor for connection accept events.
- * An ACE_Acceptor can only listen to one port at a time; if one desires to
- * change the address that an ACE_Acceptor listens on, call close()
- * before calling open() again.
+ * register with the specified reactor for accept events. An
+ * acceptor can only listen to one port at a time, so make sure to
+ * @c close() the acceptor before calling @c open() again.
*
- * The @c PEER_ACCEPTOR handle is put into nonblocking mode as a
+ * The @c PEER_ACCEPTOR handle is put into non-blocking mode as a
* safeguard against the race condition that can otherwise occur
* between the time when the passive-mode socket handle is "ready"
- * and when the actual accept() call is made. During this
- * interval, the client can shut down the connection, in which case
- * the accept() call can block indefinitely.
+ * and when the actual @c accept() call is made. During this
+ * interval, the client can shutdown the connection, in which case,
+ * the @c accept() call can hang.
*
* @param local_addr The address to listen at.
* @param reactor Pointer to the ACE_Reactor instance to register
@@ -99,7 +98,7 @@ public:
* OS allow reuse of the listen port. The default is 1.
*/
ACE_Acceptor (const ACE_PEER_ACCEPTOR_ADDR &local_addr,
- ACE_Reactor *reactor = ACE_Reactor::instance (),
+ ACE_Reactor * = ACE_Reactor::instance (),
int flags = 0,
int use_select = 1,
int reuse_addr = 1);
@@ -184,18 +183,17 @@ protected:
/**
* Bridge method for accepting the new connection into the
- * specified @a svc_handler. The default behavior delegates to the
- * @c PEER_ACCEPTOR::accept() method.
+ * <svc_handler>. The default behavior delegates to the
+ * PEER_ACCEPTOR::accept.
*/
virtual int accept_svc_handler (SVC_HANDLER *svc_handler);
/**
- * Bridge method for activating the specified @a svc_handler with the
- * appropriate concurrency strategy.
- * The default behavior of this method is to activate the service handler
- * by calling its open() method (which allows the handler to define its
- * own concurrency strategy).
- * However, subclasses of ACE_Acceptor can override this method to do more
+ * Bridge method for activating a {svc_handler} with the appropriate
+ * concurrency strategy. The default behavior of this method is to
+ * activate the SVC_HANDLER by calling its {open} method (which
+ * allows the SVC_HANDLER to define its own concurrency strategy).
+ * However, subclasses can override this strategy to do more
* sophisticated concurrency activations (such as making the
* SVC_HANDLER as an "active object" via multi-threading or
* multi-processing).
@@ -391,7 +389,6 @@ public:
/// Declare the dynamic allocation hooks.
ACE_ALLOC_HOOK_DECLARE;
-protected:
// = Service management hooks.
/// This method delegates to the {Scheduling_Strategy}'s {suspend}
@@ -402,6 +399,8 @@ protected:
/// method.
virtual int resume (void);
+protected:
+
/// Calls {handle_close} when dynamically unlinked.
virtual int fini (void);
diff --git a/ACE/ace/CDR_Size.cpp b/ACE/ace/CDR_Size.cpp
index 9d24a648ca5..8265881b670 100644
--- a/ACE/ace/CDR_Size.cpp
+++ b/ACE/ace/CDR_Size.cpp
@@ -1,6 +1,5 @@
#include "ace/CDR_Size.h"
#include "ace/SString.h"
-#include "ace/OS_Memory.h"
#if !defined (__ACE_INLINE__)
# include "ace/CDR_Size.inl"
@@ -59,7 +58,10 @@ ACE_SizeCDR::write_wchar (ACE_CDR::WChar x)
return (this->good_bit_ = false);
}
if (ACE_OutputCDR::wchar_maxbytes () == sizeof (ACE_CDR::WChar))
- return this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (&x));
+ {
+ const void *temp = &x;
+ return this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (temp));
+ }
else if (ACE_OutputCDR::wchar_maxbytes () == 2)
{
ACE_CDR::Short sx = static_cast<ACE_CDR::Short> (x);
diff --git a/ACE/ace/CDR_Size.inl b/ACE/ace/CDR_Size.inl
index 4c835067ce8..90197379cab 100644
--- a/ACE/ace/CDR_Size.inl
+++ b/ACE/ace/CDR_Size.inl
@@ -90,25 +90,29 @@ ACE_SizeCDR::write_longlong (const ACE_CDR::LongLong &x)
ACE_INLINE ACE_CDR::Boolean
ACE_SizeCDR::write_ulonglong (const ACE_CDR::ULongLong &x)
{
- return this->write_8 (reinterpret_cast<const ACE_CDR::ULongLong*> (&x));
+ const void *temp = &x;
+ return this->write_8 (reinterpret_cast<const ACE_CDR::ULongLong *> (temp));
}
ACE_INLINE ACE_CDR::Boolean
ACE_SizeCDR::write_float (ACE_CDR::Float x)
{
- return this->write_4 (reinterpret_cast<const ACE_CDR::ULong*> (&x));
+ const void *temp = &x;
+ return this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (temp));
}
ACE_INLINE ACE_CDR::Boolean
ACE_SizeCDR::write_double (const ACE_CDR::Double &x)
{
- return this->write_8 (reinterpret_cast<const ACE_CDR::ULongLong*> (&x));
+ const void *temp = &x;
+ return this->write_8 (reinterpret_cast<const ACE_CDR::ULongLong*> (temp));
}
ACE_INLINE ACE_CDR::Boolean
ACE_SizeCDR::write_longdouble (const ACE_CDR::LongDouble &x)
{
- return this->write_16 (reinterpret_cast<const ACE_CDR::LongDouble*> (&x));
+ const void *temp = &x;
+ return this->write_16 (reinterpret_cast<const ACE_CDR::LongDouble*> (temp));
}
ACE_INLINE ACE_CDR::Boolean
diff --git a/ACE/ace/CDR_Stream.cpp b/ACE/ace/CDR_Stream.cpp
index d7030235d5d..2a4c042d6ff 100644
--- a/ACE/ace/CDR_Stream.cpp
+++ b/ACE/ace/CDR_Stream.cpp
@@ -261,7 +261,10 @@ ACE_OutputCDR::write_wchar (ACE_CDR::WChar x)
return (this->good_bit_ = false);
}
if (ACE_OutputCDR::wchar_maxbytes_ == sizeof (ACE_CDR::WChar))
- return this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (&x));
+ {
+ const void *temp = &x;
+ return this->write_4 (reinterpret_cast<const ACE_CDR::ULong *> (temp));
+ }
else if (ACE_OutputCDR::wchar_maxbytes_ == 2)
{
ACE_CDR::Short sx = static_cast<ACE_CDR::Short> (x);
@@ -966,9 +969,15 @@ ACE_InputCDR::skip_wchar (void)
{
ACE_CDR::WChar x;
if (ACE_OutputCDR::wchar_maxbytes_ == 2)
- return this->read_2 (reinterpret_cast<ACE_CDR::UShort *> (&x));
+ {
+ void *temp = &x;
+ return this->read_2 (reinterpret_cast<ACE_CDR::UShort *> (temp));
+ }
else
- return this->read_4 (reinterpret_cast<ACE_CDR::ULong *> (&x));
+ {
+ void *temp = &x;
+ return this->read_4 (reinterpret_cast<ACE_CDR::ULong *> (temp));
+ }
}
return (this->good_bit_ = false);
@@ -1007,9 +1016,15 @@ ACE_InputCDR::read_wchar (ACE_CDR::WChar& x)
}
if (sizeof (ACE_CDR::WChar) == 2)
- return this->read_2 (reinterpret_cast<ACE_CDR::UShort *> (&x));
+ {
+ void *temp = &x;
+ return this->read_2 (reinterpret_cast<ACE_CDR::UShort *> (temp));
+ }
else
- return this->read_4 (reinterpret_cast<ACE_CDR::ULong *> (&x));
+ {
+ void *temp = &x;
+ return this->read_4 (reinterpret_cast<ACE_CDR::ULong *> (temp));
+ }
}
if (static_cast<ACE_CDR::Short> (major_version_) == 1
diff --git a/ACE/ace/Containers_T.cpp b/ACE/ace/Containers_T.cpp
index 0dd3bfbf160..4ae7d970f6f 100644
--- a/ACE/ace/Containers_T.cpp
+++ b/ACE/ace/Containers_T.cpp
@@ -1865,9 +1865,10 @@ template <class T> T *
ACE_DLList<T>::insert_tail (T *new_item)
{
ACE_DLList_Node *temp1, *temp2;
+ void *temp = new_item;
ACE_NEW_MALLOC_RETURN (temp1,
static_cast<ACE_DLList_Node *> (this->allocator_->malloc (sizeof (ACE_DLList_Node))),
- ACE_DLList_Node ((void *&)new_item),
+ ACE_DLList_Node (temp),
0);
temp2 = ACE_DLList_Base::insert_tail (temp1);
return (T *) (temp2 ? temp2->item_ : 0);
@@ -1877,9 +1878,10 @@ template <class T> T *
ACE_DLList<T>::insert_head (T *new_item)
{
ACE_DLList_Node *temp1;
+ void *temp = new_item;
ACE_NEW_MALLOC_RETURN (temp1,
(ACE_DLList_Node *) this->allocator_->malloc (sizeof (ACE_DLList_Node)),
- ACE_DLList_Node ((void *&)new_item), 0);
+ ACE_DLList_Node (temp), 0);
ACE_DLList_Node *temp2 =
ACE_DLList_Base::insert_head (temp1);
return (T *) (temp2 ? temp2->item_ : 0);
diff --git a/ACE/ace/INET_Addr.h b/ACE/ace/INET_Addr.h
index fd7f5159627..fe5522d6fbb 100644
--- a/ACE/ace/INET_Addr.h
+++ b/ACE/ace/INET_Addr.h
@@ -279,15 +279,31 @@ public:
#endif /* ACE_HAS_WCHAR */
/**
- * Return the character representation of the hostname (this version
- * is non-reentrant since it returns a pointer to a static data
- * area).
+ * Return the character representation of the hostname. This
+ * version is non-reentrant since it returns a pointer to a static
+ * data area. You should therefore either (1) do a "deep copy" of
+ * the address returned by get_host_name(), e.g., using strdup() or
+ * (2) use the "reentrant" version of get_host_name() described
+ * above.
*/
const char *get_host_name (void) const;
- /// Return the "dotted decimal" Internet address.
+ /**
+ * Return the "dotted decimal" Internet address representation of
+ * the hostname storing it in the <addr> (which is assumed to be
+ * <addr_size> bytes long). This version is reentrant.
+ */
+ const char *get_host_addr (char *addr, int addr_size) const;
+
+ /**
+ * Return the "dotted decimal" Internet address representation of
+ * the hostname. This version is non-reentrant since it returns a
+ * pointer to a static data area. You should therefore either
+ * (1) do a "deep copy" of the address returned by get_host_addr(), e.g.,
+ * using strdup() or (2) use the "reentrant" version of
+ * get_host_addr() described above.
+ */
const char *get_host_addr (void) const;
- const char *get_host_addr (char *dst, int size) const;
/// Return the 4-byte IP address, converting it into host byte
/// order.
diff --git a/ACE/ace/Log_Msg.cpp b/ACE/ace/Log_Msg.cpp
index 0c77181410a..277c971c41b 100644
--- a/ACE/ace/Log_Msg.cpp
+++ b/ACE/ace/Log_Msg.cpp
@@ -254,12 +254,12 @@ ACE_Log_Msg::exists (void)
# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || \
defined (ACE_HAS_TSS_EMULATION)
ACE_Log_Msg *tss_log_msg = 0;
+ void *temp = 0; // Need this temp to keep G++ from complaining.
// Get the tss_log_msg from thread-specific storage.
return key_created_
- && ACE_Thread::getspecific (*(log_msg_tss_key ()),
- reinterpret_cast<void **> (&tss_log_msg)) != -1
- && tss_log_msg;
+ && ACE_Thread::getspecific (*(log_msg_tss_key ()), &temp) != -1
+ && (tss_log_msg = static_cast <ACE_Log_Msg *> (temp)) != 0;
# else
# error "Platform must support thread-specific storage if threads are used."
# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */
@@ -325,12 +325,14 @@ ACE_Log_Msg::instance (void)
}
ACE_Log_Msg *tss_log_msg = 0;
+ void *temp = tss_log_msg;
// Get the tss_log_msg from thread-specific storage.
- if (ACE_Thread::getspecific (*(log_msg_tss_key ()),
- reinterpret_cast<void **> (&tss_log_msg)) == -1)
+ if (ACE_Thread::getspecific (*(log_msg_tss_key ()), &temp) == -1)
return 0; // This should not happen!
+ tss_log_msg = static_cast <ACE_Log_Msg *> (temp);
+
// Check to see if this is the first time in for this thread.
if (tss_log_msg == 0)
{
diff --git a/ACE/ace/Logging_Strategy.cpp b/ACE/ace/Logging_Strategy.cpp
index 63776c14aac..cbb528f7a65 100644
--- a/ACE/ace/Logging_Strategy.cpp
+++ b/ACE/ace/Logging_Strategy.cpp
@@ -266,10 +266,19 @@ ACE_Logging_Strategy::ACE_Logging_Strategy (void)
#endif /* ACE_DEFAULT_LOGFILE */
}
+ACE_Logging_Strategy::~ACE_Logging_Strategy (void)
+{
+ // This is allocated in constructor, so it must be deallocated in
+ // the destructor!
+ delete [] this->filename_;
+}
+
int
ACE_Logging_Strategy::fini (void)
{
delete [] this->filename_;
+ this->filename_ = 0; // Avoid double deletions.
+
delete [] this->logger_key_;
delete [] this->program_name_;
diff --git a/ACE/ace/Logging_Strategy.h b/ACE/ace/Logging_Strategy.h
index 962dee6bc53..89b4427e0eb 100644
--- a/ACE/ace/Logging_Strategy.h
+++ b/ACE/ace/Logging_Strategy.h
@@ -80,6 +80,9 @@ public:
/// Constructor.
ACE_Logging_Strategy (void);
+ /// Destructor.
+ ~ACE_Logging_Strategy (void);
+
/// Dynamic linking initialization hook.
virtual int init (int argc, ACE_TCHAR *argv[]);
diff --git a/ACE/ace/TSS_T.cpp b/ACE/ace/TSS_T.cpp
index aa2160c28c9..1157bcbd38d 100644
--- a/ACE/ace/TSS_T.cpp
+++ b/ACE/ace/TSS_T.cpp
@@ -602,7 +602,7 @@ ACE_TSS_Write_Guard<ACE_LOCK>::tryacquire (void)
guard = static_cast <ACE_Write_Guard<ACE_LOCK> *> (tss_adapter->ts_obj_);
#else
void *temp = guard; // Need this temp to keep G++ from complaining.
- ACE_Thread::getspecific (this->key_, temp);
+ ACE_Thread::getspecific (this->key_, &temp);
guard = static_cast <ACE_Write_Guard<ACE_LOCK> *> (temp);
#endif /* ACE_HAS_THR_C_DEST */
diff --git a/ACE/ace/Timeprobe_T.cpp b/ACE/ace/Timeprobe_T.cpp
index 254f3290197..6b5348770c4 100644
--- a/ACE/ace/Timeprobe_T.cpp
+++ b/ACE/ace/Timeprobe_T.cpp
@@ -83,17 +83,6 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (u_long event)
{
ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
-# if defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
- ACE_ASSERT (this->current_size_ < this->max_size_);
-# else /* ! ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
- // wrap around to the beginning on overflow
- if (this->current_size_ >= this->max_size_)
- {
- this->current_size_ = 0;
- this->report_buffer_full_ = 1;
- }
-# endif /* ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
-
this->timeprobes_[this->current_size_].event_.event_number_ = event;
this->timeprobes_[this->current_size_].event_type_ = ACE_timeprobe_t::NUMBER;
this->timeprobes_[this->current_size_].time_ = ACE_OS::gethrtime ();
@@ -101,6 +90,16 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (u_long event)
++this->current_size_;
+#if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
+ // wrap around to the beginning on overflow
+ if (this->current_size_ >= this->max_size_)
+ {
+ this->current_size_ = 0;
+ this->report_buffer_full_ = 1;
+ }
+#endif /* ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
+
+ ACE_ASSERT (this->current_size_ < this->max_size_);
}
template <class ACE_LOCK, class ALLOCATOR> void
@@ -108,11 +107,14 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (const char *event)
{
ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
- ACE_ASSERT (this->current_size_ < this->max_size_);
+ this->timeprobes_[this->current_size_].event_.event_description_ = event;
+ this->timeprobes_[this->current_size_].event_type_ = ACE_timeprobe_t::STRING;
+ this->timeprobes_[this->current_size_].time_ = ACE_OS::gethrtime ();
+ this->timeprobes_[this->current_size_].thread_ = ACE_OS::thr_self ();
-#if defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
- ACE_ASSERT (this->current_size_ < this->max_size_);
-#else /* ! ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
+ ++this->current_size_;
+
+#if !defined (ACE_TIMEPROBE_ASSERTS_FIXED_SIZE)
// wrap around to the beginning on overflow
if (this->current_size_ >= this->max_size_)
{
@@ -121,12 +123,7 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::timeprobe (const char *event)
}
#endif /* ACE_TIMEPROBE_ASSERTS_FIXED_SIZE */
- this->timeprobes_[this->current_size_].event_.event_description_ = event;
- this->timeprobes_[this->current_size_].event_type_ = ACE_timeprobe_t::STRING;
- this->timeprobes_[this->current_size_].time_ = ACE_OS::gethrtime ();
- this->timeprobes_[this->current_size_].thread_ = ACE_OS::thr_self ();
-
- ++this->current_size_;
+ ACE_ASSERT (this->current_size_ < this->max_size_);
}
template <class ACE_LOCK, class ALLOCATOR> void
@@ -141,35 +138,35 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::reset (void)
template <class ACE_LOCK, class ALLOCATOR> void
ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::increase_size (u_long size)
{
- ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
+ ACE_GUARD (ACE_LOCK, ace_mon, this->lock_);
- if (size > this->max_size_)
- {
+ if (size > this->max_size_)
+ {
ACE_timeprobe_t *temp = 0;
ACE_NEW_MALLOC_ARRAY (temp,
- (ACE_timeprobe_t *) this->allocator ()->
- malloc (this->max_size_
- * sizeof (ACE_timeprobe_t)),
- ACE_timeprobe_t,
- size);
+ (ACE_timeprobe_t *) this->allocator ()->
+ malloc (this->max_size_
+ * sizeof (ACE_timeprobe_t)),
+ ACE_timeprobe_t,
+ size);
if (this->max_size_ > 0)
- {
- ACE_OS::memcpy (temp,
- this->timeprobes_,
- this->max_size_ * sizeof (ACE_timeprobe_t));
-
- // Iterates over the array explicitly calling the destructor for
- // each probe instance, then deallocates the memory
-
- ACE_DES_ARRAY_FREE ((ACE_timeprobe_t *)(this->timeprobes_),
- this->max_size_,
- this->allocator ()->free,
- ACE_timeprobe_t);
- }
+ {
+ ACE_OS::memcpy (temp,
+ this->timeprobes_,
+ this->max_size_ * sizeof (ACE_timeprobe_t));
+
+ // Iterates over the array explicitly calling the destructor for
+ // each probe instance, then deallocates the memory
+
+ ACE_DES_ARRAY_FREE ((ACE_timeprobe_t *)(this->timeprobes_),
+ this->max_size_,
+ this->allocator ()->free,
+ ACE_timeprobe_t);
+ }
this->timeprobes_ = temp;
this->max_size_ = size;
- }
+ }
}
template <class ACE_LOCK, class ALLOCATOR> ACE_Unbounded_Set<ACE_Event_Descriptions> &
@@ -231,11 +228,14 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_times (void)
// Sort the event descriptions
this->sort_event_descriptions_i ();
+ u_long size = this->report_buffer_full_ ? this->max_size_
+ : this->current_size_;
+
ACE_DEBUG ((LM_DEBUG,
- "\nACE_Timeprobe_Ex; %d timestamps were recorded:\n",
- this->current_size_));
+ "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
+ size));
- if (this->current_size_ == 0)
+ if (size == 0)
return;
ACE_DEBUG ((LM_DEBUG,
@@ -244,52 +244,65 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_times (void)
"thread",
"usec"));
+ double gsf = ACE_High_Res_Timer::global_scale_factor ();
+ u_long i, j;
+
+ // First element
+ i = this->report_buffer_full_ ? this->current_size_ : 0;
+
ACE_DEBUG ((LM_DEBUG,
"%-50.50s %8.8x %13.13s\n",
- this->find_description_i (0),
- this->timeprobes_[0].thread_,
+ this->find_description_i (i),
+ this->timeprobes_[i].thread_,
"START"));
- ACE_UINT32 gsf = ACE_High_Res_Timer::global_scale_factor ();
- u_long i, j;
+ if (size == 1)
+ return;
+
+ bool has_timestamp_inversion = false;
- if (report_buffer_full_ == 0) {
- i = 1;
- }
- else {
- i = this->current_size_;
- }
+ j = i;
+ i = (i + 1) % this->max_size_;
do
{
- if (i == 0) {
- j = this->max_size_;
- }
- else {
- j = i - 1;
- }
-
- ACE_hrtime_t time_difference =
- this->timeprobes_[i].time_ - this->timeprobes_[j].time_;
-
- ACE_UINT32 elapsed_time_in_micro_seconds =
- (ACE_UINT32) (time_difference / gsf);
- ACE_UINT32 remainder =
- (ACE_UINT32) (time_difference % gsf);
- // Convert to the fractional part in microseconds, with 3 digits
- // of precision (hence the 1000).
- ACE_UINT32 fractional = remainder * 1000 / gsf;
+ // When reusing the same ACE_Timeprobe from multiple threads
+ // with Linux on Intel SMP, it sometimes happens that the
+ // recorded times go backward in time if they are recorded from
+ // different threads (see bugzilla #2342). To obtain the
+ // correct signed difference between consecutive recorded times,
+ // one has to cast the time difference to an intermediate signed
+ // integral type of the same size as ACE_hrtime_t.
+
+ double time_difference =
+ (ACE_INT64) (this->timeprobes_[i].time_ - this->timeprobes_[j].time_);
+
+ if (time_difference < 0)
+ has_timestamp_inversion = true;
+
+ // Convert to microseconds.
+ time_difference /= gsf;
ACE_DEBUG ((LM_DEBUG,
- "%-50.50s %8.8x %10u.%03.3u\n",
+ "%-50.50s %8.8x %14.3f\n",
this->find_description_i (i),
this->timeprobes_[i].thread_,
- (unsigned int) elapsed_time_in_micro_seconds,
- (unsigned int) fractional));
+ time_difference));
- i = (i + 1) % this ->max_size_; // Modulus increment: loops around at the end.
+ j = i;
+ i = (i + 1) % this->max_size_;
+ }
+ while (i != this->current_size_);
- } while (i != this->current_size_);
+ static bool inversion_warning_printed = false;
+ if (!inversion_warning_printed && has_timestamp_inversion)
+ {
+ inversion_warning_printed = true;
+ ACE_DEBUG ((LM_DEBUG,
+ "\nWARNING: The timestamps recorded by gethrtime() on"
+ " this platform are\n"
+ "not monotonic across different threads.\n"));
+ }
}
template <class ACE_LOCK, class ALLOCATOR> void
@@ -300,13 +313,15 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_absolute_times (void)
// Sort the event descriptions
this->sort_event_descriptions_i ();
+ u_long size = this->report_buffer_full_ ? this->max_size_
+ : this->current_size_;
+
ACE_DEBUG ((LM_DEBUG,
- "\nACE_Timeprobe_Ex; %d timestamps were recorded:\n",
- this->current_size_));
+ "\nACE_Timeprobe_Ex; %u timestamps were recorded:\n",
+ size));
- if (this->current_size_ == 0 && this->report_buffer_full_ == 0) {
+ if (size == 0)
return;
- }
ACE_DEBUG ((LM_DEBUG,
"\n%-50.50s %8.8s %13.13s\n\n",
@@ -314,13 +329,7 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_absolute_times (void)
"thread",
"stamp"));
- u_long i;
- if (report_buffer_full_ == 0) {
- i = 1;
- }
- else {
- i = this->current_size_;
- }
+ u_long i = this->report_buffer_full_ ? this->current_size_ : 0;
ACE_Time_Value tv; // to convert ACE_hrtime_t
do
@@ -333,17 +342,18 @@ ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::print_absolute_times (void)
this->timeprobes_ [i].thread_,
tv.sec () * 1000000
+ tv.usec ()));
- i = (i + 1) % this ->max_size_; // Modulus increment: loops around at the end.
- } while (i != this->current_size_);
+ // Modulus increment: loops around at the end.
+ i = (i + 1) % this->max_size_;
+ }
+ while (i != this->current_size_);
}
template <class ACE_LOCK, class ALLOCATOR> const char *
ACE_Timeprobe_Ex<ACE_LOCK, ALLOCATOR>::find_description_i (u_long i)
{
- if (this->timeprobes_[i].event_type_ == ACE_timeprobe_t::STRING) {
+ if (this->timeprobes_[i].event_type_ == ACE_timeprobe_t::STRING)
return this->timeprobes_[i].event_.event_description_;
- }
else
{
EVENT_DESCRIPTIONS::iterator iterator = this->sorted_event_descriptions_.begin ();