@@ -45,6 +45,8 @@ defmodule Abit.Counter do
4545
4646 @ bit_sizes [ 2 , 4 , 8 , 16 , 32 ]
4747
48+ import Bitwise
49+
4850 alias Abit.Counter
4951
5052 @ keys [ :atomics_ref , :signed , :wrap_around , :size , :counters_bit_size , :min , :max ]
@@ -128,7 +130,7 @@ defmodule Abit.Counter do
128130
129131 atomics_value = :atomics . get ( atomics_ref , atomics_index )
130132
131- get_value ( signed , counters_bit_size , bit_index , << atomics_value :: 64 >> )
133+ get_value ( signed , counters_bit_size , bit_index , atomics_value )
132134 end
133135
134136 @ doc """
@@ -179,8 +181,8 @@ defmodule Abit.Counter do
179181 bit_index ,
180182 atomics_value
181183 ) do
182- { final_counter_value , << next_atomics_value :: 64 >> } =
183- put_value ( signed , counters_bit_size , bit_index , << atomics_value :: 64 >> , value )
184+ { final_counter_value , next_atomics_value } =
185+ put_value ( signed , counters_bit_size , bit_index , atomics_value , value )
184186
185187 case :atomics . compare_exchange (
186188 atomics_ref ,
@@ -231,7 +233,7 @@ defmodule Abit.Counter do
231233
232234 atomics_value = :atomics . get ( atomics_ref , atomics_index )
233235
234- current_value = get_value ( signed , counters_bit_size , bit_index , << atomics_value :: 64 >> )
236+ current_value = get_value ( signed , counters_bit_size , bit_index , atomics_value )
235237
236238 next_value = current_value + incr
237239
@@ -240,8 +242,8 @@ defmodule Abit.Counter do
240242 { :error , :value_out_of_bounds }
241243
242244 { _ , _ } ->
243- { final_counter_value , << next_atomics_value :: 64 >> } =
244- put_value ( signed , counters_bit_size , bit_index , << atomics_value :: 64 >> , next_value )
245+ { final_counter_value , next_atomics_value } =
246+ put_value ( signed , counters_bit_size , bit_index , atomics_value , next_value )
245247
246248 case :atomics . compare_exchange (
247249 atomics_ref ,
@@ -409,71 +411,30 @@ defmodule Abit.Counter do
409411 end
410412 end
411413
412- @ bit_sizes
413- |> Enum . each ( fn counters_bit_size ->
414- 0 .. 63
415- |> Enum . filter ( fn n -> rem ( n , counters_bit_size ) == 0 end )
416- |> Enum . each ( fn bit_index ->
417- bit_left_start = bit_index + counters_bit_size
418- left_bits = 64 - bit_left_start
419- right_bits = bit_left_start - counters_bit_size
420-
421- defp unquote ( :get_value ) (
422- false ,
423- unquote ( counters_bit_size ) ,
424- unquote ( bit_index ) ,
425- << _ :: unquote ( left_bits ) , value :: unquote ( counters_bit_size ) , _ :: unquote ( right_bits ) >>
426- ) do
427- value
428- end
414+ defp get_value ( signed , bit_size , bit_index , atomic ) do
415+ value = atomic >>> bit_index &&& bit_mask ( bit_size )
416+ decode_value ( value , signed , bit_size )
417+ end
429418
430- defp unquote ( :get_value ) (
431- true ,
432- unquote ( counters_bit_size ) ,
433- unquote ( bit_index ) ,
434- << _left :: unquote ( left_bits ) , value :: unquote ( counters_bit_size ) - signed ,
435- _right :: unquote ( right_bits ) >>
436- ) do
437- value
438- end
419+ defp put_value ( signed , bit_size , bit_index , atomic , new_value ) do
420+ mask = bit_mask ( bit_size )
421+ encoded_value = new_value &&& mask
422+ shifted_mask = mask <<< bit_index
423+ next_atomic = ( atomic &&& bnot ( shifted_mask ) ) ||| encoded_value <<< bit_index
439424
440- defp unquote ( :put_value ) (
441- false ,
442- unquote ( counters_bit_size ) ,
443- unquote ( bit_index ) ,
444- << left :: unquote ( left_bits ) , _current_value :: unquote ( counters_bit_size ) ,
445- right :: unquote ( right_bits ) >> ,
446- new_value
447- ) do
448- << final_counter_value :: unquote ( counters_bit_size ) >> =
449- << new_value :: unquote ( counters_bit_size ) >>
450-
451- {
452- final_counter_value ,
453- << left :: unquote ( left_bits ) , new_value :: unquote ( counters_bit_size ) ,
454- right :: unquote ( right_bits ) >>
455- }
456- end
425+ { decode_value ( encoded_value , signed , bit_size ) , next_atomic }
426+ end
457427
458- defp unquote ( :put_value ) (
459- true ,
460- unquote ( counters_bit_size ) ,
461- unquote ( bit_index ) ,
462- << left :: unquote ( left_bits ) , _current_value :: unquote ( counters_bit_size ) - signed ,
463- right :: unquote ( right_bits ) >> ,
464- new_value
465- ) do
466- << final_counter_value :: unquote ( counters_bit_size ) - signed >> =
467- << new_value :: unquote ( counters_bit_size ) - signed >>
468-
469- {
470- final_counter_value ,
471- << left :: unquote ( left_bits ) , new_value :: unquote ( counters_bit_size ) - signed ,
472- right :: unquote ( right_bits ) >>
473- }
474- end
475- end )
476- end )
428+ defp decode_value ( value , false , _bit_size ) , do: value
429+
430+ defp decode_value ( value , true , bit_size ) do
431+ sign_bit = 1 <<< ( bit_size - 1 )
432+ if ( value &&& sign_bit ) == 0 , do: value , else: value - ( sign_bit <<< 1 )
433+ end
434+
435+ for bit_size <- @ bit_sizes do
436+ defp bit_mask ( unquote ( bit_size ) ) , do: unquote ( ( 1 <<< bit_size ) - 1 )
437+ end
477438
478439 defp integer_to_counters ( integer , signed , bit_size ) do
479440 do_integer_to_counters ( << integer :: 64 >> , signed , bit_size , [ ] )
@@ -503,8 +464,6 @@ defmodule Abit.Counter do
503464
504465 # Returns the {min, max} counter range for the given signed flag and bit size.
505466 defp counter_range ( signed , bit_size ) do
506- import Bitwise
507-
508467 case signed do
509468 false -> { 0 , ( 1 <<< bit_size ) - 1 }
510469 true -> { - ( 1 <<< ( bit_size - 1 ) ) , ( 1 <<< ( bit_size - 1 ) ) - 1 }
0 commit comments