medfall

A super great game engine
Log | Files | Refs

memory.hpp (6167B)


      1 /*  Relacy Race Detector
      2  *  Copyright (c) 2008-2013, Dmitry S. Vyukov
      3  *  All rights reserved.
      4  *  This software is provided AS-IS with no warranty, either express or implied.
      5  *  This software is distributed under a license and may not be copied,
      6  *  modified or distributed except as expressly authorized under the
      7  *  terms of the license contained in the file LICENSE in this distribution.
      8  */
      9 
     10 #ifndef RL_MEMORY_HPP
     11 #define RL_MEMORY_HPP
     12 #ifdef _MSC_VER
     13 #   pragma once
     14 #endif
     15 
     16 #include "base.hpp"
     17 
     18 
     19 namespace rl
     20 {
     21 
     22 
     23 class memory_mgr : nocopy<>
     24 {
     25 public:
     26     memory_mgr()
     27     {
     28         memset(deferred_free_, 0, sizeof(deferred_free_));
     29         memset(deferred_free_size_, 0, sizeof(deferred_free_size_));
     30         deferred_index_ = 0;
     31     }
     32 
     33     ~memory_mgr()
     34     {
     35         /*
     36         while (allocs_.size())
     37         {
     38             size_t* p = (size_t*)(allocs_.begin()->first);
     39             free(p - 1, false);
     40             allocs_.erase(allocs_.begin());
     41         }
     42         */
     43     }
     44 
     45 #ifndef RL_GC
     46     void* alloc(size_t size)
     47 #else
     48     void* alloc(size_t size, void (*dtor)(void*))
     49 #endif
     50     {
     51         void* pp = 0;
     52         for (size_t i = 0; i != alloc_cache_.size(); ++i)
     53         {
     54             if (alloc_cache_[i].first == size)
     55             {
     56                 if (alloc_cache_[i].second.size())
     57                 {
     58                     pp = alloc_cache_[i].second.top();
     59                     alloc_cache_[i].second.pop();
     60                 }
     61                 break;
     62             }
     63         }
     64         if (0 == pp)
     65             pp = (::malloc)(size + alignment);
     66 
     67         if (pp)
     68         {
     69             RL_VERIFY(alignment >= sizeof(void*));
     70             *(size_t*)pp = size;
     71             void* p = (char*)pp + alignment;
     72 #ifndef RL_GC
     73             allocs_.insert(std::make_pair(p, size));
     74 #else
     75             alloc_desc_t desc = {p, size, dtor};
     76             gc_allocs_.push_back(desc);
     77 #endif
     78             return p;
     79         }
     80         else
     81         {
     82             throw std::bad_alloc();
     83         }
     84     }
     85 
     86     bool free(void* pp, bool defer)
     87     {
     88         if (0 == pp)
     89             return true;
     90 
     91 #ifndef RL_GC
     92         map<void*, size_t>::type::iterator iter = allocs_.find(pp);
     93         if (allocs_.end() == iter)
     94             return false;
     95 
     96         allocs_.erase(iter);
     97 
     98         void* p = (char*)pp - alignment;
     99         size_t size = *(size_t*)p;
    100 
    101         if (defer)
    102         {
    103             deferred_free_[deferred_index_ % deferred_count] = p;
    104             deferred_free_size_[deferred_index_ % deferred_count] = size;
    105             deferred_index_ += 1;
    106             p = deferred_free_[deferred_index_ % deferred_count];
    107             size = deferred_free_size_[deferred_index_ % deferred_count];
    108             if (p)
    109                 rl_free_impl(p, size);
    110         }
    111         else
    112         {
    113             rl_free_impl(p, size);
    114         }
    115         return true;
    116 #else
    117         (void)defer;
    118         for (size_t i = 0; i != gc_allocs_.size(); ++i)
    119         {
    120             alloc_desc_t const& desc = gc_allocs_[i];
    121             if (desc.addr == pp)
    122             {
    123                 void* p = (char*)desc.addr - alignment;
    124                 rl_free_impl(p, desc.size);
    125                 gc_allocs_.erase(gc_allocs_.begin() + i);
    126                 return true;
    127             }
    128         }
    129         return false;
    130 #endif
    131     }
    132 
    133     bool iteration_end()
    134     {
    135 #ifndef RL_GC
    136         return allocs_.empty();
    137 #else
    138         for (size_t i = 0; i != gc_allocs_.size(); ++i)
    139         {
    140             alloc_desc_t const& desc = gc_allocs_[i];
    141             if (desc.dtor)
    142                 desc.dtor(desc.addr);
    143             void* p = (char*)desc.addr - alignment;
    144             rl_free_impl(p, desc.size);
    145         }
    146         gc_allocs_.clear();
    147         return true;
    148 #endif
    149     }
    150 
    151 #ifndef RL_GC
    152     void output_allocs(std::ostream& stream)
    153     {
    154         stream << "memory allocations:" << std::endl;
    155         map<void*, size_t>::type::iterator iter = allocs_.begin();
    156         map<void*, size_t>::type::iterator end = allocs_.end();
    157         for (; iter != end; ++iter)
    158         {
    159             stream << iter->first << " [" << (unsigned)iter->second << "]" << std::endl;
    160         }
    161         stream << std::endl;
    162     }
    163 #endif
    164 
    165 private:
    166     typedef stack<void*>::type              freelist_t;
    167     typedef std::pair<size_t, freelist_t>   alloc_entry_t;
    168     typedef vector<alloc_entry_t>::type     alloc_t;
    169 
    170     static size_t const deferred_count      = 64;
    171 
    172     alloc_t alloc_cache_;
    173     size_t deferred_index_;
    174     void* deferred_free_ [deferred_count];
    175     size_t deferred_free_size_ [deferred_count];
    176 
    177 #ifndef RL_GC
    178     map<void*, size_t>::type allocs_;
    179 #else
    180     struct alloc_desc_t
    181     {
    182         void*       addr;
    183         size_t      size;
    184         void        (*dtor)(void*);
    185     };
    186     vector<alloc_desc_t>::type gc_allocs_;
    187 #endif
    188 
    189     void rl_free_impl(void* p, size_t size)
    190     {
    191         bool found = false;
    192         for (size_t i = 0; i != alloc_cache_.size(); ++i)
    193         {
    194             if (alloc_cache_[i].first == size)
    195             {
    196                 found = true;
    197                 alloc_cache_[i].second.push(p);
    198                 break;
    199             }
    200         }
    201         if (!found)
    202         {
    203             alloc_cache_.push_back(std::make_pair(size, freelist_t()));
    204             alloc_cache_.back().second.push(p);
    205         }
    206     }
    207 };
    208 
    209 
    210 
    211 
    212 struct memory_alloc_event
    213 {
    214     void*                       addr_;
    215     size_t                      size_;
    216     bool                        is_array_;
    217 
    218     void output(std::ostream& s) const
    219     {
    220         s << "memory allocation: addr=" << std::hex << (void*)((char*)addr_ + (is_array_ ? alignment : 0)) << std::dec
    221             << ", size=" << (unsigned)size_;
    222     }
    223 };
    224 
    225 
    226 struct memory_free_event
    227 {
    228     void*                       addr_;
    229     bool                        is_array_;
    230 
    231     void output(std::ostream& s) const
    232     {
    233         s << "memory deallocation: addr=" << std::hex << (void*)((char*)addr_ + (is_array_ ? alignment : 0)) << std::dec;
    234     }
    235 };
    236 
    237 
    238 
    239 }
    240 
    241 #endif