rrudb 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +1 -0
- data/LICENSE.txt +22 -0
- data/README.md +26 -0
- data/examples/example.rb +39 -0
- data/ext/rudb/NuDB/include/nudb/CMakeLists.txt +104 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/basic_seconds_clock.hpp +200 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/chrono_util.hpp +58 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/fail_file.hpp +343 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/temp_dir.hpp +73 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/test_store.hpp +451 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/test/xor_shift_engine.hpp +105 -0
- data/ext/rudb/NuDB/include/nudb/_experimental/util.hpp +288 -0
- data/ext/rudb/NuDB/include/nudb/basic_store.hpp +461 -0
- data/ext/rudb/NuDB/include/nudb/concepts.hpp +205 -0
- data/ext/rudb/NuDB/include/nudb/context.hpp +144 -0
- data/ext/rudb/NuDB/include/nudb/create.hpp +117 -0
- data/ext/rudb/NuDB/include/nudb/detail/arena.hpp +296 -0
- data/ext/rudb/NuDB/include/nudb/detail/bucket.hpp +473 -0
- data/ext/rudb/NuDB/include/nudb/detail/buffer.hpp +86 -0
- data/ext/rudb/NuDB/include/nudb/detail/bulkio.hpp +196 -0
- data/ext/rudb/NuDB/include/nudb/detail/cache.hpp +236 -0
- data/ext/rudb/NuDB/include/nudb/detail/endian.hpp +93 -0
- data/ext/rudb/NuDB/include/nudb/detail/field.hpp +265 -0
- data/ext/rudb/NuDB/include/nudb/detail/format.hpp +630 -0
- data/ext/rudb/NuDB/include/nudb/detail/gentex.hpp +259 -0
- data/ext/rudb/NuDB/include/nudb/detail/mutex.hpp +26 -0
- data/ext/rudb/NuDB/include/nudb/detail/pool.hpp +243 -0
- data/ext/rudb/NuDB/include/nudb/detail/store_base.hpp +45 -0
- data/ext/rudb/NuDB/include/nudb/detail/stream.hpp +149 -0
- data/ext/rudb/NuDB/include/nudb/detail/xxhash.hpp +328 -0
- data/ext/rudb/NuDB/include/nudb/error.hpp +257 -0
- data/ext/rudb/NuDB/include/nudb/file.hpp +55 -0
- data/ext/rudb/NuDB/include/nudb/impl/basic_store.ipp +785 -0
- data/ext/rudb/NuDB/include/nudb/impl/context.ipp +241 -0
- data/ext/rudb/NuDB/include/nudb/impl/create.ipp +163 -0
- data/ext/rudb/NuDB/include/nudb/impl/error.ipp +175 -0
- data/ext/rudb/NuDB/include/nudb/impl/posix_file.ipp +248 -0
- data/ext/rudb/NuDB/include/nudb/impl/recover.ipp +209 -0
- data/ext/rudb/NuDB/include/nudb/impl/rekey.ipp +248 -0
- data/ext/rudb/NuDB/include/nudb/impl/verify.ipp +634 -0
- data/ext/rudb/NuDB/include/nudb/impl/visit.ipp +96 -0
- data/ext/rudb/NuDB/include/nudb/impl/win32_file.ipp +264 -0
- data/ext/rudb/NuDB/include/nudb/native_file.hpp +76 -0
- data/ext/rudb/NuDB/include/nudb/nudb.hpp +27 -0
- data/ext/rudb/NuDB/include/nudb/posix_file.hpp +228 -0
- data/ext/rudb/NuDB/include/nudb/progress.hpp +32 -0
- data/ext/rudb/NuDB/include/nudb/recover.hpp +73 -0
- data/ext/rudb/NuDB/include/nudb/rekey.hpp +110 -0
- data/ext/rudb/NuDB/include/nudb/store.hpp +27 -0
- data/ext/rudb/NuDB/include/nudb/type_traits.hpp +63 -0
- data/ext/rudb/NuDB/include/nudb/verify.hpp +200 -0
- data/ext/rudb/NuDB/include/nudb/version.hpp +21 -0
- data/ext/rudb/NuDB/include/nudb/visit.hpp +63 -0
- data/ext/rudb/NuDB/include/nudb/win32_file.hpp +246 -0
- data/ext/rudb/NuDB/include/nudb/xxhasher.hpp +45 -0
- data/ext/rudb/extconf.rb +12 -0
- data/ext/rudb/rudb.cpp +234 -0
- data/lib/rudb/version.rb +3 -0
- data/lib/rudb.rb +1 -0
- metadata +104 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
//
|
2
|
+
// Copyright (c) 2019 Miguel Portilla (miguelportilla64 at gmail dot com)
|
3
|
+
//
|
4
|
+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
5
|
+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
6
|
+
//
|
7
|
+
|
8
|
+
#ifndef NUDB_CONTEXT_HPP
|
9
|
+
#define NUDB_CONTEXT_HPP
|
10
|
+
|
11
|
+
#include <condition_variable>
|
12
|
+
#include <memory>
|
13
|
+
#include <mutex>
|
14
|
+
#include <thread>
|
15
|
+
|
16
|
+
#define NUDB_DECL inline
|
17
|
+
|
18
|
+
namespace nudb {
|
19
|
+
|
20
|
+
namespace test {
|
21
|
+
class context_test;
|
22
|
+
} // test
|
23
|
+
|
24
|
+
namespace detail {
|
25
|
+
class store_base;
|
26
|
+
} // detail
|
27
|
+
|
28
|
+
class context
|
29
|
+
{
|
30
|
+
public:
|
31
|
+
/// Constructor
|
32
|
+
context() = default;
|
33
|
+
|
34
|
+
/** Destructor.
|
35
|
+
|
36
|
+
Halts execution of all threads. Blocks until all threads
|
37
|
+
have completed any ongoing operation and have stopped.
|
38
|
+
*/
|
39
|
+
NUDB_DECL
|
40
|
+
~context() noexcept (false);
|
41
|
+
|
42
|
+
/// Copy constructor (disallowed)
|
43
|
+
context(context const&) = delete;
|
44
|
+
|
45
|
+
/// Move constructor (disallowed)
|
46
|
+
context(context&&) = delete;
|
47
|
+
|
48
|
+
// Copy assignment (disallowed)
|
49
|
+
context& operator=(context const&) = delete;
|
50
|
+
|
51
|
+
// Move assignment (disallowed)
|
52
|
+
context& operator=(context&&) = delete;
|
53
|
+
|
54
|
+
/** Start thread execution.
|
55
|
+
|
56
|
+
Starts the context thread execution.
|
57
|
+
*/
|
58
|
+
NUDB_DECL
|
59
|
+
void
|
60
|
+
start();
|
61
|
+
|
62
|
+
/** Stop thread execution.
|
63
|
+
|
64
|
+
Halts execution of all threads. Blocks until all threads
|
65
|
+
have completed any ongoing operation and have stopped.
|
66
|
+
*/
|
67
|
+
NUDB_DECL
|
68
|
+
void
|
69
|
+
stop_all();
|
70
|
+
|
71
|
+
/** Thread function.
|
72
|
+
|
73
|
+
Function to service the databases.
|
74
|
+
Thread objects must call this function.
|
75
|
+
*/
|
76
|
+
NUDB_DECL
|
77
|
+
void
|
78
|
+
run();
|
79
|
+
|
80
|
+
private:
|
81
|
+
using clock_type = std::chrono::steady_clock;
|
82
|
+
using store_base = detail::store_base;
|
83
|
+
|
84
|
+
template<class, class> friend class basic_store;
|
85
|
+
#if ! NUDB_DOXYGEN
|
86
|
+
friend class test::context_test;
|
87
|
+
#endif
|
88
|
+
|
89
|
+
NUDB_DECL
|
90
|
+
void
|
91
|
+
insert(store_base& store);
|
92
|
+
|
93
|
+
NUDB_DECL
|
94
|
+
void
|
95
|
+
erase(store_base& store);
|
96
|
+
|
97
|
+
NUDB_DECL
|
98
|
+
bool
|
99
|
+
flush_one();
|
100
|
+
|
101
|
+
class list
|
102
|
+
{
|
103
|
+
public:
|
104
|
+
NUDB_DECL
|
105
|
+
void
|
106
|
+
push_back(store_base* node);
|
107
|
+
|
108
|
+
NUDB_DECL
|
109
|
+
void
|
110
|
+
erase(store_base* node);
|
111
|
+
|
112
|
+
NUDB_DECL
|
113
|
+
void
|
114
|
+
splice(list& l);
|
115
|
+
|
116
|
+
bool
|
117
|
+
empty() const noexcept
|
118
|
+
{
|
119
|
+
return head_ == nullptr;
|
120
|
+
}
|
121
|
+
|
122
|
+
store_base* head_ = nullptr;
|
123
|
+
|
124
|
+
private:
|
125
|
+
store_base* tail_ = nullptr;
|
126
|
+
};
|
127
|
+
|
128
|
+
std::mutex m_;
|
129
|
+
list waiting_;
|
130
|
+
std::condition_variable cv_w_;
|
131
|
+
list flushing_;
|
132
|
+
std::condition_variable cv_f_;
|
133
|
+
|
134
|
+
std::uint32_t num_threads_ = 0;
|
135
|
+
std::thread t_;
|
136
|
+
|
137
|
+
bool stop_ = false;
|
138
|
+
};
|
139
|
+
|
140
|
+
} // nudb
|
141
|
+
|
142
|
+
#include <nudb/impl/context.ipp>
|
143
|
+
|
144
|
+
#endif
|
@@ -0,0 +1,117 @@
|
|
1
|
+
//
|
2
|
+
// Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
3
|
+
//
|
4
|
+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
5
|
+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
6
|
+
//
|
7
|
+
|
8
|
+
#ifndef NUDB_CREATE_HPP
|
9
|
+
#define NUDB_CREATE_HPP
|
10
|
+
|
11
|
+
#include <nudb/native_file.hpp>
|
12
|
+
#include <nudb/detail/bucket.hpp>
|
13
|
+
#include <nudb/detail/format.hpp>
|
14
|
+
#include <algorithm>
|
15
|
+
#include <cstring>
|
16
|
+
#include <random>
|
17
|
+
#include <stdexcept>
|
18
|
+
#include <utility>
|
19
|
+
|
20
|
+
namespace nudb {
|
21
|
+
|
22
|
+
/** Return a random salt.
|
23
|
+
|
24
|
+
This function will use the system provided random
|
25
|
+
number device to generate a uniformly distributed
|
26
|
+
64-bit unsigned value suitable for use the salt
|
27
|
+
value in a call to @ref create.
|
28
|
+
*/
|
29
|
+
template<class = void>
|
30
|
+
std::uint64_t
|
31
|
+
make_salt();
|
32
|
+
|
33
|
+
/** Create a new database.
|
34
|
+
|
35
|
+
This function creates a set of new database files with
|
36
|
+
the given parameters. The files must not already exist or
|
37
|
+
else an error is returned.
|
38
|
+
|
39
|
+
If an error occurs while the files are being created,
|
40
|
+
the function attempts to remove the files before
|
41
|
+
returning.
|
42
|
+
|
43
|
+
@par Example
|
44
|
+
@code
|
45
|
+
error_code ec;
|
46
|
+
create<xxhasher>(
|
47
|
+
"db.dat", "db.key", "db.log",
|
48
|
+
1, make_salt(), 8, 4096, 0.5f, ec);
|
49
|
+
@endcode
|
50
|
+
|
51
|
+
@par Template Parameters
|
52
|
+
|
53
|
+
@tparam Hasher The hash function to use. This type must
|
54
|
+
meet the requirements of @b Hasher. The same hash
|
55
|
+
function must be used every time the database is opened,
|
56
|
+
or else an error is returned. The provided @ref xxhasher
|
57
|
+
is a suitable general purpose hash function.
|
58
|
+
|
59
|
+
@tparam File The type of file to use. Use the default of
|
60
|
+
@ref native_file unless customizing the file behavior.
|
61
|
+
|
62
|
+
@param dat_path The path to the data file.
|
63
|
+
|
64
|
+
@param key_path The path to the key file.
|
65
|
+
|
66
|
+
@param log_path The path to the log file.
|
67
|
+
|
68
|
+
@param appnum A caller-defined value stored in the file
|
69
|
+
headers. When opening the database, the same value is
|
70
|
+
preserved and returned to the caller.
|
71
|
+
|
72
|
+
@param salt A random unsigned integer used to permute
|
73
|
+
the hash function to make it unpredictable. The return
|
74
|
+
value of @ref make_salt returns a suitable value.
|
75
|
+
|
76
|
+
@param key_size The number of bytes in each key.
|
77
|
+
|
78
|
+
@param blockSize The size of a key file block. Larger
|
79
|
+
blocks hold more keys but require more I/O cycles per
|
80
|
+
operation. The ideal block size the largest size that
|
81
|
+
may be read in a single I/O cycle, and device dependent.
|
82
|
+
The return value of @ref block_size returns a suitable
|
83
|
+
value for the volume of a given path.
|
84
|
+
|
85
|
+
@param load_factor A number between zero and one
|
86
|
+
representing the average bucket occupancy (number of
|
87
|
+
items). A value of 0.5 is perfect. Lower numbers
|
88
|
+
waste space, and higher numbers produce negligible
|
89
|
+
savings at the cost of increased I/O cycles.
|
90
|
+
|
91
|
+
@param ec Set to the error, if any occurred.
|
92
|
+
|
93
|
+
@param args Optional arguments passed to @b File constructors.
|
94
|
+
*/
|
95
|
+
template<
|
96
|
+
class Hasher,
|
97
|
+
class File = native_file,
|
98
|
+
class... Args
|
99
|
+
>
|
100
|
+
void
|
101
|
+
create(
|
102
|
+
path_type const& dat_path,
|
103
|
+
path_type const& key_path,
|
104
|
+
path_type const& log_path,
|
105
|
+
std::uint64_t appnum,
|
106
|
+
std::uint64_t salt,
|
107
|
+
nsize_t key_size,
|
108
|
+
nsize_t blockSize,
|
109
|
+
float load_factor,
|
110
|
+
error_code& ec,
|
111
|
+
Args&&... args);
|
112
|
+
|
113
|
+
} // nudb
|
114
|
+
|
115
|
+
#include <nudb/impl/create.ipp>
|
116
|
+
|
117
|
+
#endif
|
@@ -0,0 +1,296 @@
|
|
1
|
+
//
|
2
|
+
// Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
|
3
|
+
//
|
4
|
+
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
5
|
+
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
6
|
+
//
|
7
|
+
|
8
|
+
#ifndef NUDB_DETAIL_ARENA_HPP
|
9
|
+
#define NUDB_DETAIL_ARENA_HPP
|
10
|
+
|
11
|
+
#include <boost/assert.hpp>
|
12
|
+
#include <algorithm>
|
13
|
+
#include <chrono>
|
14
|
+
#include <cmath>
|
15
|
+
#include <cstddef>
|
16
|
+
#include <cstdint>
|
17
|
+
#include <memory>
|
18
|
+
|
19
|
+
#if NUDB_DEBUG_ARENA
|
20
|
+
#include <boost/beast/_experimental/unit_test/dstream.hpp>
|
21
|
+
#include <iostream>
|
22
|
+
#endif
|
23
|
+
|
24
|
+
namespace nudb {
|
25
|
+
namespace detail {
|
26
|
+
|
27
|
+
/* Custom memory manager that allocates in large blocks.
|
28
|
+
|
29
|
+
The implementation measures the rate of allocations in
|
30
|
+
bytes per second and tunes the large block size to fit
|
31
|
+
one second's worth of allocations.
|
32
|
+
*/
|
33
|
+
template<class = void>
|
34
|
+
class arena_t
|
35
|
+
{
|
36
|
+
using clock_type =
|
37
|
+
std::chrono::steady_clock;
|
38
|
+
|
39
|
+
using time_point =
|
40
|
+
typename clock_type::time_point;
|
41
|
+
|
42
|
+
class element;
|
43
|
+
|
44
|
+
char const* label_; // diagnostic
|
45
|
+
std::size_t alloc_ = 0; // block size
|
46
|
+
std::size_t used_ = 0; // bytes allocated
|
47
|
+
element* list_ = nullptr; // list of blocks
|
48
|
+
time_point when_ = clock_type::now();
|
49
|
+
|
50
|
+
public:
|
51
|
+
arena_t(arena_t const&) = delete;
|
52
|
+
arena_t& operator=(arena_t&&) = delete;
|
53
|
+
arena_t& operator=(arena_t const&) = delete;
|
54
|
+
|
55
|
+
~arena_t();
|
56
|
+
|
57
|
+
explicit
|
58
|
+
arena_t(char const* label = "");
|
59
|
+
|
60
|
+
arena_t(arena_t&& other);
|
61
|
+
|
62
|
+
// Set the allocation size
|
63
|
+
void
|
64
|
+
hint(std::size_t alloc)
|
65
|
+
{
|
66
|
+
alloc_ = alloc;
|
67
|
+
}
|
68
|
+
|
69
|
+
// Free all memory
|
70
|
+
void
|
71
|
+
clear();
|
72
|
+
|
73
|
+
void
|
74
|
+
periodic_activity();
|
75
|
+
|
76
|
+
std::uint8_t*
|
77
|
+
alloc(std::size_t n);
|
78
|
+
|
79
|
+
template<class U>
|
80
|
+
friend
|
81
|
+
void
|
82
|
+
swap(arena_t<U>& lhs, arena_t<U>& rhs);
|
83
|
+
};
|
84
|
+
|
85
|
+
//------------------------------------------------------------------------------
|
86
|
+
|
87
|
+
template<class _>
|
88
|
+
class arena_t<_>::element
|
89
|
+
{
|
90
|
+
std::size_t const capacity_;
|
91
|
+
std::size_t used_ = 0;
|
92
|
+
element* next_;
|
93
|
+
|
94
|
+
public:
|
95
|
+
element(std::size_t capacity, element* next)
|
96
|
+
: capacity_(capacity)
|
97
|
+
, next_(next)
|
98
|
+
{
|
99
|
+
}
|
100
|
+
|
101
|
+
element*
|
102
|
+
next() const
|
103
|
+
{
|
104
|
+
return next_;
|
105
|
+
}
|
106
|
+
|
107
|
+
void
|
108
|
+
clear()
|
109
|
+
{
|
110
|
+
used_ = 0;
|
111
|
+
}
|
112
|
+
|
113
|
+
std::size_t
|
114
|
+
remain() const
|
115
|
+
{
|
116
|
+
return capacity_ - used_;
|
117
|
+
}
|
118
|
+
|
119
|
+
std::size_t
|
120
|
+
capacity() const
|
121
|
+
{
|
122
|
+
return capacity_;
|
123
|
+
}
|
124
|
+
|
125
|
+
std::uint8_t*
|
126
|
+
alloc(std::size_t n);
|
127
|
+
};
|
128
|
+
|
129
|
+
template<class _>
|
130
|
+
std::uint8_t*
|
131
|
+
arena_t<_>::element::
|
132
|
+
alloc(std::size_t n)
|
133
|
+
{
|
134
|
+
if(n > capacity_ - used_)
|
135
|
+
return nullptr;
|
136
|
+
auto const p = const_cast<std::uint8_t*>(
|
137
|
+
reinterpret_cast<uint8_t const*>(this + 1)
|
138
|
+
) + used_;
|
139
|
+
used_ += n;
|
140
|
+
return p;
|
141
|
+
}
|
142
|
+
|
143
|
+
//------------------------------------------------------------------------------
|
144
|
+
|
145
|
+
template<class _>
|
146
|
+
arena_t<_>::
|
147
|
+
arena_t(char const* label)
|
148
|
+
: label_(label)
|
149
|
+
{
|
150
|
+
}
|
151
|
+
|
152
|
+
template<class _>
|
153
|
+
arena_t<_>::
|
154
|
+
~arena_t()
|
155
|
+
{
|
156
|
+
clear();
|
157
|
+
}
|
158
|
+
|
159
|
+
template<class _>
|
160
|
+
arena_t<_>::
|
161
|
+
arena_t(arena_t&& other)
|
162
|
+
: label_(other.label_)
|
163
|
+
, alloc_(other.alloc_)
|
164
|
+
, used_(other.used_)
|
165
|
+
, list_(other.list_)
|
166
|
+
, when_(other.when_)
|
167
|
+
{
|
168
|
+
other.used_ = 0;
|
169
|
+
other.list_ = nullptr;
|
170
|
+
other.when_ = clock_type::now();
|
171
|
+
other.alloc_ = 0;
|
172
|
+
}
|
173
|
+
|
174
|
+
template<class _>
|
175
|
+
void
|
176
|
+
arena_t<_>::
|
177
|
+
clear()
|
178
|
+
{
|
179
|
+
used_ = 0;
|
180
|
+
while(list_)
|
181
|
+
{
|
182
|
+
auto const e = list_;
|
183
|
+
list_ = list_->next();
|
184
|
+
e->~element();
|
185
|
+
delete[] reinterpret_cast<std::uint8_t*>(e);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
template<class _>
|
190
|
+
void
|
191
|
+
arena_t<_>::
|
192
|
+
periodic_activity()
|
193
|
+
{
|
194
|
+
using namespace std::chrono;
|
195
|
+
auto const now = clock_type::now();
|
196
|
+
auto const elapsed = now - when_;
|
197
|
+
if(elapsed < milliseconds{500})
|
198
|
+
return;
|
199
|
+
when_ = now;
|
200
|
+
auto const rate = static_cast<std::size_t>(std::ceil(
|
201
|
+
used_ / duration_cast<duration<float>>(elapsed).count()));
|
202
|
+
#if NUDB_DEBUG_ARENA
|
203
|
+
beast::unit_test::dstream dout{std::cout};
|
204
|
+
auto const size =
|
205
|
+
[](element* e)
|
206
|
+
{
|
207
|
+
std::size_t n = 0;
|
208
|
+
while(e)
|
209
|
+
{
|
210
|
+
++n;
|
211
|
+
e = e->next();
|
212
|
+
}
|
213
|
+
return n;
|
214
|
+
};
|
215
|
+
#endif
|
216
|
+
if(rate >= alloc_ * 2)
|
217
|
+
{
|
218
|
+
// adjust up
|
219
|
+
alloc_ = std::max(rate, alloc_ * 2);
|
220
|
+
#if NUDB_DEBUG_ARENA
|
221
|
+
dout << label_ << ": "
|
222
|
+
"rate=" << rate <<
|
223
|
+
", alloc=" << alloc_ << " UP"
|
224
|
+
", nused=" << used_ <<
|
225
|
+
", used=" << size(list_) <<
|
226
|
+
"\n";
|
227
|
+
#endif
|
228
|
+
}
|
229
|
+
else if(rate <= alloc_ / 2)
|
230
|
+
{
|
231
|
+
// adjust down
|
232
|
+
alloc_ /= 2;
|
233
|
+
#if NUDB_DEBUG_ARENA
|
234
|
+
dout << label_ << ": "
|
235
|
+
"rate=" << rate <<
|
236
|
+
", alloc=" << alloc_ << " DOWN"
|
237
|
+
", nused=" << used_ <<
|
238
|
+
", used=" << size(list_) <<
|
239
|
+
"\n";
|
240
|
+
#endif
|
241
|
+
}
|
242
|
+
else
|
243
|
+
{
|
244
|
+
#if NUDB_DEBUG_ARENA
|
245
|
+
dout << label_ << ": "
|
246
|
+
"rate=" << rate <<
|
247
|
+
", alloc=" << alloc_ <<
|
248
|
+
", nused=" << used_ <<
|
249
|
+
", used=" << size(list_) <<
|
250
|
+
"\n";
|
251
|
+
#endif
|
252
|
+
}
|
253
|
+
}
|
254
|
+
|
255
|
+
template<class _>
|
256
|
+
std::uint8_t*
|
257
|
+
arena_t<_>::
|
258
|
+
alloc(std::size_t n)
|
259
|
+
{
|
260
|
+
// Undefined behavior: Zero byte allocations
|
261
|
+
BOOST_ASSERT(n != 0);
|
262
|
+
n = 8 *((n + 7) / 8);
|
263
|
+
std::uint8_t* p;
|
264
|
+
if(list_)
|
265
|
+
{
|
266
|
+
p = list_->alloc(n);
|
267
|
+
if(p)
|
268
|
+
{
|
269
|
+
used_ += n;
|
270
|
+
return p;
|
271
|
+
}
|
272
|
+
}
|
273
|
+
auto const size = std::max(alloc_, n);
|
274
|
+
auto const e = reinterpret_cast<element*>(
|
275
|
+
new std::uint8_t[sizeof(element) + size]);
|
276
|
+
list_ = ::new(e) element{size, list_};
|
277
|
+
used_ += n;
|
278
|
+
return list_->alloc(n);
|
279
|
+
}
|
280
|
+
|
281
|
+
template<class _>
|
282
|
+
void
|
283
|
+
swap(arena_t<_>& lhs, arena_t<_>& rhs)
|
284
|
+
{
|
285
|
+
using std::swap;
|
286
|
+
swap(lhs.used_, rhs.used_);
|
287
|
+
swap(lhs.list_, rhs.list_);
|
288
|
+
// don't swap alloc_ or when_
|
289
|
+
}
|
290
|
+
|
291
|
+
using arena = arena_t<>;
|
292
|
+
|
293
|
+
} // detail
|
294
|
+
} // nudb
|
295
|
+
|
296
|
+
#endif
|