File: allocators.h

package info (click to toggle)
bagel 1.2.2-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 134,940 kB
  • sloc: cpp: 1,236,571; javascript: 15,383; python: 1,461; ansic: 674; makefile: 253; sh: 109
file content (128 lines) | stat: -rw-r--r-- 3,280 bytes parent folder | download | duplicates (7)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * allocators.h
 *
 *  Created on: Jan 4, 2014
 *      Author: evaleev
 */

#ifndef BTAS_VARRAY_ALLOCATORS_H_
#define BTAS_VARRAY_ALLOCATORS_H_

#include <cstddef>
#include <algorithm>
#include <memory>
#include <vector>
#include <stdexcept>
#include <iostream>
#include <iomanip>

namespace btas {

  struct stack_arena {
      size_t size;            //!< in bytes
      char* const buffer;     //!< buffer begin
      char* current;          //!< ptr to the free space in buffer

      template<typename T>
      stack_arena(T* b, size_t s) :
        size(s),
        buffer(reinterpret_cast<char*>(b)),
        current(reinterpret_cast<char*>(b))
        {
      }

      void increment(const size_t n) { current += n; }
      void decrement(const size_t n) { current -= n; }
  };


  /// This is a very simple allocator implementation that uses an externally managed memory stack.
  /// It's mostly for demonstration purposes.

  /// stack_allocator is a first-in-last-out allocator,
  /// i.e. deallocation of the memory must happen in the opposite order of allocation.
  template<typename T>
  class stack_allocator {
    private:
      std::shared_ptr<stack_arena> arena_;

      size_t size() const {
        return arena_->size / sizeof(T);
      }
      T* buffer() const {
        return reinterpret_cast<T*>(arena_->buffer);
      }
      T* current() const {
        return reinterpret_cast<T*>(arena_->current);
      }

      void increment(const size_t n) {
        arena_->increment(n * sizeof(T));
      }
      void decrement(const size_t n) {
        arena_->decrement(n * sizeof(T));
      }

    public:
      // do not allocate here
      stack_allocator(std::shared_ptr<stack_arena> a) :
          arena_(a) {
      }

      stack_allocator(const stack_allocator<T>& o) :
          arena_(o.arena_) {
      }
      stack_allocator& operator=(const stack_allocator<T>& o) {
        arena_ = o.arena_;
        return *this;
      }
      struct rebind {
          typedef stack_allocator<T> other;
      };

      typedef T* pointer;
      typedef T& reference;
      typedef const T* const_pointer;
      typedef const T& const_reference;
      typedef T value_type;
      typedef size_t size_type;
      typedef ptrdiff_t difference_type;

      pointer allocate(size_type n, const void* = 0) {
        //std::cout << "Allocating " << std::setw(6) << sizeof(T)*n << " bytes. "
        //          << "Available memory: "
        //          << std::setw(6) << sizeof(T) * (size() - std::distance(buffer(), current())) << " bytes."<< std::endl;
        pointer out = current();
        increment(n);
        if (std::distance(buffer(), current()) > size())
          throw std::runtime_error("preallocated memory exhausted");
        return out;
      }

      pointer address(reference x) const {
        return &x;
      }
      const_pointer address(const_reference x) const {
        return &x;
      }

      void deallocate(pointer p, size_type n) {
        assert(p == current() - n);
        decrement(n);
      }

      void construct(pointer p, const T& val) {
        *p = val;
      }
      void destroy(pointer p) {
      }

      size_type max_size() const {
        return size();
      }
  };

}


#endif /* BTAS_VARRAY_ALLOCATORS_H_ */