Class: AMQ::IntAllocator

Inherits:
Object
  • Object
show all
Defined in:
lib/amq/int_allocator.rb

Overview

Simple bitset-based integer allocator, heavily inspired by com.rabbitmq.utility.IntAllocator class in the RabbitMQ Java client.

Unlike monotonically incrementing identifier, this allocator is suitable for very long running programs that aggressively allocate and release channels.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(lo, hi) ⇒ IntAllocator

Returns a new instance of IntAllocator.

Parameters:

  • lo (Integer)

    Lower boundary of the integer range available for allocation

  • hi (Integer)

    Upper boundary of the integer range available for allocation

Raises:

  • (ArgumentError)

    if upper boundary is not greater than the lower one



28
29
30
31
32
33
34
35
36
37
# File 'lib/amq/int_allocator.rb', line 28

def initialize(lo, hi)
  raise ArgumentError.new "upper boundary must be greater than the lower one (given: hi = #{hi}, lo = #{lo})" unless hi > lo

  @hi = hi
  @lo = lo

  @number_of_bits = hi - lo
  @range          = Range.new(1, @number_of_bits)
  @free_set       = BitSet.new(@number_of_bits)
end

Instance Attribute Details

#hiInteger (readonly)

Returns Upper boundary of the integer range available for allocation.

Returns:

  • (Integer)

    Upper boundary of the integer range available for allocation



21
22
23
# File 'lib/amq/int_allocator.rb', line 21

def hi
  @hi
end

#loInteger (readonly)

Returns Lower boundary of the integer range available for allocation.

Returns:

  • (Integer)

    Lower boundary of the integer range available for allocation



23
24
25
# File 'lib/amq/int_allocator.rb', line 23

def lo
  @lo
end

#number_of_bitsInteger (readonly)

Returns Number of integers in the allocation range.

Returns:

  • (Integer)

    Number of integers in the allocation range



19
20
21
# File 'lib/amq/int_allocator.rb', line 19

def number_of_bits
  @number_of_bits
end

Instance Method Details

#allocateInteger

Attempts to allocate next available integer. If allocation succeeds, allocated value is returned. Otherwise, -1 is returned.

Current implementation of this method is O(n), where n is number of bits in the range available for allocation.

Returns:

  • (Integer)

    Allocated integer if allocation succeeded. -1 otherwise.



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/amq/int_allocator.rb', line 46

def allocate

  if n = @free_set.next_clear_bit

    if n < @hi - 1 then
      @free_set.set(n)
      n + 1
    else
      -1
    end

  else
    -1
  end
end

#allocated?(reservation) ⇒ Boolean

Returns true if provided argument was previously allocated, false otherwise.

Returns:

  • (Boolean)

    true if provided argument was previously allocated, false otherwise



72
73
74
# File 'lib/amq/int_allocator.rb', line 72

def allocated?(reservation)
  @free_set.get(reservation-1)
end

#free(reservation) ⇒ NilClass Also known as: release

Releases previously allocated integer. If integer provided as argument was not previously allocated, this method has no effect.

Returns:

  • (NilClass)

    nil



66
67
68
# File 'lib/amq/int_allocator.rb', line 66

def free(reservation)
  @free_set.unset(reservation-1)
end

#resetObject

Releases the whole allocation range



77
78
79
# File 'lib/amq/int_allocator.rb', line 77

def reset
  @free_set.clear
end