forked from rethinkdb/rethinkdb
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathobject_buffer.hpp
More file actions
93 lines (78 loc) · 2.27 KB
/
object_buffer.hpp
File metadata and controls
93 lines (78 loc) · 2.27 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
// Copyright 2010-2012 RethinkDB, all rights reserved.
#ifndef CONTAINERS_OBJECT_BUFFER_HPP_
#define CONTAINERS_OBJECT_BUFFER_HPP_
#include "errors.hpp"
// Caveat: do not use this template with an object that has a blocking destructor, if
// you are going to allocate multiple times using a single object_buffer_t. This object
// should catch it if you try to do anything particularly stupid, though.
template <class T>
class object_buffer_t {
public:
class destruction_sentinel_t {
public:
explicit destruction_sentinel_t(object_buffer_t<T> *_parent) : parent(_parent) { }
~destruction_sentinel_t() {
if (parent->has()) {
parent->reset();
}
}
private:
object_buffer_t<T> *parent;
DISABLE_COPYING(destruction_sentinel_t);
};
object_buffer_t() : state(EMPTY) { }
~object_buffer_t() {
// The buffer cannot be destroyed while an object is in the middle of
// constructing or destructing
if (state == INSTANTIATED) {
reset();
} else {
rassert(state == EMPTY);
}
}
template <class... Args>
T *create(const Args &... args) {
rassert(state == EMPTY);
state = CONSTRUCTING;
try {
new (&object_data[0]) T(args...);
} catch (...) {
state = EMPTY;
throw;
}
state = INSTANTIATED;
return get();
}
T *get() {
rassert(state == INSTANTIATED);
return reinterpret_cast<T *>(&object_data[0]);
}
T *operator->() {
return get();
}
const T *get() const {
rassert(state == INSTANTIATED);
return reinterpret_cast<const T *>(&object_data[0]);
}
void reset() {
T *obj_ptr = get();
state = DESTRUCTING;
obj_ptr->~T();
state = EMPTY;
}
bool has() const {
return (state == INSTANTIATED);
}
private:
// We're going more for a high probability of good alignment than
// proof of good alignment.
char object_data[sizeof(T)];
enum buffer_state_t {
EMPTY,
CONSTRUCTING,
INSTANTIATED,
DESTRUCTING
} state;
DISABLE_COPYING(object_buffer_t);
};
#endif // CONTAINERS_OBJECT_BUFFER_HPP_