# class Crystal::EventLoop::Polling::Arena(T, BLOCK_BYTESIZE)

- Crystal::EventLoop::Polling::Arena(T, BLOCK_BYTESIZE)
- Reference
- Object

##
Overview

Generational Arena.

The arena allocates objects `T` at a predefined index. The object itself is uninitialized (outside of having its memory initialized to zero). The object can be allocated and later retrieved using the generation index (Arena::Index) that contains both the actual index (Int32) and the generation number (UInt32). Deallocating the object increases the generation number, which allows the object to be reallocated later on. Trying to retrieve the allocation using the generation index will fail if the generation number changed (it's a new allocation).

This arena isn't generic as it won't keep a list of free indexes. It assumes that something else will maintain the uniqueness of indexes and reuse indexes as much as possible instead of growing.

For example this arena is used to hold `Crystal::EventLoop::Polling::PollDescriptor` allocations for all the fd in a program, where the fd is used as the index. They're unique to the process and the OS always reuses the lowest fd numbers before growing.

Thread safety: the memory region is divided in blocks of size BLOCK_BYTESIZE allocated in the GC. Pointers are thus never invalidated. Mutating the blocks is protected by a mutual exclusion lock. Individual (de)allocations of objects are protected with a fine grained lock.

Guarantees: blocks' memory is initialized to zero, which means `T` objects are initialized to zero by default, then `#free` will also clear the memory, so the next allocation shall be initialized to zero, too.

##
Defined in:

crystal/event_loop/polling/arena.cr

##
Constant Summary

INVALID_INDEX = `Index.new(-1, 0)`

##
Constructors

- .new(capacity : Int32)

##
Instance Method Summary

- #allocate_at(index : Int32, & : Pointer(T), Index -> ) : Index | Nil

  Same as `#allocate_at?` but raises when already allocated.

- #allocate_at?(index : Int32, & : Pointer(T), Index -> ) : Index | Nil

  Allocates the object at index unless already allocated, then yields a pointer to the object at index and the current generation index to later retrieve and free the allocated object.

- #each_index(&) : Nil

  Iterates all allocated objects, yields the actual index as well as the generation index.

- #free(index : Index, &) : Nil

  Yields the object previously allocated at index then releases it.

- #get(index : Index, &) : Nil

  Yields a pointer to the object previously allocated at index.

- #get?(index : Index, &) : Bool

  Yields a pointer to the object previously allocated at index and returns true.

### Instance methods inherited from class `Reference`

==(other : self)
==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup, hash(hasher) hash, initialize initialize, inspect(io : IO) : Nil inspect, object_id : UInt64 object_id, pretty_print(pp) : Nil pretty_print, same?(other : Reference) : Bool
same?(other : Nil) same?, to_s(io : IO) : Nil to_s

### Constructor methods inherited from class `Reference`

new new, unsafe_construct(address : Pointer, *args, **opts) : self unsafe_construct

### Class methods inherited from class `Reference`

pre_initialize(address : Pointer) pre_initialize

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io : String | IO, root : String)
from_json(string_or_io : String | IO) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Constructor Detail

def self.new(capacity : Int32) #

##
Instance Method Detail

def allocate_at(index : Int32, & : Pointer(T), Index -> ) : Index | Nil #

Same as `#allocate_at?` but raises when already allocated.

def allocate_at?(index : Int32, & : Pointer(T), Index -> ) : Index | Nil #

Allocates the object at index unless already allocated, then yields a pointer to the object at index and the current generation index to later retrieve and free the allocated object. Eventually returns the generation index.

Does nothing if the object has already been allocated and returns `nil`.

There are no generational checks. Raises if index is out of bounds.

def each_index(&) : Nil #

Iterates all allocated objects, yields the actual index as well as the generation index.

def free(index : Index, &) : Nil #

Yields the object previously allocated at index then releases it.

Does nothing if the object isn't allocated, the generation has changed or index is out of bounds.

def get(index : Index, &) : Nil #

Yields a pointer to the object previously allocated at index.

Raises if the object isn't allocated, the generation has changed (i.e. the object has been freed then reallocated) or index is out of bounds.

def get?(index : Index, &) : Bool #

Yields a pointer to the object previously allocated at index and returns true.

Does nothing if the object isn't allocated, the generation has changed or index is out of bounds.