-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathstore.cpp
More file actions
122 lines (109 loc) · 2.89 KB
/
store.cpp
File metadata and controls
122 lines (109 loc) · 2.89 KB
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
/*
* mini-cp is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3
* as published by the Free Software Foundation.
*
* mini-cp is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with mini-cp. If not, see http://www.gnu.org/licenses/lgpl-3.0.en.html
*
* Copyright (c) 2018. by Laurent Michel, Pierre Schaus, Pascal Van Hentenryck
*/
#include "store.hpp"
#include <algorithm>
#include <assert.h>
Storage::Segment::Segment(std::size_t tsz)
{
_sz = tsz;
_base = new char[_sz];
}
Storage::Segment::~Segment()
{
delete []_base;
}
Storage::Storage(Trailer::Ptr ctx,std::size_t defSize)
: _ctx(ctx),
_store(0),
_segSize(defSize),
_top(ctx,0),
_seg(ctx,0)
{
_store.push_back(std::make_shared<Storage::Segment>(_segSize));
}
std::size_t Storage::capacity() const
{
return _segSize;
}
std::size_t Storage::usage() const
{
return (_store.size() - 1) * _segSize + _top;
}
Storage::~Storage()
{
_store.clear();
}
void* Storage::allocate(std::size_t sz)
{
if (sz == 0) return nullptr;
if (sz & 0xF) // unaligned on 8 bytes boundary
sz = (sz | 0xF) + 1; // increase to align
assert((sz & 0xF) == 0 && sz != 0); // check alignment
auto s = _store[_seg];
if (_top + sz >= s->_sz) {
while (_store.size() != _seg + 1)
_store.pop_back(); // discard old segments
_store.push_back(std::make_shared<Storage::Segment>(std::max(_segSize,sz)));
_seg = _seg + 1;
_top = 0;
s = _store[_seg];
}
void* ptr = s->_base + _top;
_top = _top + sz;
return ptr;
}
// ========================================================================
Pool::Pool(std::size_t defSize)
: _store(0),
_segSize(defSize),
_top(0),
_seg(0),
_nbSeg(1),
_mxs(32)
{
_store = new Segment*[_mxs];
_store[0] = new Segment(_segSize);
}
Pool::~Pool()
{
for(auto i = 0u;i < _nbSeg;++i)
delete[] _store[i];
delete[] _store;
}
void* Pool::allocate(std::size_t sz)
{
if (sz & 0xF) // unaligned on 8 bytes boundary
sz = (sz | 0xF) + 1; // increase to align
assert((sz & 0xF) == 0 && sz != 0); // check alignment
auto s = _store[_seg];
while(_top + sz >= s->_sz) {
++_seg;
if (_seg >= _nbSeg) {
if (_nbSeg == _mxs) {
Segment** tab = new Segment*[_mxs << 1];
for(auto i = 0u;i < _mxs;++i) tab[i] = _store[i];
delete []_store;
_store = tab;
_mxs <<= 1;
}
_store[_nbSeg++] = new Segment(std::max(_segSize,sz));
}
_top = 0;
s = _store[_seg];
}
void* ptr = s->_base + _top;
_top = _top + sz;
return ptr;
}