class

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

Inherits Reference / Object

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.

Constants

INVALID_INDEX = Index.new(-1, 0)

Constructors

new(capacity : Int32)
Source

Instance methods

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

Same as #allocate_at? but raises when already allocated.

Source
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.

Source
each_index

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

Source
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.

Source
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.

Source
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.

Source

Nested types