BasicQueueLinkAllocator_T.h

Go to the documentation of this file.
00001 /*
00002  *
00003  *
00004  * Distributed under the OpenDDS License.
00005  * See: http://www.opendds.org/license.html
00006  */
00007 
00008 #ifndef OPENDDS_DCPS_BASICQUEUELINKALLOCATOR_T_H
00009 #define OPENDDS_DCPS_BASICQUEUELINKALLOCATOR_T_H
00010 
00011 #include "BasicQueueLink_T.h"
00012 #include "BasicQueueLinkChunk_T.h"
00013 #include "ace/Malloc_T.h"
00014 #include "ace/Null_Mutex.h"
00015 #include "dds/DCPS/PoolAllocationBase.h"
00016 
00017 namespace OpenDDS {
00018 namespace DCPS {
00019 
00020 template <typename T>
00021 class BasicQueueLinkAllocator : public ACE_New_Allocator, public PoolAllocationBase {
00022 private:
00023 
00024   typedef BasicQueueLink<T>                              LinkType;
00025   typedef BasicQueueLinkChunk<T>                         ChunkType;
00026   typedef ACE_Cached_Mem_Pool_Node<LinkType >            NodeType;
00027   typedef ACE_Locked_Free_List<NodeType, ACE_Null_Mutex> FreeListType;
00028 
00029 public:
00030 
00031   /// Constructor.
00032   BasicQueueLinkAllocator(size_t chunk_size, size_t initial_chunks)
00033     : chunk_size_(chunk_size),
00034       head_chunk_(0),
00035       tail_chunk_(0),
00036       free_list_(ACE_PURE_FREE_LIST) {
00037     for (size_t i = 0; i < initial_chunks; i++) {
00038       this->grow();
00039     }
00040   }
00041 
00042   /// Virtual Destructor.
00043   virtual ~BasicQueueLinkAllocator() {
00044     ChunkType* chunk = this->head_chunk_;
00045 
00046     while (chunk != 0) {
00047       ChunkType* next_chunk = chunk->next_;
00048       delete chunk;
00049       chunk = next_chunk;
00050     }
00051   }
00052 
00053   /// malloc implementation.
00054   void* malloc(size_t nbytes = sizeof(LinkType)) {
00055     // Check if size requested fits within pre-determined size.
00056     if (nbytes != sizeof(LinkType)) {
00057       return 0;
00058     }
00059 
00060     // addr() call is really not absolutely necessary because
00061     // of the way ACE_Cached_Mem_Pool_Node's internal
00062     // structure is arranged.
00063     void* ptr = this->free_list_.remove()->addr();
00064 
00065     if (ptr == 0) {
00066       this->grow();
00067       ptr = this->free_list_.remove()->addr();
00068     }
00069 
00070     return ptr;
00071   }
00072 
00073   /// calloc implementation.
00074   virtual void* calloc(size_t nbytes = sizeof(LinkType),
00075                        char initial_value = '\0') {
00076     // Check if size requested fits the pre-determined size.
00077     if (nbytes != sizeof(LinkType)) {
00078       return 0;
00079     }
00080 
00081     // addr() call is really not absolutely necessary because
00082     // of the way ACE_Cached_Mem_Pool_Node's internal
00083     // structure is arranged.
00084     void* ptr = this->free_list_.remove()->addr();
00085 
00086     if (ptr == 0) {
00087       this->grow();
00088       ptr = this->free_list_.remove()->addr();
00089     }
00090 
00091     ACE_OS::memset(ptr, initial_value, sizeof(LinkType));
00092 
00093     return ptr;
00094   }
00095 
00096   /// This interface not supported.
00097   virtual void* calloc(size_t n_elem,
00098                        size_t elem_size,
00099                        char   initial_value = '\0') {
00100     ACE_UNUSED_ARG(n_elem);
00101     ACE_UNUSED_ARG(elem_size);
00102     ACE_UNUSED_ARG(initial_value);
00103     ACE_NOTSUP_RETURN(0);
00104   }
00105 
00106   /// free implementation.
00107   void free(void* ptr) {
00108     this->free_list_.add((NodeType*)ptr);
00109   }
00110 
00111 private:
00112 
00113   /// Grow by another chunk.
00114   void grow() {
00115     ChunkType* chunk;
00116     ACE_NEW(chunk, ChunkType(this->chunk_size_));
00117 
00118     for (size_t i = 0; i < this->chunk_size_; ++i) {
00119       void* placement = &(chunk->links_[i]);
00120       this->free_list_.add(new(placement) NodeType);
00121     }
00122 
00123     // Add the chunk to the "chunk list".
00124     if (head_chunk_ == 0) {
00125       this->head_chunk_ = this->tail_chunk_ = chunk;
00126 
00127     } else {
00128       this->tail_chunk_->next_ = chunk;
00129       this->tail_chunk_ = chunk;
00130     }
00131   }
00132 
00133   /// Number of links to allocate for each chunk.
00134   size_t chunk_size_;
00135 
00136   /// The first chunk
00137   ChunkType* head_chunk_;
00138 
00139   /// The last chunk
00140   ChunkType* tail_chunk_;
00141 
00142   /// Maintain a cached memory free list.
00143   FreeListType free_list_;
00144 };
00145 
00146 } // namespace DCPS
00147 } // namespace OpenDDS
00148 
00149 #endif  /* OPENDDS_DCPS_BASICQUEUELINKALLOCATOR_T_H */

Generated on Fri Feb 12 20:05:18 2016 for OpenDDS by  doxygen 1.4.7