summaryrefslogtreecommitdiff
path: root/ace/Timer_Heap_T.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ace/Timer_Heap_T.cpp')
-rw-r--r--ace/Timer_Heap_T.cpp83
1 files changed, 77 insertions, 6 deletions
diff --git a/ace/Timer_Heap_T.cpp b/ace/Timer_Heap_T.cpp
index 8f777920706..644a13b90db 100644
--- a/ace/Timer_Heap_T.cpp
+++ b/ace/Timer_Heap_T.cpp
@@ -1,18 +1,37 @@
// $Id$
-#ifndef ACE_TIMER_HEAP_T_C
-#define ACE_TIMER_HEAP_T_C
+#ifndef ACE_TIMER_HEAP_T_CPP
+#define ACE_TIMER_HEAP_T_CPP
#include "ace/Timer_Heap_T.h"
#include "ace/Log_Msg.h"
#include "ace/Guard_T.h"
+#include "ace/OS_NS_errno.h"
#include "ace/OS_NS_string.h"
#if !defined (ACE_LACKS_PRAGMA_ONCE)
# pragma once
#endif /* ACE_LACKS_PRAGMA_ONCE */
-ACE_RCSID(ace, Timer_Heap_T, "$Id$")
+/*
+** The ACE_Timer_Heap::max_size_ and array loops, checks, etc. are all size_t.
+** The timer IDs are long, and since they are indices into the heap, we need
+** to be sure that the timer heap size can fit in a long. Hence, when size
+** is (re)set, limit it to the maximum long value. We use the C++ standard
+** limits if available.
+*/
+#if !defined(ACE_LACKS_NUMERIC_LIMITS)
+// some platforms pollute the namespace by defining max() and min() macros
+#ifdef max
+#undef max
+#endif
+#ifdef min
+#undef min
+#endif
+#include <limits>
+#endif /* ACE_LACKS_NUMERIC_LIMITS */
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
// Define some simple macros to clarify the code.
#define ACE_HEAP_PARENT(X) (X == 0 ? 0 : (((X) - 1) / 2))
@@ -89,6 +108,21 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (size_t size,
{
ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
+ // Possibly reduce size to fit in a long.
+#if !defined(ACE_LACKS_NUMERIC_LIMITS)
+ if (size > static_cast<size_t> (std::numeric_limits<long>::max ()))
+ {
+ size = static_cast<size_t> (std::numeric_limits<long>::max ());
+ this->max_size_ = size;
+ }
+#else
+ if (size > LONG_MAX)
+ {
+ size = LONG_MAX;
+ this->max_size_ = size;
+ }
+#endif /* ACE_LACKS_NUMERIC_LIMITS */
+
// Create the heap array.
ACE_NEW (this->heap_,
ACE_Timer_Node_T<TYPE> *[size]);
@@ -146,6 +180,15 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::ACE_Timer_Heap_T (FUNCTOR *upcall_fun
{
ACE_TRACE ("ACE_Timer_Heap_T::ACE_Timer_Heap_T");
+ // Possibly reduce size to fit in a long.
+#if !defined(ACE_LACKS_NUMERIC_LIMITS)
+ if (this->max_size_ > static_cast<size_t> (std::numeric_limits<long>::max ()))
+ this->max_size_ = static_cast<size_t> (std::numeric_limits<long>::max ());
+#else
+ if (this->max_size_ > LONG_MAX)
+ this->max_size_ = LONG_MAX;
+#endif /* ACE_LACKS_NUMERIC_LIMITS */
+
// Create the heap array.
#if defined (__IBMCPP__) && (__IBMCPP__ >= 400) && defined (_WINDOWS)
ACE_NEW (this->heap_,
@@ -237,7 +280,7 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::pop_freelist (void)
this->timer_ids_min_free_ = this->max_size_;
}
- return this->timer_ids_curr_;
+ return static_cast<long> (this->timer_ids_curr_);
}
template <class TYPE, class FUNCTOR, class ACE_LOCK> void
@@ -474,9 +517,27 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::insert (ACE_Timer_Node_T<TYPE> *new_n
template <class TYPE, class FUNCTOR, class ACE_LOCK> void
ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::grow_heap (void)
{
- // All the containers will double in size from max_size_
+ // All the containers will double in size from max_size_.
size_t new_size = this->max_size_ * 2;
+#if 0
+ // Yikes - there's no way to flag a failure of going out of range of
+ // a 'long' - this is a problem that should be addressed at some point.
+#if !defined(ACE_LACKS_NUMERIC_LIMITS)
+ if (new_size > std::numeric_limits<long>::max ())
+ new_size = std::numeric_limits<long>::max ();
+#else
+ if (new_size > LONG_MAX)
+ new_size = LONG_MAX;
+#endif /* ACE_LACKS_NUMERIC_LIMITS */
+
+ if (new_size <= this->max_size_) // We are already at the limit
+ {
+ errno = ENOMEM;
+ return -1;
+ }
+#endif /* 0 */
+
// First grow the heap itself.
ACE_Timer_Node_T<TYPE> **new_heap = 0;
@@ -554,6 +615,9 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::grow_heap (void)
}
this->max_size_ = new_size;
+ // Force rescan of list from beginning for a free slot (I think...)
+ // This fixed Bugzilla #2447.
+ this->timer_ids_min_free_ = this->max_size_;
}
// Reschedule a periodic timer. This function must be called with the
@@ -765,6 +829,11 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::cancel (const TYPE &type,
number_of_cancellations++;
this->free_node (temp);
+
+ // We reset to zero so that we don't miss checking any nodes
+ // if a reheapify occurs when a node is removed. There
+ // may be a better fix than this, however.
+ i = 0;
}
else
i++;
@@ -814,4 +883,6 @@ ACE_Timer_Heap_T<TYPE, FUNCTOR, ACE_LOCK>::get_first (void)
return this->cur_size_ == 0 ? 0 : this->heap_[0];
}
-#endif /* ACE_TIMER_HEAP_T_C */
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_TIMER_HEAP_T_CPP */