Eneboo - Documentación para desarrolladores
src/hoard/src/alignedmmap.h
Ir a la documentación de este archivo.
00001 // -*- C++ -*-
00002 
00009 #ifndef _ALIGNEDMMAP_H_
00010 #define _ALIGNEDMMAP_H_
00011 
00012 #include "sassert.h"
00013 #include "myhashmap.h"
00014 #include "freelistheap.h"
00015 #include "mmapwrapper.h"
00016 #include "bumpalloc.h"
00017 #include "exactlyone.h"
00018 #include "mmapalloc.h"
00019 
00020 using namespace std;
00021 using namespace HL;
00022 
00023 namespace Hoard {
00024 
00032 template <size_t Alignment_>
00033 class AlignedMmapInstance {
00034 public:
00035 
00036   enum { Alignment = Alignment_ };
00037 
00038   inline void * malloc (size_t sz) {
00039 
00040     // Round up sz to the nearest page.
00041     sz = (sz + HL::MmapWrapper::Size - 1) & ~(HL::MmapWrapper::Size - 1);
00042 
00043     // If the memory is already suitably aligned, just track size requests.
00044     if ((size_t) HL::MmapWrapper::Alignment % (size_t) Alignment == 0) {
00045       void * ptr = HL::MmapWrapper::map (sz);
00046       MyMap.set (ptr, sz);
00047       return ptr;
00048     }
00049 
00050     // Try a map call and hope that it's suitably aligned. If we get lucky,
00051     // we're done.
00052 
00053     char * ptr = reinterpret_cast<char *>(HL::MmapWrapper::map (sz));
00054 
00055     if (ptr == align(ptr)) {
00056       // We're done.
00057       MyMap.set (ptr, sz);
00058       return ptr;
00059     } else {
00060       // Try again.
00061       HL::MmapWrapper::unmap ((void *) ptr, sz);
00062     }
00063 
00064     // We have to align it ourselves. We get memory from
00065     // mmap, align a pointer in the space, and free the space before
00066     // and after the aligned segment.
00067 
00068     ptr = reinterpret_cast<char *>(HL::MmapWrapper::map (sz + Alignment_));
00069 
00070     if (ptr == NULL) {
00071       return NULL;
00072     }
00073 
00074     char * newptr = align (ptr);
00075 
00076     // Unmap the part before (prolog) and after.
00077 
00078     size_t prolog = (size_t) newptr - (size_t) ptr;
00079 
00080     if (prolog > 0) {
00081       // Get rid of the prolog.
00082       HL::MmapWrapper::unmap (ptr, prolog);
00083     }
00084 
00085     size_t epilog = Alignment_ - prolog;
00086     HL::MmapWrapper::unmap ((char *) newptr + sz, epilog);
00087 
00088     // Now record the size associated with this pointer.
00089 
00090     MyMap.set (newptr, sz);
00091     return newptr;
00092   }
00093 
00094   inline void free (void * ptr) {
00095 
00096     // Find the object. If we don't find it, we didn't allocate it.
00097     // For now, just ignore such an invalid free...
00098 
00099     size_t requestedSize = MyMap.get (ptr);
00100 
00101     if (requestedSize == 0) {
00102       return;
00103     }
00104 
00105     HL::MmapWrapper::unmap (ptr, requestedSize);
00106 
00107     // Finally, undo the mapping.
00108     MyMap.erase (ptr);
00109   }
00110   
00111   inline size_t getSize (void * ptr) {
00112     return MyMap.get (ptr);
00113   }
00114 
00115 
00116 private:
00117 
00119   inline static char * align (char * buf) {
00120     return (char *)(((size_t) buf + (Alignment_-1)) & ~(Alignment_-1));
00121   }
00122 
00123   // Manage information in a map that uses a custom heap for
00124   // allocation.
00125 
00127   typedef void * keyType;
00128 
00130   typedef size_t valType;
00131 
00132   // The heap from which memory comes for the Map's purposes.
00133   // Objects come from chunks via mmap, and we manage these with a free list.
00134   class SourceHeap : public HL::FreelistHeap<BumpAlloc<65536, MmapAlloc> > { };
00135 
00137   typedef MyHashMap<keyType, valType, SourceHeap> mapType;
00138 
00140   mapType MyMap;
00141 
00142 };
00143 
00144 
00151 template <size_t Alignment_,
00152           class LockType>
00153 class AlignedMmap :
00154     public ExactlyOne<LockedHeap<LockType, AlignedMmapInstance<Alignment_> > > 
00155 {
00156 public:
00157 
00158   enum { Alignment = Alignment_ };
00159 
00160   inline void * malloc (size_t sz) {
00161     return (*this)().malloc (sz);
00162   }
00163   inline void free (void * ptr) {
00164     return (*this)().free (ptr);
00165   }
00166   inline size_t getSize (void * ptr) const {
00167     return (*this)().getSize (ptr);
00168   }
00169  
00170 };
00171 
00172 }
00173 
00174 #endif
 Todo Clases Namespaces Archivos Funciones Variables 'typedefs' Enumeraciones Valores de enumeraciones Propiedades Amigas 'defines'