Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

Malloc.h

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 
00003 //==========================================================================
00004 /**
00005  *  @file    Malloc.h
00006  *
00007  *  $Id: Malloc.h,v 1.1.1.4 2003/02/21 18:36:32 chad Exp $
00008  *
00009  *  @author Doug Schmidt and Irfan Pyarali
00010  */
00011 //==========================================================================
00012 
00013 #ifndef ACE_MALLOC_H
00014 #define ACE_MALLOC_H
00015 
00016 #include "ace/pre.h"
00017 
00018 #include "ace/ACE_export.h"
00019 
00020 #if !defined (ACE_LACKS_PRAGMA_ONCE)
00021 # pragma once
00022 #endif /* ACE_LACKS_PRAGMA_ONCE */
00023 
00024 #include "ace/OS.h"
00025 #include "ace/Log_Msg.h"
00026 
00027 #if defined (ACE_HAS_MALLOC_STATS)
00028 #include "ace/Atomic_Op.h"
00029 #if defined (ACE_HAS_THREADS)
00030 #include "ace/Process_Mutex.h"
00031 #define ACE_PROCESS_MUTEX ACE_Process_Mutex
00032 #else
00033 #include "ace/SV_Semaphore_Simple.h"
00034 #define ACE_PROCESS_MUTEX ACE_SV_Semaphore_Simple
00035 #endif /* ACE_HAS_THREADS */
00036 
00037 typedef ACE_Atomic_Op<ACE_PROCESS_MUTEX, int> ACE_INT;
00038 
00039 /******************************************************************
00040 
00041 * Assume that ACE_MALLOC_ALIGN is the number of bytes of the alignment
00042   of the platform. Usually, this will be 4 on most platforms.  Some
00043   platforms require this to be 8.  In any case, this macro should
00044   always be a 2's power.
00045 
00046 * Malloc_Header structure.
00047 
00048   Notice that sizeof (ACE_Malloc_Header) must be multiple of
00049   ACE_MALLOC_ALIGN
00050 
00051    +-----------------------------------------+
00052    |MALLOC_HEADER_PTR *next_block_;          |
00053    |   // Points to next free Malloc_Header  |
00054    |   // in this chain.                     |
00055    +-----------------------------------------+
00056    |size_t size_;                            |
00057    |   // Size of buffer associate with      |
00058    |   // this Malloc_Header                 |
00059    }   // The size is in number of           |
00060    |   // Malloc_Header (including this one.)|
00061    +-----------------------------------------+
00062    |long paddings_[ACE_MALLOC_PADDING_SIZE]; |
00063    |   // Padding long array.  This purpose  |
00064    |   // of this padding array is to adjust |
00065    |   // the sizeof (Malloc_Header) to be   |
00066    |   // multiple of ACE_MALLOC_ALIGN.      |
00067    |   // If you are sure that               |
00068    |   //    sizeof (MALLOC_HEADER_PTR)      |
00069    |   //  + sizeof (size_t) is a multiple   |
00070    |   // of ACE_MALLOC_ALIGN, then you can  |
00071    |   // #define ACE_MALLOC_PADDING_SIZE 0  |
00072    |   // to complete remove this data member|
00073    |   // from Malloc_Header.  Otherwise,    |
00074    |   // ACE will try to figure out the     |
00075    |   // correct value of this macro.       |
00076    |   // However, the calculation does not  |
00077    |   // always do the right thing and in   |
00078    |   // some rare cases, you'll need to    |
00079    |   // tweak this value by defining the   |
00080    |   // macro (ACE_MALLOC_PADDING_SIZE)    |
00081    |   // explicitly.                        |
00082    +-----------------------------------------+
00083 
00084 * Name_Node
00085 
00086   ACE_Malloc allows searching thru it's allocated buffer using names.
00087   Name_Node is an internal data structure that ACE_Malloc used to
00088   maintain a linked list that manages this (name, buffer) mappings.
00089 
00090    +-----------------------------------------+
00091    |char *name_;                             |
00092    |   // Points to a dynamically allocated  |
00093    |   // char buffer that holds the name    |
00094    |   // of this node.  This buffer is      |
00095    |   // allocated from using this          |
00096    |   // ACE_MALLOC instance that owns this |
00097    |   // Name_Node (so it always points to  |
00098    |   // a buffer owned by its Malloc.      |
00099    +-----------------------------------------+
00100    |char *pointer_;                          |
00101    |   // Points to the content that <name_> |
00102    |   // referring to.  Like <name_>, the   |
00103    |   // context always resides within the  |
00104    |   // Malloc.                            |
00105    +-----------------------------------------+
00106    |NAME_NODE_PTR next_;                     |
00107    +-----------------------------------------+
00108    |NAME_NODE_PTR prev_;                     |
00109    |   // Name Node linked list pointers.    |
00110    +-----------------------------------------+
00111 
00112 
00113 * Control_Block
00114 
00115   Only the first ACE_Malloc instance that uses
00116   the shared memory will initialize the control block because all
00117   later instances are supposed to share the memory with the first
00118   instance.  The following diagram shows the initial value of a
00119   Control_Block.
00120 
00121    +-----------------------------------------+
00122    |NAME_NODE_PTR name_head_;                |<---- NULL
00123    |   // Entry point for double-linked list.|
00124    |   // Initialized to NULL pointer to     |
00125    |   // indicate an empty list.            |
00126    +-----------------------------------------+
00127    |MALLOC_HEADER_PTR freep_;                |
00128    |   // Pointer to last un-allocated       |
00129    |   // malloc_header linked list.         |---+
00130    +-----------------------------------------+   |
00131    |char lock_name_[MAXNAMELEN];             |   |
00132    |   // The global name of the lock.       |   |
00133    +-----------------------------------------+   |
00134    |Malloc_Stats malloc_stats_;              |   |
00135    |   // (Optional statistic information.   |   |
00136    |   //  Do not exist if                   |   |
00137    |   //  ACE_HAS_MALLOC_STATS is not       |   |
00138    |   //  defined.                          |   |
00139    +-----------------------------------------+   |
00140    |long align_[CONTROL_BLOCK_ALIGN_LONGS];  |   |
00141    |   //                                    |   |
00142    +-----------------------------------------+   |
00143    |Malloc_Header base_;                     |<--+
00144    |  // Dummy node used to anchor the       |
00145    |  // freelist.                           |<--+
00146    |                           +-------------+   |
00147    |                           |next_        |---+
00148    |                           +-------------+
00149    |                           |size_        |----> 0
00150    +-----------------------------------------+
00151 
00152   The first ACE_Malloc initializes the control block by allocating a
00153   memory block of size equal to or greater than sizeof (control block)
00154   (rounded to the closest <rounded_bytes>) and invokes the placement
00155   new's on to initialize the control block and its internal
00156   pointers/data structures.  If the extra memory (memory after the
00157   <base_> in the following diagram) is enough to create a
00158   Malloc_Header chain, one is created and added to the freelist list.
00159   That is, if the memory size returned by init_acquire() is greater
00160   than the sizeof Control_Block, the control block is initialized to
00161   the following diagram:
00162 
00163 
00164    +-------------------------------------
00165    |name_head_;                          |
00166    +-------------------------------------+
00167    |MALLOC_HEADER_PTR freep_;            |--+
00168    +-------------------------------------+  |
00169    |lock_name_[...];                     |  |
00170    +-------------------------------------+  |
00171    |malloc_stats_; (Optional)            |  |
00172    +-------------------------------------+  |
00173    |align_[...];                         |  |
00174    +-------------------------------------+  |
00175    |Malloc_Header base_;                 |<-+
00176    |                         +-----------+
00177    |                         |next_;     |--+
00178    |                         +-----------+  |
00179    |                         |size_ = 0; |  |
00180    +=====================================+  |
00181    |Malloc_Header base_;                 |<-+
00182    |                         +-----------+
00183    |                         |next_;     |
00184    |                         +-----------+
00185    |                         |size_ = 3; |
00186    +-------------------------------------+
00187    |Malloc_Header base_;                 |
00188    |                         +-----------+
00189    |   (Uninitialized)       |next_;     |
00190    |                         +-----------+
00191    |                         |size_;     |
00192    +-------------------------------------+
00193    |Malloc_Header base_;                 |
00194    |                         +-----------+
00195    |   (Uninitialized)       |next_;     |
00196    |                         +-----------+
00197    |                         |size_;     |
00198    +-------------------------------------+
00199 
00200 ***********************************************************/
00201 
00202 /// This keeps stats on the usage of the memory manager.
00203 struct ACE_Export ACE_Malloc_Stats
00204 {
00205   ACE_Malloc_Stats (void);
00206   void dump (void) const;
00207 
00208   /// Coarse-grained unit of allocation.
00209   ACE_INT nchunks_;
00210 
00211   /// Fine-grained unit of allocation.
00212   ACE_INT nblocks_;
00213 
00214   /// Number of blocks in use
00215   ACE_INT ninuse_;
00216 };
00217 #define ACE_MALLOC_STATS(X) X
00218 #else
00219 #define ACE_MALLOC_STATS(X)
00220 #endif /* ACE_HAS_MALLOC_STATS */
00221 
00222 #if !defined (ACE_MALLOC_PADDING)
00223 // ACE_MALLOC_PADDING allows you to insure that allocated regions are
00224 // at least <ACE_MALLOC_PADDING> bytes long.  It is especially useful
00225 // when you want areas to be at least a page long, or 32K long, or
00226 // something like that.  It doesn't guarantee alignment to an address
00227 // multiple, like 8-byte data alignment, etc.  The allocated area's
00228 // padding to your selected size is done with an added array of long[]
00229 // and your compiler will decide how to align things in memory.
00230 
00231 #define ACE_MALLOC_PADDING 1
00232 #endif /* ACE_MALLOC_PADDING */
00233 
00234 #if !defined (ACE_MALLOC_ALIGN)
00235 // Align the malloc header size to a multiple of a double.
00236 #define ACE_MALLOC_ALIGN (sizeof (double))
00237 #endif /* ACE_MALLOC_ALIGN */
00238 
00239 // ACE_MALLOC_HEADER_SIZE is the normalized malloc header size.
00240 #define ACE_MALLOC_HEADER_SIZE (ACE_MALLOC_PADDING % ACE_MALLOC_ALIGN == 0 \
00241                                 ? ACE_MALLOC_PADDING \
00242                                 : (((ACE_MALLOC_PADDING / ACE_MALLOC_ALIGN) + 1) \
00243                                    * ACE_MALLOC_ALIGN))
00244 
00245 /**
00246  * @class ACE_Control_Block
00247  *
00248  * @brief This information is stored in memory allocated by the <Memory_Pool>.
00249  *
00250  * This class defines the "old" control block class for use in
00251  * ACE_Malloc_T.  This control block implementation is
00252  * considerable more efficient than the "position independent"
00253  * one below (ACE_PI_Control_Block) but if you are going to use
00254  * it to construct a ACE_Malloc_T and access the memory from
00255  * several different processes, you must "map" the underlying
00256  * memory pool to the same address.
00257  */
00258 class ACE_Export ACE_Control_Block
00259 {
00260 public:
00261 
00262   /**
00263    * @class ACE_Malloc_Header
00264    *
00265    * @brief This is the control block header.  It's used by <ACE_Malloc>
00266    * to keep track of each chunk of data when it's in the free
00267    * list or in use.
00268    */
00269   class ACE_Export ACE_Malloc_Header
00270   {
00271   public:
00272     ACE_Malloc_Header (void);
00273 
00274     /// Points to next block if on free list.
00275     ACE_Malloc_Header *next_block_;
00276 
00277     /// Initialize a malloc header pointer.
00278     static void init_ptr (ACE_Malloc_Header **ptr,
00279                           ACE_Malloc_Header *init,
00280                           void *base_addr);
00281 
00282     /// Size of this header control block.
00283     size_t size_;
00284 
00285 #if defined (ACE_MALLOC_PADDING_SIZE) && (ACE_MALLOC_PADDING_SIZE == 0)
00286     // No padding required.
00287 #else
00288 # if !defined (ACE_MALLOC_PADDING_SIZE)
00289 #   define ACE_MALLOC_PADDING_SIZE ((int) (ACE_MALLOC_HEADER_SIZE - \
00290                                     (sizeof (ACE_Malloc_Header*) + sizeof (size_t)))\
00291                                     / (int) sizeof (long))
00292 # endif /* !ACE_MALLOC_PADDING_SIZE */
00293     long padding_[ACE_MALLOC_PADDING_SIZE < 1 ? 1 : ACE_MALLOC_PADDING_SIZE];
00294 #endif /* ACE_MALLOC_PADDING_SIZE && ACE_MALLOC_PADDING_SIZE == 0 */
00295 
00296     /// Dump the state of the object.
00297     void dump (void) const;
00298   };
00299 
00300   /**
00301    * @class ACE_Name_Node
00302    *
00303    * @brief This class supports "named memory regions" within <ACE_Malloc>.
00304    *
00305    * Internally, the named memory regions are stored as a
00306    * doubly-linked list within the <Memory_Pool>.  This makes
00307    * it easy to iterate over the items in the list in both FIFO
00308    * and LIFO order.
00309    */
00310   class ACE_Export ACE_Name_Node
00311   {
00312   public:
00313     // = Initialization methods.
00314     /// Constructor.
00315     ACE_Name_Node (const char *name,
00316                    char *name_ptr,
00317                    char *pointer,
00318                    ACE_Name_Node *head);
00319 
00320     /// Copy constructor.
00321     ACE_Name_Node (const ACE_Name_Node &);
00322 
00323     /// Constructor.
00324     ACE_Name_Node (void);
00325 
00326     /// Constructor.
00327     ~ACE_Name_Node (void);
00328 
00329     /// Initialize a name node pointer.
00330     static void init_ptr (ACE_Name_Node **ptr,
00331                           ACE_Name_Node *init,
00332                           void *base_addr);
00333 
00334     /// Return a pointer to the name of this node.
00335     const char *name (void) const;
00336 
00337     /// Assign a name;
00338     void name (const char *);
00339 
00340     /// Name of the Node.
00341     char *name_;
00342 
00343     /// Pointer to the contents.
00344     char *pointer_;
00345 
00346     /// Pointer to the next node in the doubly-linked list.
00347     ACE_Name_Node *next_;
00348 
00349     /// Pointer to the previous node in the doubly-linked list.
00350     ACE_Name_Node *prev_;
00351 
00352     /// Dump the state of the object.
00353     void dump (void) const;
00354   };
00355 
00356   /// Print out a bunch of size info for debugging.
00357   static void print_alignment_info (void);
00358 
00359   /// Reference counter.
00360   int ref_counter_;
00361 
00362   /// Head of the linked list of Name Nodes.
00363   ACE_Name_Node *name_head_;
00364 
00365   /// Current head of the freelist.
00366   ACE_Malloc_Header *freep_;
00367 
00368   /// Name of lock thats ensures mutual exclusion.
00369   char lock_name_[MAXNAMELEN];
00370 
00371 #if defined (ACE_HAS_MALLOC_STATS)
00372   /// Keep statistics about ACE_Malloc state and performance.
00373   ACE_Malloc_Stats malloc_stats_;
00374 #define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \
00375                                       + sizeof (ACE_Malloc_Header*) \
00376                                       + sizeof (int) \
00377                                       + MAXNAMELEN  \
00378                                       + sizeof (ACE_Malloc_Stats)))
00379 #else
00380 #define ACE_CONTROL_BLOCK_SIZE ((int)(sizeof (ACE_Name_Node*) \
00381                                       + sizeof (ACE_Malloc_Header*) \
00382                                       + sizeof (int) \
00383                                       + MAXNAMELEN))
00384 #endif /* ACE_HAS_MALLOC_STATS */
00385 
00386 // Notice the casting to int for <sizeof> otherwise unsigned int
00387 // arithmetic is used and some awful things may happen.
00388 #if defined (ACE_CONTROL_BLOCK_ALIGN_LONGS) && (ACE_CONTROL_BLOCK_ALIGN_LONGS == 0)
00389   // No padding required in control block.
00390 #else
00391 # if !defined (ACE_CONTROL_BLOCK_ALIGN_LONGS)
00392 #   define ACE_CONTROL_BLOCK_ALIGN_LONGS \
00393             ((ACE_CONTROL_BLOCK_SIZE % ACE_MALLOC_ALIGN != 0 \
00394               ? ACE_MALLOC_ALIGN - (ACE_CONTROL_BLOCK_SIZE % ACE_MALLOC_ALIGN) \
00395               : ACE_MALLOC_ALIGN) / int (sizeof (long)))
00396 # endif /* !ACE_CONTROL_BLOCK_ALIGN_LONGS */
00397   /// Force alignment.
00398   long align_[ACE_CONTROL_BLOCK_ALIGN_LONGS < 1 ? 1 : ACE_CONTROL_BLOCK_ALIGN_LONGS];
00399 #endif /* ACE_CONTROL_BLOCK_ALIGN_LONGS && ACE_CONTROL_BLOCK_ALIGN_LONGS == 0 */
00400 
00401   /// Dummy node used to anchor the freelist.  This needs to come last...
00402   ACE_Malloc_Header base_;
00403 
00404   /// Dump the state of the object.
00405   void dump (void) const;
00406 };
00407 
00408 #if defined (__ACE_INLINE__)
00409 #include "ace/Malloc.i"
00410 #endif /* __ACE_INLINE__ */
00411 
00412 // Include the ACE_Malloc templates and ACE_Memory_Pool classes at this point.
00413 #include "ace/Malloc_T.h"
00414 #include "ace/Memory_Pool.h"
00415 
00416 #include "ace/post.h"
00417 
00418 #endif /* ACE_MALLOC_H */

Generated on Mon Jun 16 11:20:04 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002