stdx.allocator.typed

This module defines TypedAllocator, a statically-typed allocator that aggregates multiple untyped allocators and uses them depending on the static properties of the types allocated. For example, distinct allocators may be used for thread-local vs. thread-shared data, or for fixed-size data (struct, class objects) vs. resizable data (arrays).

  • Declaration

    enum AllocFlag: uint;

    Allocation-related flags dictated by type characteristics. TypedAllocator deduces these flags from the type being allocated and uses the appropriate allocator accordingly.

    • Declaration

      fixedSize

      Fixed-size allocation (unlikely to get reallocated later). Examples: int, double, any struct or class type. By default it is assumed that the allocation is variable-size, i.e. susceptible to later reallocation (for example all array types). This flag is advisory, i.e. in-place resizing may be attempted for fixedSize allocations and may succeed. The flag is just a hint to the compiler it may use allocation strategies that work well with objects of fixed size.

    • Declaration

      hasNoIndirections

      The type being allocated embeds no pointers. Examples: int, int[], . The implicit conservative assumption is that the type has members with indirections so it needs to be scanned if garbage collected. Example of types with pointers: int*[], .

    • Declaration

      immutableShared
      threadLocal

      By default it is conservatively assumed that allocated memory may be cast to shared, passed across threads, and deallocated in a different thread than the one that allocated it. If that's not the case, there are two options. First, immutableShared means the memory is allocated for immutable data and will be deallocated in the same thread it was allocated in. Second, threadLocal means the memory is not to be shared across threads at all. The two flags cannot be simultaneously present.

  • Declaration

    struct TypedAllocator(PrimaryAllocator, Policies...);

    TypedAllocator acts like a chassis on which several specialized allocators can be assembled. To let the system make a choice about a particular kind of allocation, use Default for the respective parameters.

    Discussion

    There is a hierarchy of allocation kinds. When an allocator is implemented for a given combination of flags, it is used. Otherwise, the next down the list is chosen.

    Parameters

    PrimaryAllocator

    The default allocator.

    Policies

    Zero or more pairs consisting of an AllocFlag and an allocator type.

    Examples

    1. import stdx.allocator.gc_allocator : GCAllocator; import stdx.allocator.mallocator : Mallocator; import stdx.allocator.mmap_allocator : MmapAllocator; alias MyAllocator = TypedAllocator!(GCAllocator, AllocFlag.fixedSize | AllocFlag.threadLocal, Mallocator, AllocFlag.fixedSize | AllocFlag.threadLocal | AllocFlag.hasNoIndirections, MmapAllocator, ); MyAllocator a; auto b = &a.allocatorFor!0(); static assert(is(typeof(*b) == shared GCAllocator)); enum f1 = AllocFlag.fixedSize | AllocFlag.threadLocal; auto c = &a.allocatorFor!f1(); static assert(is(typeof(*c) == Mallocator)); enum f2 = AllocFlag.fixedSize | AllocFlag.threadLocal; static assert(is(typeof(a.allocatorFor!f2()) == Mallocator)); // Partial match enum f3 = AllocFlag.threadLocal; static assert(is(typeof(a.allocatorFor!f3()) == Mallocator)); int* p = a.make!int; scope(exit) a.dispose(p); int[] arr = a.makeArray!int(42); scope(exit) a.dispose(arr); assert(a.expandArray(arr, 3)); assert(a.shrinkArray(arr, 4));

    • Declaration

      ref auto allocatorFor(uint flags)();
      ref auto allocatorFor(T)();

      Given flags as a combination of AllocFlag values, or a type T, returns the allocator that's a closest fit in capabilities.

    • Declaration

      uint type2flags(T)();

      Given a type T, returns its allocation-related flags as a combination of AllocFlag values.

    • Declaration

      auto make(T, A...)(auto ref A args);

      Dynamically allocates (using the appropriate allocator chosen with allocatorFor!T) and then creates in the memory allocated an object of type T, using args (if any) for its initialization. Initialization occurs in the memory allocated and is otherwise semantically the same as T(args). (Note that using make!(T[]) creates a pointer to an (empty) array of Ts, not an array. To allocate and initialize an array, use makeArray!T described below.)

      Parameters

      T

      Type of the object being created.

      A args

      Optional arguments used for initializing the created object. If not present, the object is default constructed.

      Return Value

      If T is a class type, returns a reference to the created T object. Otherwise, returns a T* pointing to the created object. In all cases, returns null if allocation failed.

      Throws

      If T's constructor throws, deallocates the allocated memory and propagates the exception.

    • Declaration

      T[] makeArray(T)(size_t length);
      T[] makeArray(T)(size_t length, auto ref T init);
      T[] makeArray(T, R)(R range) if (isInputRange!R);

      Create an array of T with length elements. The array is either default-initialized, filled with copies of init, or initialized with values fetched from range.

      Parameters

      T

      element type of the array being created

      size_t length

      length of the newly created array

      T init

      element used for filling the array

      R range

      range used for initializing the array elements

      Return Value

      The newly-created array, or null if either length was 0 or allocation failed.

      Throws

      The first two overloads throw only if the used allocator's primitives do. The overloads that involve copy initialization deallocate memory and propagate the exception if the copy operation throws.

    • Declaration

      bool expandArray(T)(ref T[] array, size_t delta);
      bool expandArray(T)(T[] array, size_t delta, auto ref T init);
      bool expandArray(T, R)(ref T[] array, R range) if (isInputRange!R);

      Grows array by appending delta more elements. The needed memory is allocated using the same allocator that was used for the array type. The extra elements added are either default-initialized, filled with copies of init, or initialized with values fetched from range.

      Parameters

      T

      element type of the array being created

      T[] array

      a reference to the array being grown

      size_t delta

      number of elements to add (upon success the new length of array is )

      T init

      element used for filling the array

      R range

      range used for initializing the array elements

      Return Value

      true upon success, false if memory could not be allocated. In the latter case array is left unaffected.

      Throws

      The first two overloads throw only if the used allocator's primitives do. The overloads that involve copy initialization deallocate memory and propagate the exception if the copy operation throws.

    • Declaration

      bool shrinkArray(T)(ref T[] arr, size_t delta);

      Shrinks an array by delta elements using allocatorFor!(T[]).

      Discussion

      If , does nothing and returns false. Otherwise, destroys the last elements in the array and then reallocates the array's buffer. If reallocation fails, fills the array with default-initialized data.

      Parameters

      T

      element type of the array being created

      T[] arr

      a reference to the array being shrunk

      size_t delta

      number of elements to remove (upon success the new length of arr is )

      Return Value

      true upon success, false if memory could not be reallocated. In the latter case is left with default-initialized elements.

      Throws

      The first two overloads throw only if the used allocator's primitives do. The overloads that involve copy initialization deallocate memory and propagate the exception if the copy operation throws.

    • Declaration

      void dispose(T)(T* p);
      void dispose(T)(T p) if (is(T == class) || is(T == interface));
      void dispose(T)(T[] array);

      Destroys and then deallocates (using allocatorFor!T) the object pointed to by a pointer, the class object referred to by a class or interface reference, or an entire array. It is assumed the respective entities had been allocated with the same allocator.