Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Forums
  - IRC
  - Community Discord
  - Wiki
  - GitHub
  - Issues
  - Get involved
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# std.experimental.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).

Source std/experimental/allocator/typed.d

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.
  `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.
  `hasNoIndirections`
    The type being allocated embeds no pointers. Examples: int, int[], Tuple!(int, float). 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*[], Tuple!(int, string).
  `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.
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.
  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.

  AllocFlag combination | Description
  --- | ---
  `AllocFlag.threadLocal | AllocFlag.hasNoIndirections | AllocFlag.fixedSize` | This is the most specific allocation policy: the memory being allocated is thread local, has no indirections at all, and will not be reallocated. Examples of types fitting this description: int, double, Tuple!(int, long), but not Tuple!(int, string), which contains an indirection.
  `AllocFlag.threadLocal | AllocFlag.hasNoIndirections` | As above, but may be reallocated later. Examples of types fitting this description are int[], double[], Tuple!(int, long)[], but not Tuple!(int, string)[], which contains an indirection.
  `AllocFlag.threadLocal` | As above, but may embed indirections. Examples of types fitting this description are int*[], Object[], Tuple!(int, string)[].
  `AllocFlag.immutableShared | AllocFlag.hasNoIndirections | AllocFlag.fixedSize` | The type being allocated is immutable and has no pointers. The thread that allocated it must also deallocate it. Example: immutable(int).
  `AllocFlag.immutableShared | AllocFlag.hasNoIndirections` | As above, but the type may be appended to in the future. Example: string.
  `AllocFlag.immutableShared` | As above, but the type may embed references. Example: immutable(Object)[].
  `AllocFlag.hasNoIndirections | AllocFlag.fixedSize` | The type being allocated may be shared across threads, embeds no indirections, and has fixed size.
  `AllocFlag.hasNoIndirections` | The type being allocated may be shared across threads, may embed indirections, and has variable size.
  `AllocFlag.fixedSize` | The type being allocated may be shared across threads, may embed indirections, and has fixed size.
  `0` | The most conservative/general allocation: memory may be shared, deallocated in a different thread, may or may not be resized, and may embed references.

  Parameters:

  PrimaryAllocator | The default allocator.
  Policies | Zero or more pairs consisting of an AllocFlag and an allocator type.

  Examples:

      import std.experimental.allocator.gc_allocator : GCAllocator;
      import std.experimental.allocator.mallocator : Mallocator;
      import std.experimental.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 const(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));

  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.
  uint `type2flags`(T)();
    Given a type T, returns its allocation-related flags as a combination of AllocFlag values.
  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.

    Returns:
    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.
  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

    Returns:
    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.
  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 array.length + delta)
    T `init` | element used for filling the array
    R `range` | range used for initializing the array elements

    Returns:
    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.
  bool `shrinkArray`(T)(ref T[] `arr`, size_t `delta`);
    Shrinks an array by `delta` elements using allocatorFor!(T[]).
    If arr.length < delta, does nothing and returns false. Otherwise, destroys the last arr.length - delta 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 arr.length - delta)

    Returns:
    true upon success, false if memory could not be reallocated. In the latter case arr[$ - delta .. $] 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.
  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.

Copyright © 1999-2023 by the D Language Foundation | Page generated by Ddoc on Sat Jul 15 12:04:02 2023