@@ -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);
0 commit comments