@@ -266,27 +266,39 @@ resolve(Opts, CurrPath, [Next | Rest], Depth) ->
266266 resolve (Opts , PathPart , Rest , Depth )
267267 end .
268268
269- % % @doc Look up an entry. Checks new table first, falls back to old.
270- % % Promotes raw/link entries from old to new (with ensure_parent_groups).
271- % % Groups are NOT promoted — they expire with their table. They get
272- % % recreated in new as a side-effect when children are promoted.
269+ % % @doc Look up an entry. Single-table: direct lookup (original speed).
270+ % % Double-buffer: checks new first, falls back to old with promote.
271+ % % Groups are NOT promoted — they expire with their table.
273272lookup_entry (Opts , Key ) when is_map (Opts ) ->
274- {New , Old } = get_tables (Opts ),
275- case ets :lookup (New , Key ) of
276- [{_ , Entry }] ->
277- Entry ;
278- [] when Old =:= undefined ->
279- nil ;
280- [] ->
281- case ets :lookup (Old , Key ) of
282- [{_ , {group , _ } = Entry }] ->
283- Entry ;
273+ Found = hb_store :find (Opts ),
274+ case Found of
275+ #{<<" ets-flip" >> := Flip ,
276+ <<" ets-table" >> := T1 ,
277+ <<" ets-table-2" >> := T2 } ->
278+ {New , Old } =
279+ case atomics :get (Flip , 1 ) of
280+ 0 -> {T1 , T2 };
281+ 1 -> {T2 , T1 }
282+ end ,
283+ case ets :lookup (New , Key ) of
284284 [{_ , Entry }] ->
285- ets :insert (New , {Key , Entry }),
286- ensure_parent_groups (New , Key ),
287285 Entry ;
288286 [] ->
289- nil
287+ case ets :lookup (Old , Key ) of
288+ [{_ , {group , _ } = Entry }] ->
289+ Entry ;
290+ [{_ , Entry }] ->
291+ ets :insert (New , {Key , Entry }),
292+ ensure_parent_groups (New , Key ),
293+ Entry ;
294+ [] ->
295+ nil
296+ end
297+ end ;
298+ #{<<" ets-table" >> := Table } ->
299+ case ets :lookup (Table , Key ) of
300+ [] -> nil ;
301+ [{_ , Entry }] -> Entry
290302 end
291303 end ;
292304lookup_entry (Table , Key ) ->
@@ -306,30 +318,50 @@ list(Opts, Path) ->
306318 list_resolved (Opts , resolve (Opts , Path )).
307319
308320list_resolved (Opts , ResolvedPath ) ->
309- {New , Old } = get_tables (Opts ),
310- S1 = group_set (New , ResolvedPath ),
311- S2 =
312- case Old of
313- undefined -> sets :new ();
314- _ -> group_set (Old , ResolvedPath )
315- end ,
316- Union = sets :union (S1 , S2 ),
317- case sets :size (Union ) > 0 of
318- true ->
319- {ok , sets :to_list (Union )};
320- false ->
321- case lookup_entry (Opts , ResolvedPath ) of
322- {link , Link } ->
323- list (Opts , Link );
324- {raw , Value } when is_map (Value ) ->
325- {ok , maps :keys (Value )};
326- {raw , Value } when is_list (Value ) ->
327- {ok , Value };
328- _ ->
329- not_found
321+ Found = hb_store :find (Opts ),
322+ case Found of
323+ #{<<" ets-flip" >> := Flip ,
324+ <<" ets-table" >> := T1 ,
325+ <<" ets-table-2" >> := T2 } ->
326+ {New , Old } =
327+ case atomics :get (Flip , 1 ) of
328+ 0 -> {T1 , T2 };
329+ 1 -> {T2 , T1 }
330+ end ,
331+ Union = sets :union (
332+ group_set (New , ResolvedPath ),
333+ group_set (Old , ResolvedPath )
334+ ),
335+ case sets :size (Union ) > 0 of
336+ true ->
337+ {ok , sets :to_list (Union )};
338+ false ->
339+ list_fallback (Opts , ResolvedPath )
340+ end ;
341+ #{<<" ets-table" >> := Table } ->
342+ case lookup_entry (Table , ResolvedPath ) of
343+ {group , Set } ->
344+ {ok , sets :to_list (Set )};
345+ Other ->
346+ list_from_entry (Opts , ResolvedPath , Other )
330347 end
331348 end .
332349
350+ list_fallback (Opts , ResolvedPath ) ->
351+ case lookup_entry (Opts , ResolvedPath ) of
352+ {link , Link } -> list (Opts , Link );
353+ Other -> list_from_entry (Opts , ResolvedPath , Other )
354+ end .
355+
356+ list_from_entry (_Opts , _Path , {raw , Value }) when is_map (Value ) ->
357+ {ok , maps :keys (Value )};
358+ list_from_entry (_Opts , _Path , {raw , Value }) when is_list (Value ) ->
359+ {ok , Value };
360+ list_from_entry (Opts , _Path , {link , Link }) ->
361+ list (Opts , Link );
362+ list_from_entry (_Opts , _Path , _ ) ->
363+ not_found .
364+
333365% % @doc Determine the item type at a path.
334366type (Opts , RawKey ) ->
335367 Key = resolve (Opts , RawKey ),
0 commit comments