memory_manager.h

00001 
00002 /***************************************************************************
00003  *  memory_manager.h - BlackBoard memory manager
00004  *
00005  *  Created: Sat Sep 23 16:00:56 2006 (INSITE 2006, Joburg, South Africa)
00006  *  Copyright  2006-2009  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #ifndef __BLACKBOARD_MEMORY_MANAGER_H_
00025 #define __BLACKBOARD_MEMORY_MANAGER_H_
00026 
00027 #include <sys/types.h>
00028 
00029 namespace fawkes {
00030 
00031 class BlackBoardSharedMemoryHeader;
00032 class SharedMemory;
00033 class Mutex;
00034 class SemaphoreSet;
00035 
00036 // define our own list type std::list is way too fat
00037 /** Chunk lists as stored in BlackBoard shared memory segment.
00038  * The data segment of a chunk follows directly after the header. So if c is a chunk_list_t
00039  * pointer to a chunk then the data segment of that chunk can be accessed via
00040  * (char *)c + sizeof(chunk_list_t).
00041  */
00042 struct chunk_list_t {
00043   chunk_list_t  *next;          /**< offset to next element in list */
00044   void          *ptr;           /**< pointer to data memory */
00045   unsigned int   size;          /**< total size of chunk, including overhanging bytes,
00046                                  * excluding header */
00047   unsigned int   overhang;      /**< number of overhanging bytes in this chunk */
00048 };
00049 
00050 // May be added later if we want/need per chunk semaphores
00051 //  int            semset_key;  /* key of semaphore for this chunk */
00052 //  unsigned int   reserved   :16;/* reserved bytes */
00053 //  unsigned int   semset_sem : 8;/* semaphore number in semaphore set */
00054 
00055 
00056 class BlackBoardMemoryManager
00057 {
00058   friend class BlackBoardInterfaceManager;
00059  public:
00060   BlackBoardMemoryManager(size_t memsize);
00061   BlackBoardMemoryManager(size_t memsize, unsigned int version,
00062                           bool use_shmem,
00063                           const char *shmem_token = "FawkesBlackBoard");
00064   ~BlackBoardMemoryManager();
00065 
00066   void * alloc(unsigned int num_bytes);
00067   void   free(void *chunk_ptr);
00068 
00069   void   check();
00070 
00071   bool   is_master() const;
00072 
00073   unsigned int max_free_size() const;
00074   unsigned int max_allocated_size() const;
00075 
00076   unsigned int free_size() const;
00077   unsigned int allocated_size() const;
00078   unsigned int overhang_size() const;
00079 
00080   unsigned int num_free_chunks() const;
00081   unsigned int num_allocated_chunks() const;
00082 
00083   unsigned int memory_size() const;
00084   unsigned int version() const;
00085 
00086   void   print_free_chunks_info() const;
00087   void   print_allocated_chunks_info() const;
00088   void   print_performance_info() const;
00089 
00090   void   lock();
00091   bool   try_lock();
00092   void   unlock();
00093 
00094   /*
00095   void   lock(void *ptr);
00096   bool   try_lock(void *ptr);
00097   void   unlock(void *ptr);
00098   */
00099 
00100   class ChunkIterator
00101   {
00102     friend class BlackBoardMemoryManager;
00103    private:
00104     ChunkIterator(SharedMemory *shmem, chunk_list_t *cur);
00105     ChunkIterator(chunk_list_t *cur);
00106    public:
00107     ChunkIterator();
00108     ChunkIterator(const ChunkIterator &it);
00109     ChunkIterator & operator++ ();        // prefix
00110     ChunkIterator   operator++ (int inc); // postfix
00111     ChunkIterator & operator+  (unsigned int i);
00112     ChunkIterator & operator+= (unsigned int i);
00113     bool            operator== (const ChunkIterator & c) const;
00114     bool            operator!= (const ChunkIterator & c) const;
00115     void *          operator*  () const;
00116     ChunkIterator & operator=  (const ChunkIterator & c);
00117 
00118     unsigned int    size() const;
00119     unsigned int    overhang() const;
00120 
00121    private:
00122     SharedMemory *__shmem;
00123     chunk_list_t *__cur;
00124   };
00125 
00126   ChunkIterator begin();
00127   ChunkIterator end();
00128 
00129  private:
00130   chunk_list_t * list_add(chunk_list_t *list, chunk_list_t *addel);
00131   chunk_list_t * list_remove(chunk_list_t *list, chunk_list_t *rmel);
00132   chunk_list_t * list_find_ptr(chunk_list_t *list, void *ptr);
00133   unsigned int   list_length(const chunk_list_t *list) const;
00134   chunk_list_t * list_get_biggest(const chunk_list_t *list) const;
00135   chunk_list_t * list_next(const chunk_list_t *list) const;
00136 
00137   void cleanup_free_chunks();
00138 
00139   void list_print_info(const chunk_list_t *list) const;
00140 
00141   void * alloc_nolock(unsigned int num_bytes);
00142 
00143  private:
00144   bool __master;
00145 
00146   size_t __memsize;
00147 
00148   // Mutex to be used for all list operations (alloc, free)
00149   Mutex *__mutex;
00150 
00151   // used for shmem
00152   BlackBoardSharedMemoryHeader *__shmem_header;
00153   SharedMemory *__shmem;
00154 
00155   // Used for heap memory
00156   void  *__memory;
00157   chunk_list_t *__free_list_head;       /**< offset of the free chunks list head */
00158   chunk_list_t *__alloc_list_head;      /**< offset of the allocated chunks list head */
00159 
00160 };
00161 
00162 } // end namespace fawkes
00163 
00164 #endif