Allocators

Usage

use Allocators;

or

import Allocators;

Warning

The Allocators module is under development and does not have a stable interface yet

Provides custom allocators for Chapel objects on the heap.

This module provides an interface to customize how Chapel objects are allocated on the heap. This is opted into by changing calls to new/delete into newWithAllocator/deleteWithAllocator. This new functions allow Chapel code to customize how objects are allocated and deallocated.

For example, the following code demonstrates how the mallocWrapper allocator can be used to allocate a Chapel class.

class MyClass { var x: int; }
var alloc = new mallocWrapper(1024);
var x = newWithAllocator(alloc, unmanaged MyClass, 1);
writeln(x);
deleteWithAllocator(alloc, x);

Custom allocators can be defined as classes or records that implement the allocator interface. The interface has two methods: allocate and deallocate. The allocate method accepts an integer n and returns a c_ptr to the allocated memory. The deallocate method accepts a c_ptr to the allocated memory. Allocators are free to implement their own memory management strategies.

Limitations:
  • The newWithAllocator and deleteWithAllocator procedures are meant to be stand-ins pending a more elegant syntax to use custom allocators.

  • This module currently only supports allocating Chapel classes. In the future we hope to support other heap objects like arrays.

  • Allocating managed (owned/shared) Chapel classes are not supported, only unmanaged classes are supported.

interface allocator

All allocators must implement this interface. The interface has two methods: allocate and deallocate. The allocate method accepts an integer size and returns a pointer to the allocated memory. The deallocate method accepts a pointer to the allocated memory.

Allocators may either be classes or records.

proc ref Self.allocate(n: int) : c_ptr(void)

Allocate memory for n bytes.

Arguments:

n – The number of bytes to allocate.

Returns:

A c_ptr(void) to the allocated memory.

proc ref Self.deallocate(p: c_ptr(void))

Deallocate memory at p.

Arguments:

p – The pointer to the allocated memory.

proc newWithAllocator(alloc: allocator, type T, args ...) : T

Allocate a new unmanaged class with type T by invoking the allocate method of the given alloc. This is a drop-in replacement for new.

Example:

class MyClass { var x: int; }
var allocator = new bumpPtrMemPool(1024);
// The following two lines are equivalent, but the second one uses the allocator
var x = new unmanaged MyClass(1);
var x = newWithAllocator(allocator, unmanaged MyClass, 1);

Note

Named argument passing will not work with this function currently.

proc deleteWithAllocator(alloc: allocator, objects ...)

Delete the objects by invoking the deallocate method of the given allocator. This is a drop-in replacement for delete.

class mallocWrapper : allocator

A simple allocator that acts as a wrapper around CTypes.allocate and CTypes.deallocate.

proc allocate(n: int) : c_ptr(void)

Allocate memory for n bytes.

Arguments:

n – The number of bytes to allocate.

Returns:

A c_ptr(void) to the allocated memory.

proc deallocate(p: c_ptr(void))

Deallocate memory at p.

Arguments:

p – The pointer to the allocated memory.

class bumpPtrMemPool : allocator

The is a simple bump pointer allocator that is useful for allocating many small objects.

This allocator makes a single memory allocation in a contiguous block, calls to allocate will return the next available address. This allocator is not thread-safe by default, but can be made thread-safe by setting the parSafe parameter to true. By default, all memory allocated by bumpPtrMemPool is aligned to 16 bytes. This can be changed by setting the alignment parameter. An alignment of 0 will disable alignment.

The bumpPtrMemPool is initialized with a fixed size and allocates memory from that fixed size. Attempting to allocate more memory than the fixed size will result in an error. With checks enabled the program will halt, otherwise memory errors will occur.

All memory allocated by bumpPtrMemPool is deallocated when the bumpPtrMemPool instance is destroyed. The deallocate method is a no-op.

param parSafe : bool = false

Whether or not this allocator is thread-safe. if true, this allocator will use a lock to ensure that only one thread can allocate memory at a time.

param alignment : int = 16

The alignment of memory allocated by this allocator. If alignment is greater than 0, the pointers returned by allocate will be aligned to that alignment. alignment must be a power of 2.

var size : int(64)

The size of the memory block allocated by this allocator.

proc init(size: int(64), param parSafe: bool = false, param alignment: int = 16)

Initializes the allocator with a fixed size. The allocator will allocate memory from this fixed size.

Memory is allocated eagerly, so the entire size is allocated when the allocator is created.

Arguments:
  • size – The size of the memory block allocated by this allocator.

  • parSafe – Whether or not this allocator is thread-safe.

  • alignment – The alignment of memory allocated by this allocator.

proc deinit()

Deallocates all memory owned by this allocator. Attempting to use an object allocated by this allocator after calling this method will result in a use-after-free error.

proc allocate(n: int) : c_ptr(void)

Allocate memory for n bytes. If alignment is greater than 0, the memory will be aligned to that alignment.

If not enough memory is available and checks are enabled, this method will halt the program.

Arguments:

n – The number of bytes to allocate.

Returns:

A c_ptr(void) to the allocated memory.

proc deallocate(p: c_ptr(void))

This is a stub method that does nothing. All memory owned by this allocator is deallocated when the allocator is destroyed.

Arguments:

p – The pointer to the allocated memory.