Skip to content

Instantly share code, notes, and snippets.

@garazdawi
Last active June 9, 2023 17:42
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save garazdawi/48f1284c0d533ab5a39eeac6f8ff99a0 to your computer and use it in GitHub Desktop.
Save garazdawi/48f1284c0d533ab5a39eeac6f8ff99a0 to your computer and use it in GitHub Desktop.
A shared mutable bit-vector in Erlang
-module(bit_vector).
-export([new/1, get/2, set/2, clear/2, flip/2, print/1]).
new(Size) ->
Words = (Size + 63) div 64,
{?MODULE, Size, atomics:new(Words, [{signed, false}])}.
get({?MODULE, _Size, Aref}, Bix) ->
Wix = (Bix div 64) + 1,
Mask = (1 bsl (Bix rem 64)),
case atomics:get(Aref, Wix) band Mask of
0 -> 0;
Mask -> 1
end.
set({?MODULE, _Size, Aref}, Bix) ->
Mask = (1 bsl (Bix rem 64)),
update(Aref, Bix, fun(Word) -> Word bor Mask end).
clear({?MODULE, _Size, Aref}, Bix) ->
Mask = bnot (1 bsl (Bix rem 64)),
update(Aref, Bix, fun(Word) -> Word band Mask end).
flip({?MODULE, _Size, Aref}, Bix) ->
Mask = (1 bsl (Bix rem 64)),
update(Aref, Bix, fun(Word) -> Word bxor Mask end).
print({?MODULE, Size, _Aref} = BV) ->
print(BV, Size-1).
print(BV, 0) ->
io:format("~B~n",[get(BV, 0)]);
print(BV, Slot) ->
io:format("~B",[get(BV, Slot)]),
print(BV, Slot-1).
update(Aref, Bix, Fun) ->
Wix = (Bix div 64) + 1,
update_loop(Aref, Wix, Fun, atomics:get(Aref, Wix)).
update_loop(Aref, Wix, Fun, Expected) ->
case atomics:compare_exchange(Aref, Wix, Expected, Fun(Expected)) of
ok ->
ok;
Was ->
update_loop(Aref, Wix, Fun, Was)
end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment