-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Expand file tree
/
Copy pathcleanup.h
More file actions
109 lines (89 loc) · 2.87 KB
/
cleanup.h
File metadata and controls
109 lines (89 loc) · 2.87 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
#pragma once
#include <functional>
#include <list>
#include "source/common/common/assert.h"
namespace Envoy {
// RAII cleanup via functor.
class Cleanup {
public:
Cleanup(std::function<void()> f) : f_(std::move(f)) {}
~Cleanup() { f_(); }
// Copying leads to cleanup multiple times, so only allow move.
Cleanup(const Cleanup&) = delete;
Cleanup(Cleanup&&) = default;
void cancel() {
cancelled_ = true;
f_ = []() {};
}
bool cancelled() { return cancelled_; }
static Cleanup noop() {
return {[]() {}};
}
private:
std::function<void()> f_;
bool cancelled_{false};
};
// RAII helper class to add an element to an std::list on construction and erase
// it on destruction, unless the cancel method has been called.
template <class T> class RaiiListElement {
public:
RaiiListElement(std::list<T>& container, T element) : container_(container) {
it_ = container.emplace(container.begin(), element);
}
virtual ~RaiiListElement() {
if (!cancelled_) {
erase();
}
}
// Cancel deletion of the element on destruction. This should be called if the iterator has
// been invalidated, e.g., if the list has been cleared or the element removed some other way.
void cancel() { cancelled_ = true; }
// Delete the element now, instead of at destruction.
void erase() {
ASSERT(!cancelled_);
container_.erase(it_);
cancelled_ = true;
}
private:
std::list<T>& container_;
typename std::list<T>::iterator it_;
bool cancelled_{false};
};
// RAII helper class to add an element to a std::list held inside an absl::flat_hash_map on
// construction and erase it on destruction, unless the cancel method has been called. If the list
// is empty after removal of the element, the destructor will also remove the list from the map.
template <class Key, class Value> class RaiiMapOfListElement {
public:
using MapOfList = absl::flat_hash_map<Key, std::list<Value>>;
template <typename ConvertibleToKey>
RaiiMapOfListElement(MapOfList& map, const ConvertibleToKey& key, Value value)
: map_(map), key_(key) {
// The list reference itself cannot be saved because it is not stable in the event of a
// absl::flat_hash_map rehash.
std::list<Value>& list = map_.try_emplace(key).first->second;
it_ = list.emplace(list.begin(), value);
}
virtual ~RaiiMapOfListElement() {
if (!cancelled_) {
erase();
}
}
void cancel() { cancelled_ = true; }
private:
void erase() {
ASSERT(!cancelled_);
auto list_it = map_.find(key_);
ASSERT(list_it != map_.end());
list_it->second.erase(it_);
if (list_it->second.empty()) {
map_.erase(key_);
}
cancelled_ = true;
}
MapOfList& map_;
// Because of absl::flat_hash_map iterator instability we have to keep a copy of the key.
const Key key_;
typename MapOfList::mapped_type::iterator it_;
bool cancelled_{false};
};
} // namespace Envoy