summaryrefslogtreecommitdiff
path: root/ACE/ace/Malloc_T.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ACE/ace/Malloc_T.cpp')
-rw-r--r--ACE/ace/Malloc_T.cpp1259
1 files changed, 1259 insertions, 0 deletions
diff --git a/ACE/ace/Malloc_T.cpp b/ACE/ace/Malloc_T.cpp
new file mode 100644
index 00000000000..ffa9772644a
--- /dev/null
+++ b/ACE/ace/Malloc_T.cpp
@@ -0,0 +1,1259 @@
+// $Id$
+
+#ifndef ACE_MALLOC_T_CPP
+#define ACE_MALLOC_T_CPP
+
+#include "ace/Malloc_T.h"
+
+#if !defined (ACE_LACKS_PRAGMA_ONCE)
+# pragma once
+#endif /* ACE_LACKS_PRAGMA_ONCE */
+
+#if !defined (__ACE_INLINE__)
+#include "ace/Malloc_T.inl"
+#endif /* __ACE_INLINE__ */
+
+#include "ace/ACE.h"
+#include "ace/OS_NS_string.h"
+
+
+ACE_BEGIN_VERSIONED_NAMESPACE_DECL
+
+template <class T, class ACE_LOCK>
+ACE_Cached_Allocator<T, ACE_LOCK>::ACE_Cached_Allocator (size_t n_chunks)
+ : pool_ (0),
+ free_list_ (ACE_PURE_FREE_LIST)
+{
+ // To maintain alignment requirements, make sure that each element
+ // inserted into the free list is aligned properly for the platform.
+ // Since the memory is allocated as a char[], the compiler won't help.
+ // To make sure enough room is allocated, round up the size so that
+ // each element starts aligned.
+ //
+ // NOTE - this would probably be easier by defining pool_ as a pointer
+ // to T and allocating an array of them (the compiler would probably
+ // take care of the alignment for us), but then the ACE_NEW below would
+ // require a default constructor on T - a requirement that is not in
+ // previous versions of ACE
+ size_t chunk_size = sizeof (T);
+ chunk_size = ACE_MALLOC_ROUNDUP (chunk_size, ACE_MALLOC_ALIGN);
+ ACE_NEW (this->pool_,
+ char[n_chunks * chunk_size]);
+
+ for (size_t c = 0;
+ c < n_chunks;
+ c++)
+ {
+ void* placement = this->pool_ + c * chunk_size;
+ this->free_list_.add (new (placement) ACE_Cached_Mem_Pool_Node<T>);
+ }
+ // Put into free list using placement contructor, no real memory
+ // allocation in the above <new>.
+}
+
+template <class T, class ACE_LOCK>
+ACE_Cached_Allocator<T, ACE_LOCK>::~ACE_Cached_Allocator (void)
+{
+ delete [] this->pool_;
+}
+
+template <class T, class ACE_LOCK> void *
+ACE_Cached_Allocator<T, ACE_LOCK>::malloc (size_t nbytes)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > sizeof (T))
+ return 0;
+
+ // addr() call is really not absolutely necessary because of the way
+ // ACE_Cached_Mem_Pool_Node's internal structure arranged.
+ return this->free_list_.remove ()->addr ();
+}
+
+template <class T, class ACE_LOCK> void *
+ACE_Cached_Allocator<T, ACE_LOCK>::calloc (size_t nbytes,
+ char initial_value)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > sizeof (T))
+ return 0;
+
+ // addr() call is really not absolutely necessary because of the way
+ // ACE_Cached_Mem_Pool_Node's internal structure arranged.
+ void *ptr = this->free_list_.remove ()->addr ();
+ if (ptr != 0)
+ ACE_OS::memset (ptr, initial_value, sizeof (T));
+ return ptr;
+}
+
+template <class T, class ACE_LOCK> void *
+ACE_Cached_Allocator<T, ACE_LOCK>::calloc (size_t,
+ size_t,
+ char)
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+template <class T, class ACE_LOCK> void
+ACE_Cached_Allocator<T, ACE_LOCK>::free (void * ptr)
+{
+ if (ptr != 0)
+ this->free_list_.add ((ACE_Cached_Mem_Pool_Node<T> *) ptr) ;
+}
+
+template <class ACE_LOCK>
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::ACE_Dynamic_Cached_Allocator
+ (size_t n_chunks, size_t chunk_size)
+ : pool_ (0),
+ free_list_ (ACE_PURE_FREE_LIST),
+ chunk_size_ (chunk_size)
+{
+ ACE_ASSERT (chunk_size > 0);
+ chunk_size = ACE_MALLOC_ROUNDUP (chunk_size, ACE_MALLOC_ALIGN);
+ ACE_NEW (this->pool_, char[n_chunks * chunk_size]);
+
+ for (size_t c = 0;
+ c < n_chunks;
+ c++)
+ {
+ void *placement = this->pool_ + c * chunk_size;
+
+ this->free_list_.add (new (placement) ACE_Cached_Mem_Pool_Node<char>);
+ }
+ // Put into free list using placement contructor, no real memory
+ // allocation in the above <new>.
+}
+
+template <class ACE_LOCK>
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::~ACE_Dynamic_Cached_Allocator (void)
+{
+ delete [] this->pool_;
+ this->pool_ = 0;
+ chunk_size_ = 0;
+}
+
+template <class ACE_LOCK> void *
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::malloc (size_t nbytes)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > chunk_size_)
+ return 0;
+
+ // addr() call is really not absolutely necessary because of the way
+ // ACE_Cached_Mem_Pool_Node's internal structure arranged.
+ return this->free_list_.remove ()->addr ();
+}
+
+template <class ACE_LOCK> void *
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::calloc (size_t nbytes,
+ char initial_value)
+{
+ // Check if size requested fits within pre-determined size.
+ if (nbytes > chunk_size_)
+ return 0;
+
+ // addr() call is really not absolutely necessary because of the way
+ // ACE_Cached_Mem_Pool_Node's internal structure arranged.
+ void *ptr = this->free_list_.remove ()->addr ();
+ if (ptr != 0)
+ ACE_OS::memset (ptr, initial_value, chunk_size_);
+ return ptr;
+}
+
+template <class ACE_LOCK> void *
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::calloc (size_t, size_t, char)
+{
+ ACE_NOTSUP_RETURN (0);
+}
+
+template <class ACE_LOCK> void
+ACE_Dynamic_Cached_Allocator<ACE_LOCK>::free (void * ptr)
+{
+ if (ptr != 0)
+ this->free_list_.add ((ACE_Cached_Mem_Pool_Node<char> *) ptr);
+}
+
+ACE_ALLOC_HOOK_DEFINE (ACE_Malloc_T)
+
+template <class MALLOC> void *
+ACE_Allocator_Adapter<MALLOC>::malloc (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::malloc");
+ return this->allocator_.malloc (nbytes);
+}
+
+template <class MALLOC> void *
+ACE_Allocator_Adapter<MALLOC>::calloc (size_t nbytes,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::calloc");
+ return this->allocator_.calloc (nbytes, initial_value);
+}
+
+template <class MALLOC> void *
+ACE_Allocator_Adapter<MALLOC>::calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::calloc");
+ return this->allocator_.calloc (n_elem, elem_size, initial_value);
+}
+
+template <class MALLOC> MALLOC &
+ACE_Allocator_Adapter<MALLOC>::alloc (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::allocator");
+ return this->allocator_;
+}
+
+template <class MALLOC> void
+ACE_Allocator_Adapter<MALLOC>::free (void *ptr)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::free");
+ this->allocator_.free (ptr);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::remove (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::remove");
+ return this->allocator_.remove ();
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::trybind (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::trybind");
+ return this->allocator_.trybind (name, pointer);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::bind (const char *name,
+ void *pointer,
+ int duplicates)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::bind");
+ return this->allocator_.bind (name, pointer, duplicates);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::find (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::find");
+ return this->allocator_.find (name, pointer);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::find (const char *name)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::find");
+ return this->allocator_.find (name);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::unbind (const char *name, void *&pointer)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::unbind");
+ return this->allocator_.unbind (name, pointer);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::unbind (const char *name)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::unbind");
+ return this->allocator_.unbind (name);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::sync (ssize_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::sync");
+ return this->allocator_.sync (len, flags);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::sync (void *addr, size_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::sync");
+ return this->allocator_.sync (addr, len, flags);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::protect (ssize_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::protect");
+ return this->allocator_.protect (len, flags);
+}
+
+template <class MALLOC> int
+ACE_Allocator_Adapter<MALLOC>::protect (void *addr, size_t len, int flags)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::protect");
+ return this->allocator_.protect (addr, len, flags);
+}
+
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (const char *pool_name)
+ : allocator_ (ACE_TEXT_CHAR_TO_TCHAR (pool_name))
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+}
+
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (
+ const char *pool_name,
+ const char *lock_name,
+ MEMORY_POOL_OPTIONS options)
+ : allocator_ (ACE_TEXT_CHAR_TO_TCHAR (pool_name),
+ ACE_TEXT_CHAR_TO_TCHAR (lock_name),
+ options)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+}
+
+#if defined (ACE_HAS_WCHAR)
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (const wchar_t *pool_name)
+ : allocator_ (ACE_TEXT_WCHAR_TO_TCHAR (pool_name))
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+}
+
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter (
+ const wchar_t *pool_name,
+ const wchar_t *lock_name,
+ MEMORY_POOL_OPTIONS options)
+ : allocator_ (ACE_TEXT_WCHAR_TO_TCHAR (pool_name),
+ ACE_TEXT_WCHAR_TO_TCHAR (lock_name),
+ options)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::ACE_Allocator_Adapter");
+}
+#endif /* ACE_HAS_WCHAR */
+
+template <class MALLOC>
+ACE_Allocator_Adapter<MALLOC>::~ACE_Allocator_Adapter (void)
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::~ACE_Allocator_Adapter");
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+template <class MALLOC> void
+ACE_Allocator_Adapter<MALLOC>::print_stats (void) const
+{
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::print_stats");
+ this->allocator_.print_stats ();
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+template <class MALLOC> void
+ACE_Allocator_Adapter<MALLOC>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Allocator_Adapter<MALLOC>::dump");
+ this->allocator_.dump ();
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->memory_pool_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("cb_ptr_ = %@\n"), this->cb_ptr_));
+ this->cb_ptr_->dump ();
+#if defined (ACE_HAS_MALLOC_STATS)
+ if (this->cb_ptr_ != 0)
+ this->cb_ptr_->malloc_stats_.dump ();
+#endif /* ACE_HAS_MALLOC_STATS */
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+#if defined (ACE_HAS_MALLOC_STATS)
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::print_stats (void) const
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::print_stats");
+ ACE_GUARD (ACE_LOCK, ace_mon, *this->lock_);
+
+ if (this->cb_ptr_ == 0)
+ return;
+ this->cb_ptr_->malloc_stats_.dump ();
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) contents of freelist:\n")));
+
+ for (MALLOC_HEADER *currp = this->cb_ptr_->freep_->next_block_;
+ ;
+ currp = currp->next_block_)
+ {
+ ACE_DEBUG ((LM_DEBUG,
+ ACE_TEXT ("(%P|%t) ptr = %@, MALLOC_HEADER units = %d, byte units = %d\n"),
+ currp,
+ currp->size_,
+ currp->size_ * sizeof (MALLOC_HEADER)));
+ if (currp == this->cb_ptr_->freep_)
+ break;
+ }
+}
+#endif /* ACE_HAS_MALLOC_STATS */
+
+// Put <ptr> in the free list (locked version).
+
+template<ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::free (void *ptr)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::free");
+ ACE_GUARD (ACE_LOCK, ace_mon, *this->lock_);
+
+ this->shared_free (ptr);
+}
+
+// This function is called by the ACE_Malloc_T constructor to initialize
+// the memory pool. The first time in it allocates room for the
+// control block (as well as a chunk of memory, depending on
+// rounding...). Depending on the type of <MEM_POOL> (i.e., shared
+// vs. local) subsequent calls from other processes will only
+// initialize the control block pointer.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::open (void)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::open");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ size_t rounded_bytes = 0;
+ int first_time = 0;
+
+ this->cb_ptr_ = (ACE_CB *)
+ this->memory_pool_.init_acquire (sizeof *this->cb_ptr_,
+ rounded_bytes,
+ first_time);
+ if (this->cb_ptr_ == 0)
+ ACE_ERROR_RETURN ((LM_ERROR,
+ ACE_TEXT ("(%P|%t) %p\n"),
+ ACE_TEXT ("init_acquire failed")),
+ -1);
+ else if (first_time)
+ {
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) first time in, control block = %@\n"), this->cb_ptr_));
+
+ MALLOC_HEADER::init_ptr (&this->cb_ptr_->freep_,
+ &this->cb_ptr_->base_,
+ this->cb_ptr_);
+
+ MALLOC_HEADER::init_ptr (&this->cb_ptr_->freep_->next_block_,
+ this->cb_ptr_->freep_,
+ this->cb_ptr_);
+
+ NAME_NODE::init_ptr (&this->cb_ptr_->name_head_,
+ 0,
+ this->cb_ptr_);
+
+ this->cb_ptr_->freep_->size_ = 0;
+ this->cb_ptr_->ref_counter_ = 1;
+
+ if (rounded_bytes > (sizeof *this->cb_ptr_ + sizeof (MALLOC_HEADER)))
+ {
+ // If we've got any extra space at the end of the control
+ // block, then skip past the dummy <MALLOC_HEADER> to
+ // point at the first free block.
+ MALLOC_HEADER *p = ((MALLOC_HEADER *) (this->cb_ptr_->freep_)) + 1;
+
+ MALLOC_HEADER::init_ptr (&p->next_block_,
+ 0,
+ this->cb_ptr_);
+
+ // Why aC++ in 64-bit mode can't grok this, I have no
+ // idea... but it ends up with an extra bit set which makes
+ // size_ really big without this hack.
+#if defined (__hpux) && defined (__LP64__)
+ size_t hpux11_hack = (rounded_bytes - sizeof *this->cb_ptr_)
+ / sizeof (MALLOC_HEADER);
+ p->size_ = hpux11_hack;
+#else
+ p->size_ = (rounded_bytes - sizeof *this->cb_ptr_)
+ / sizeof (MALLOC_HEADER);
+#endif /* (__hpux) && defined (__LP64__) */
+
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nchunks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nblocks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.ninuse_);
+
+ // Insert the newly allocated chunk of memory into the free
+ // list. Add "1" to skip over the <MALLOC_HEADER> when
+ // freeing the pointer.
+ this->shared_free (p + 1);
+ }
+ }
+ else
+ ++this->cb_ptr_->ref_counter_;
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T (const ACE_TCHAR *pool_name)
+ : cb_ptr_ (0),
+ memory_pool_ (pool_name),
+ bad_flag_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+ this->lock_ = ACE_Malloc_Lock_Adapter_T<ACE_LOCK> ()(pool_name);
+ if (this->lock_ == 0)
+ return;
+
+ this->delete_lock_ = true;
+
+ this->bad_flag_ = this->open ();
+
+ if (this->bad_flag_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T")));
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_TCHAR *lock_name,
+ const ACE_MEM_POOL_OPTIONS *options)
+ : cb_ptr_ (0),
+ memory_pool_ (pool_name, options),
+ bad_flag_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+ // Use pool_name for lock_name if lock_name not passed.
+ const ACE_TCHAR *name = lock_name ? lock_name : pool_name;
+ this->lock_ = ACE_Malloc_Lock_Adapter_T<ACE_LOCK> ()(name);
+ if (this->lock_ == 0)
+ return;
+
+ this->delete_lock_ = true;
+
+ this->bad_flag_ = this->open ();
+ if (this->bad_flag_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T")));
+}
+
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T (const ACE_TCHAR *pool_name,
+ const ACE_MEM_POOL_OPTIONS *options,
+ ACE_LOCK *lock)
+ : cb_ptr_ (0),
+ memory_pool_ (pool_name, options),
+ lock_ (lock),
+ delete_lock_ (false),
+ bad_flag_ (0)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T");
+
+ if (lock == 0)
+ {
+ this->bad_flag_ = -1;
+ errno = EINVAL;
+ return;
+ }
+
+ this->bad_flag_ = this->open ();
+ if (this->bad_flag_ == -1)
+ ACE_ERROR ((LM_ERROR,
+ ACE_TEXT ("%p\n"),
+ ACE_TEXT ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_T")));
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::~ACE_Malloc_T (void)
+{
+ ACE_TRACE ("ACE_Malloc_T<MEM_POOL>::~ACE_Malloc_T<MEM_POOL>");
+ if (this->delete_lock_)
+ {
+ delete this->lock_;
+ this->lock_ = 0;
+ }
+}
+
+// Clean up the resources allocated by ACE_Malloc_T.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::remove (void)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::remove");
+ // ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("(%P|%t) destroying ACE_Malloc_T\n")));
+
+#if defined (ACE_HAS_MALLOC_STATS)
+ this->print_stats ();
+#endif /* ACE_HAS_MALLOC_STATS */
+
+ // Remove the ACE_LOCK.
+ if (this->delete_lock_)
+ this->lock_->remove ();
+
+ // Give the memory pool a chance to release its resources.
+ int const result = this->memory_pool_.release ();
+
+ // Reset this->cb_ptr_ as it is no longer valid.
+ // There's also no need to keep the reference counter as the
+ // underlying memory pool has been destroyed.
+ // Also notice that we are leaving the decision of removing
+ // the pool to users so they can map to the same mmap file
+ // again.
+ this->cb_ptr_ = 0;
+
+ return result;
+}
+
+// General-purpose memory allocator. Assumes caller holds the locks.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_malloc (size_t nbytes)
+{
+#if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_malloc");
+#endif /* !ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ if (this->cb_ptr_ == 0)
+ return 0;
+
+ // Round up request to a multiple of the MALLOC_HEADER size.
+ size_t const nunits =
+ (nbytes + sizeof (MALLOC_HEADER) - 1) / sizeof (MALLOC_HEADER)
+ + 1; // Add one for the <MALLOC_HEADER> itself.
+
+ MALLOC_HEADER *prevp = 0;
+ MALLOC_HEADER *currp = 0;
+
+ ACE_SEH_TRY
+ {
+ // Begin the search starting at the place in the freelist where the
+ // last block was found.
+ prevp = this->cb_ptr_->freep_;
+ currp = prevp->next_block_;
+ }
+#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ currp = prevp->next_block_;
+ }
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ // Search the freelist to locate a block of the appropriate size.
+
+ while (1)
+
+ // *Warning* Do not use "continue" within this while-loop.
+
+ {
+ ACE_SEH_TRY
+ {
+ if (currp->size_ >= nunits) // Big enough
+ {
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.ninuse_);
+ if (currp->size_ == nunits)
+ // Exact size, just update the pointers.
+ prevp->next_block_ = currp->next_block_;
+ else
+ {
+ // Remaining chunk is larger than requested block, so
+ // allocate at tail end.
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nblocks_);
+ currp->size_ -= nunits;
+ currp += currp->size_;
+ MALLOC_HEADER::init_ptr (&currp->next_block_,
+ 0,
+ this->cb_ptr_);
+ currp->size_ = nunits;
+ }
+ this->cb_ptr_->freep_ = prevp;
+
+ // Skip over the MALLOC_HEADER when returning pointer.
+ return currp + 1;
+ }
+ else if (currp == this->cb_ptr_->freep_)
+ {
+ // We've wrapped around freelist without finding a
+ // block. Therefore, we need to ask the memory pool for
+ // a new chunk of bytes.
+
+ size_t chunk_bytes = 0;
+
+ currp = (MALLOC_HEADER *)
+ this->memory_pool_.acquire (nunits * sizeof (MALLOC_HEADER),
+ chunk_bytes);
+ void *remap_addr = this->memory_pool_.base_addr ();
+ if (remap_addr != 0)
+ this->cb_ptr_ = (ACE_CB *) remap_addr;
+
+ if (currp != 0)
+ {
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nblocks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.nchunks_);
+ ACE_MALLOC_STATS (++this->cb_ptr_->malloc_stats_.ninuse_);
+
+ MALLOC_HEADER::init_ptr (&currp->next_block_,
+ 0,
+ this->cb_ptr_);
+ // Compute the chunk size in MALLOC_HEADER units.
+ currp->size_ = chunk_bytes / sizeof (MALLOC_HEADER);
+
+ // Insert the newly allocated chunk of memory into the
+ // free list. Add "1" to skip over the
+ // <MALLOC_HEADER> when freeing the pointer since
+ // the first thing <free> does is decrement by this
+ // amount.
+ this->shared_free (currp + 1);
+ currp = this->cb_ptr_->freep_;
+ }
+ else
+ return 0;
+ // Shouldn't do this here because of errors with the wchar ver
+ // This is because ACE_ERROR_RETURN converts the __FILE__ to
+ // wchar before printing out. The compiler will complain
+ // about this since a destructor would present in a SEH block
+ //ACE_ERROR_RETURN ((LM_ERROR,
+ // ACE_TEXT ("(%P|%t) %p\n"),
+ // ACE_TEXT ("malloc")),
+ // 0);
+ }
+ prevp = currp;
+ currp = currp->next_block_;
+ }
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ }
+ }
+ ACE_NOTREACHED (return 0;)
+}
+
+// General-purpose memory allocator.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::malloc (size_t nbytes)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::malloc");
+ ACE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, 0);
+
+ return this->shared_malloc (nbytes);
+}
+
+// General-purpose memory allocator.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc (size_t nbytes,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc");
+ void *ptr = this->malloc (nbytes);
+
+ if (ptr != 0)
+ ACE_OS::memset (ptr, initial_value, nbytes);
+
+ return ptr;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void *
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc (size_t n_elem,
+ size_t elem_size,
+ char initial_value)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::calloc");
+
+ return this->calloc (n_elem * elem_size, initial_value);
+}
+
+// Put block AP in the free list (must be called with locks held!)
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_free (void *ap)
+{
+#if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_free");
+#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ if (ap == 0 || this->cb_ptr_ == 0)
+ return;
+
+ // Adjust AP to point to the block MALLOC_HEADER
+ MALLOC_HEADER *blockp = ((MALLOC_HEADER *) ap) - 1;
+ MALLOC_HEADER *currp = this->cb_ptr_->freep_;
+
+ // Search until we find the location where the blocks belongs. Note
+ // that addresses are kept in sorted order.
+
+ ACE_SEH_TRY
+ {
+ for (;
+ blockp <= currp
+ || blockp >= (MALLOC_HEADER *) currp->next_block_;
+ currp = currp->next_block_)
+ {
+ if (currp >= (MALLOC_HEADER *) currp->next_block_
+ && (blockp > currp
+ || blockp < (MALLOC_HEADER *) currp->next_block_))
+ // Freed block at the start or the end of the memory pool.
+ break;
+ }
+
+ // Join to upper neighbor.
+ if ((blockp + blockp->size_) == currp->next_block_)
+ {
+ ACE_MALLOC_STATS (--this->cb_ptr_->malloc_stats_.nblocks_);
+ blockp->size_ += currp->next_block_->size_;
+ blockp->next_block_ = currp->next_block_->next_block_;
+ }
+ else
+ blockp->next_block_ = currp->next_block_;
+
+ // Join to lower neighbor.
+ if ((currp + currp->size_) == blockp)
+ {
+ ACE_MALLOC_STATS (--this->cb_ptr_->malloc_stats_.nblocks_);
+ currp->size_ += blockp->size_;
+ currp->next_block_ = blockp->next_block_;
+ }
+ else
+ currp->next_block_ = blockp;
+
+ ACE_MALLOC_STATS (--this->cb_ptr_->malloc_stats_.ninuse_);
+ this->cb_ptr_->freep_ = currp;
+ }
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ }
+}
+
+// No locks held here, caller must acquire/release lock.
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void*
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_find (const char *name)
+{
+#if !defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_find");
+#endif /* !ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
+
+ if (this->cb_ptr_ == 0)
+ return 0;
+
+ ACE_SEH_TRY
+ {
+ for (NAME_NODE *node = this->cb_ptr_->name_head_;
+ node != 0;
+ node = node->next_)
+ if (ACE_OS::strcmp (node->name (),
+ name) == 0)
+ return node;
+ }
+ ACE_SEH_EXCEPT (this->memory_pool_.seh_selector (GetExceptionInformation ()))
+ {
+ }
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::shared_bind (const char *name,
+ void *pointer)
+{
+ if (this->cb_ptr_ == 0)
+ return -1;
+
+ // Combine the two allocations into one to avoid overhead...
+ NAME_NODE *new_node = 0;
+
+ ACE_ALLOCATOR_RETURN (new_node,
+ (NAME_NODE *)
+ this->shared_malloc (sizeof (NAME_NODE) +
+ ACE_OS::strlen (name) + 1),
+ -1);
+ char *name_ptr = (char *) (new_node + 1);
+
+ // Use operator placement new to insert <new_node> at the head of
+ // the linked list of <NAME_NODE>s.
+ NAME_NODE *result =
+ new (new_node) NAME_NODE (name,
+ name_ptr,
+ reinterpret_cast<char *> (pointer),
+ this->cb_ptr_->name_head_);
+ this->cb_ptr_->name_head_ = result;
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::trybind (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::trybind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ NAME_NODE *node = (NAME_NODE *) this->shared_find (name);
+
+ if (node == 0)
+ // Didn't find it, so insert it.
+ return this->shared_bind (name, pointer);
+
+ // Found it, so return a copy of the current entry.
+ pointer = (char *) node->pointer_;
+ return 1;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::bind (const char *name,
+ void *pointer,
+ int duplicates)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::bind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ if (duplicates == 0 && this->shared_find (name) != 0)
+ // If we're not allowing duplicates, then if the name is already
+ // present, return 1.
+ return 1;
+
+ // If we get this far, either we're allowing duplicates or we didn't
+ // find the name yet.
+ return this->shared_bind (name, pointer);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find (const char *name,
+ void *&pointer)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find");
+
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ NAME_NODE *node = (NAME_NODE *) this->shared_find (name);
+
+ if (node == 0)
+ return -1;
+
+ pointer = (char *) node->pointer_;
+ return 0;
+}
+
+// Returns a count of the number of available chunks that can hold
+// <size> byte allocations. Function can be used to determine if you
+// have reached a water mark. This implies a fixed amount of allocated
+// memory.
+//
+// @param size - the chunk size of that you would like a count of
+// @return function returns the number of chunks of the given size
+// that would fit in the currently allocated memory
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> ssize_t
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::avail_chunks (size_t size) const
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::avail_chunks");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ if (this->cb_ptr_ == 0)
+ return -1;
+
+ size_t count = 0;
+ // Avoid dividing by 0...
+ size = size == 0 ? 1 : size;
+ MALLOC_HEADER *currp = this->cb_ptr_->freep_;
+
+ // Calculate how many will fit in this block.
+ do {
+ size_t avail_size = currp->size_ == 0 ? 0 : currp->size_ - 1;
+ if (avail_size * sizeof (MALLOC_HEADER) >= size)
+ count += avail_size * sizeof (MALLOC_HEADER) / size;
+ currp = currp->next_block_;
+ }
+ while (currp != this->cb_ptr_->freep_);
+
+ return count;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find (const char *name)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::find");
+ ACE_READ_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ return this->shared_find (name) == 0 ? -1 : 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind (const char *name, void *&pointer)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind");
+ ACE_WRITE_GUARD_RETURN (ACE_LOCK, ace_mon, *this->lock_, -1);
+
+ if (this->cb_ptr_ == 0)
+ return -1;
+
+ NAME_NODE *prev = 0;
+
+ for (NAME_NODE *curr = this->cb_ptr_->name_head_;
+ curr != 0;
+ curr = curr->next_)
+ {
+ if (ACE_OS::strcmp (curr->name (), name) == 0)
+ {
+ pointer = (char *) curr->pointer_;
+
+ if (prev == 0)
+ this->cb_ptr_->name_head_ = curr->next_;
+ else
+ prev->next_ = curr->next_;
+
+ if (curr->next_)
+ curr->next_->prev_ = prev;
+
+ // This will free up both the node and the name due to our
+ // clever trick in <bind>!
+ this->shared_free (curr);
+ return 0;
+ }
+ prev = curr;
+ }
+
+ // Didn't find it, so fail.
+ return -1;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind (const char *name)
+{
+ ACE_TRACE ("ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::unbind");
+ void *temp = 0;
+ return this->unbind (name, temp);
+}
+
+/*****************************************************************************/
+
+template <class ACE_LOCK> ACE_LOCK *
+ACE_Malloc_Lock_Adapter_T<ACE_LOCK>::operator () (const ACE_TCHAR *name)
+{
+ ACE_LOCK *p = 0;
+ if (name == 0)
+ ACE_NEW_RETURN (p, ACE_LOCK (name), 0);
+ else
+ ACE_NEW_RETURN (p, ACE_LOCK (ACE::basename (name,
+ ACE_DIRECTORY_SEPARATOR_CHAR)),
+ 0);
+ return p;
+}
+
+/*****************************************************************************/
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->curr_->dump ();
+ this->guard_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("name_ = %C\n"), this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_LIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name)
+ : malloc_ (malloc),
+ curr_ (0),
+ guard_ (*malloc_.lock_),
+ name_ (name != 0 ? ACE_OS::strdup (name) : 0)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_LIFO_Iterator_T");
+ // Cheap trick to make code simple.
+ // @@ Doug, this looks like trouble...
+ NAME_NODE temp;
+ this->curr_ = &temp;
+ this->curr_->next_ = malloc_.cb_ptr_->name_head_;
+
+ this->advance ();
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::~ACE_Malloc_LIFO_Iterator_T (void)
+{
+ ACE_OS::free ((void *) this->name_);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry,
+ const char *&name)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = (char *) this->curr_->pointer_;
+ name = this->curr_->name ();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = this->curr_->pointer_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done (void) const
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done");
+
+ return this->curr_ == 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance (void)
+{
+ ACE_TRACE ("ACE_Malloc_LIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance");
+
+ this->curr_ = this->curr_->next_;
+
+ if (this->name_ == 0)
+ return this->curr_ != 0;
+
+ while (this->curr_ != 0
+ && ACE_OS::strcmp (this->name_,
+ this->curr_->name ()) != 0)
+ this->curr_ = this->curr_->next_;
+
+ return this->curr_ != 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> void
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump (void) const
+{
+#if defined (ACE_HAS_DUMP)
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::dump");
+
+ ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
+ this->curr_->dump ();
+ this->guard_.dump ();
+ ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("name_ = %s\n"), this->name_));
+ ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
+#endif /* ACE_HAS_DUMP */
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_FIFO_Iterator_T (ACE_Malloc_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB> &malloc,
+ const char *name)
+ : malloc_ (malloc),
+ curr_ (0),
+ guard_ (*malloc_.lock_),
+ name_ (name != 0 ? ACE_OS::strdup (name) : 0)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::ACE_Malloc_FIFO_Iterator");
+ // Cheap trick to make code simple.
+ // @@ Doug, this looks like trouble...
+ NAME_NODE temp;
+ this->curr_ = &temp;
+ this->curr_->next_ = malloc_.cb_ptr_->name_head_;
+ this->curr_->prev_ = 0;
+
+ // Go to the first element that was inserted.
+ this->start ();
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB>
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::~ACE_Malloc_FIFO_Iterator_T (void)
+{
+ ACE_OS::free ((void *) this->name_);
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry,
+ const char *&name)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = (char *) this->curr_->pointer_;
+ name = this->curr_->name ();
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next (void *&next_entry)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::next");
+
+ if (this->curr_ != 0)
+ {
+ next_entry = this->curr_->pointer_;
+ return 1;
+ }
+ else
+ return 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done (void) const
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::done");
+
+ return this->curr_ == 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance (void)
+{
+ ACE_TRACE ("ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::advance");
+
+ this->curr_ = this->curr_->prev_;
+
+ if (this->name_ == 0)
+ return this->curr_ != 0;
+
+ while (this->curr_ != 0
+ && ACE_OS::strcmp (this->name_,
+ this->curr_->name ()) != 0)
+ this->curr_ = this->curr_->prev_;
+
+ return this->curr_ != 0;
+}
+
+template <ACE_MEM_POOL_1, class ACE_LOCK, class ACE_CB> int
+ACE_Malloc_FIFO_Iterator_T<ACE_MEM_POOL_2, ACE_LOCK, ACE_CB>::start (void)
+{
+ this->curr_ = this->curr_->next_;
+ NAME_NODE *prev = 0;
+
+ // Locate the element that was inserted first.
+ // @@ We could optimize this by making the list a circular list or
+ // storing an extra pointer.
+ while (this->curr_ != 0)
+ {
+ prev = this->curr_;
+ this->curr_ = this->curr_->next_;
+ }
+
+ this->curr_ = prev;
+ return this->curr_ != 0;
+}
+
+ACE_END_VERSIONED_NAMESPACE_DECL
+
+#endif /* ACE_MALLOC_T_CPP */