Skip to content

Commit 26d85f1

Browse files
committed
For union instrumentation, don't throw if allocation fails
See comment "not using make_unique" in extrinsic_storage.h
1 parent 3c4d9f7 commit 26d85f1

File tree

2 files changed

+23
-13
lines changed

2 files changed

+23
-13
lines changed

experimental/extrinsic_storage.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,14 @@ class extrinsic_storage {
124124
// find_or_insert( pobj ) - returns the data entry for pobj
125125
//
126126
// If pobj does not yet have an entry, creates it
127+
// Returns null only if not present and allocation is needed but fails
127128
//
128-
auto find_or_insert(void* pobj) noexcept -> Value& {
129+
auto find_or_insert(void* pobj) noexcept -> Value* {
129130
if constexpr (debug_instrumentation) {
130131
// m_o_relaxed is enough, inc order doesn't matter for totals
131132
instrument_access_count.fetch_add(1, std::memory_order_relaxed);
132133
}
133-
auto v = lookup(pobj, lookup_mode::find_or_insert);
134-
assert (v);
135-
return *v;
134+
return lookup(pobj, lookup_mode::find_or_insert);
136135
}
137136

138137
//--------------------------------------------------------------------------
@@ -143,7 +142,7 @@ class extrinsic_storage {
143142
// m_o_relaxed is enough, inc order doesn't matter for totals
144143
instrument_access_count.fetch_add(1, std::memory_order_relaxed);
145144
}
146-
return lookup(pobj, lookup_mode::find_or_insert);
145+
return lookup(pobj, lookup_mode::find);
147146
}
148147

149148
//--------------------------------------------------------------------------
@@ -171,8 +170,10 @@ class extrinsic_storage {
171170
//
172171
// Parameters
173172
// pobj the key to look up
174-
// erase if true, reset key to null and return nullptr
175-
// if false, return a pointer to the value (insert key if not present)
173+
// mode if erase, reset key to null and return nullptr
174+
// if find, return a pointer to the value if it exists, or null
175+
// if find_or_insert, return a pointer to the value (inserted if
176+
// not present) or null if allocation was needed and failed
176177
//
177178
// (*) This function requires that the calling code has exclusive access to
178179
// *pobj, and if *pobj is shared has done any necessary synchronization
@@ -274,10 +275,16 @@ class extrinsic_storage {
274275
// b) Otherwise, we need to allocate a new chunk for it
275276
// At this point, pchunk points to the last chunk in this bucket
276277
assert (pchunk);
277-
auto pnew = std::make_unique<chunk>();
278-
auto ret = &pnew->values[0];
278+
279+
// Not using make_unique: In principle, if allocation fails we don't
280+
// want to change well-formed program behavior. (In practice, if this
281+
// small allocation ever fails the program is already in deep trouble;
282+
// unless Key or Data are large, a chunk is usually well under 1KB)
283+
auto pnew = std::unique_ptr<chunk>( new (std::nothrow) chunk{} );
284+
if (pnew == nullptr) { return nullptr; }
279285

280286
pnew->keys[0] = pobj;
287+
auto ret = &pnew->values[0];
281288
while (!pchunk->next.compare_exchange_weak_null(pnew)) {
282289
pchunk = pchunk->next.load();
283290
assert (pchunk);

experimental/union_test.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,13 @@ class union_registry {
6161
static inline auto invalid = std::numeric_limits<Tag>::max();
6262
static inline auto unknown = std::numeric_limits<Tag>::max()-1;
6363

64-
static inline auto on_destroy (void* pobj) noexcept -> void { tags.erase(pobj); }
65-
static inline auto on_set_alternative(void* pobj, uint32_t alt) noexcept -> 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
67-
{
64+
static inline auto on_destroy(void* pobj) noexcept -> void { tags.erase(pobj); }
65+
66+
static inline auto on_set_alternative(void* pobj, uint32_t alt) noexcept -> void {
67+
if (auto p = tags.find_or_insert(pobj)) { *p = alt; }
68+
}
69+
70+
static inline auto on_get_alternative(void* pobj, uint32_t alt, std::source_location where = std::source_location::current()) -> void {
6871
if (auto active = tags.find(pobj);
6972
active // if we have discriminator info for this union
7073
&& *active != alt // and the discriminator not what is expected

0 commit comments

Comments
 (0)