Skip to content

Commit 2857878

Browse files
committed
Support find without automatic insert-if-not-present
1 parent 6194c3d commit 2857878

File tree

2 files changed

+40
-25
lines changed

2 files changed

+40
-25
lines changed

experimental/extrinsic_storage.h

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -121,20 +121,31 @@ class extrinsic_storage {
121121
}
122122

123123
//--------------------------------------------------------------------------
124-
// operator[]( pobj ) - returns the data entry for pobj
124+
// find_or_insert( pobj ) - returns the data entry for pobj
125125
//
126126
// If pobj does not yet have an entry, creates it
127127
//
128-
auto operator[](void* pobj) -> Value& {
128+
auto find_or_insert(void* pobj) -> Value& {
129129
if constexpr (debug_instrumentation) {
130130
// m_o_relaxed is enough, inc order doesn't matter for totals
131131
instrument_access_count.fetch_add(1, std::memory_order_relaxed);
132132
}
133-
auto v = lookup(pobj);
133+
auto v = lookup(pobj, lookup_mode::find_or_insert);
134134
assert (v);
135135
return *v;
136136
}
137137

138+
//--------------------------------------------------------------------------
139+
// find( pobj ) - returns the data entry for pobj or null if not present
140+
//
141+
auto find(void* pobj) -> Value* {
142+
if constexpr (debug_instrumentation) {
143+
// m_o_relaxed is enough, inc order doesn't matter for totals
144+
instrument_access_count.fetch_add(1, std::memory_order_relaxed);
145+
}
146+
return lookup(pobj, lookup_mode::find_or_insert);
147+
}
148+
138149
//--------------------------------------------------------------------------
139150
// erase( pobj ) - removes the entry for pobj
140151
//
@@ -143,7 +154,7 @@ class extrinsic_storage {
143154
// m_o_relaxed is enough, inc order doesn't matter for totals
144155
instrument_erase_count.fetch_add(1, std::memory_order_relaxed);
145156
}
146-
lookup(pobj, true);
157+
lookup(pobj, lookup_mode::erase);
147158
}
148159

149160
private:
@@ -178,9 +189,10 @@ class extrinsic_storage {
178189
// as I think they can be correct here and they are in the hot path
179190
// of the data structure traversal.
180191
//
192+
enum class lookup_mode { find, find_or_insert, erase };
181193
auto lookup(
182-
void* pobj,
183-
bool erase = false
194+
void* pobj,
195+
lookup_mode mode
184196
)
185197
-> Value*
186198
{
@@ -202,7 +214,7 @@ class extrinsic_storage {
202214
// and so this thread already has exclusive access to *pobj
203215
// and its .values data
204216
if (pchunk->keys[i].load(std::memory_order_relaxed) == pobj) {
205-
if (erase) {
217+
if (mode == lookup_mode::erase) {
206218
pchunk->keys[i].store(nullptr, std::memory_order_relaxed);
207219
return nullptr;
208220
}
@@ -217,11 +229,14 @@ class extrinsic_storage {
217229
pchunk = pchunk->next.load(std::memory_order_relaxed);
218230
}
219231

220-
// 2. Otherwise, if we're erasing we're done but we didn't actually find something to erase
221-
if (erase) {
232+
// 2. Otherwise, if we're not allowed to insert we're done
233+
// but we didn't actually find something so return null
234+
if (mode != lookup_mode::find_or_insert) {
222235
if constexpr (debug_instrumentation) {
223-
// m_o_relaxed is enough, inc order doesn't matter for totals
224-
instrument_erase_fail_count.fetch_add(1, std::memory_order_relaxed);
236+
if (mode == lookup_mode::erase) {
237+
// m_o_relaxed is enough, inc order doesn't matter for totals
238+
instrument_erase_fail_count.fetch_add(1, std::memory_order_relaxed);
239+
}
225240
}
226241
return nullptr;
227242
}

experimental/union_test.cpp

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,25 +55,25 @@
5555
//
5656
template<typename Tag = uint8_t>
5757
class union_registry {
58-
inline static auto tags = extrinsic_storage<Tag>{};
59-
inline static auto log = std::ofstream{ "union-violations.log" };
58+
static inline auto tags = extrinsic_storage<Tag>{};
59+
static inline auto log = std::ofstream{ "union-violations.log" };
6060
public:
61-
inline static auto invalid = std::numeric_limits<Tag>::max();
62-
inline static auto unknown = std::numeric_limits<Tag>::max()-1;
61+
static inline auto invalid = std::numeric_limits<Tag>::max();
62+
static inline auto unknown = std::numeric_limits<Tag>::max()-1;
6363

64-
static auto on_destroy (void* pobj) -> void { tags.erase(pobj); }
65-
static auto on_set_alternative(void* pobj, uint32_t alt) -> void { tags[pobj] = alt; }
66-
static auto on_get_alternative(void* pobj, uint32_t alt, std::source_location where = std::source_location::current()) -> void
64+
static inline auto on_destroy (void* pobj) -> void { tags.erase(pobj); }
65+
static inline auto on_set_alternative(void* pobj, uint32_t alt) -> void { tags.find_or_insert(pobj) = alt; }
66+
static inline auto on_get_alternative(void* pobj, uint32_t alt, std::source_location where = std::source_location::current()) -> void
6767
{
68-
if (auto active = tags[pobj];
69-
active != alt
70-
&& active != unknown
68+
if (auto active = tags.find(pobj);
69+
active // if we have discriminator info for this union
70+
&& *active != alt // and the discriminator not what is expected
71+
&& *active != unknown // and is not unknown
7172
)
7273
{
73-
log << where.file_name() << '(' << where.line() << ") " << where.function_name()
74-
<< ": union " << pobj
75-
<< ", active " << (active == invalid ? "invalid" : std::to_string(active))
76-
<< ", accessed " << alt << "\n";
74+
log << where.file_name() << '(' << where.line()
75+
<< "): union type safety violation - active member " << (*active == invalid ? "invalid" : std::to_string(*active))
76+
<< ", attempted to access " << alt << "\n";
7777
}
7878
}
7979
};

0 commit comments

Comments
 (0)