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.building_blocks.free_list

Source std/experimental/allocator/building_blocks/free_list.d

struct `FreeList`(ParentAllocator, size_t minSize, size_t maxSize = minSize, Flag!"adaptive" adaptive = No.adaptive);
  Free list allocator, stackable on top of another allocator. Allocation requests between min and max bytes are rounded up to max and served from a singly-linked list of buffers deallocated in the past. All other allocations are directed to ParentAllocator. Due to the simplicity of free list management, allocations from the free list are fast. If adaptive is set to Yes.adaptive, the free list gradually reduces its size if allocations tend to use the parent allocator much more than the lists' available nodes.
  One instantiation is of particular interest: FreeList!(0, unbounded) puts every deallocation in the freelist, and subsequently serves any allocation from the freelist (if not empty). There is no checking of size matching, which would be incorrect for a freestanding allocator but is both correct and fast when an owning allocator on top of the free list allocator (such as Segregator) is already in charge of handling size checking.
  The following methods are defined if ParentAllocator defines them, and forward to it: expand, owns, reallocate.
  const @property size_t `min`();
    Returns the smallest allocation size eligible for allocation from the freelist. (If minSize != chooseAtRuntime, this is simply an alias for minSize.)
  @property void `min`(size_t `low`);
    If FreeList has been instantiated with minSize == chooseAtRuntime, then the `min` property is writable. Setting it must precede any allocation.
    Parameters:

    size_t `low` | new value for `min`

    Precondition low <= max, or maxSize == chooseAtRuntime and max has not yet been initialized. Also, no allocation has been yet done with this allocator.

    Postcondition min == low

  const @property size_t `max`();
    Returns the largest allocation size eligible for allocation from the freelist. (If maxSize != chooseAtRuntime, this is simply an alias for maxSize.) All allocation requests for sizes greater than or equal to min and less than or equal to `max` are rounded to max and forwarded to the parent allocator. When the block fitting the same constraint gets deallocated, it is put in the freelist with the allocated size assumed to be `max`.
  @property void `max`(size_t `high`);
    If FreeList has been instantiated with maxSize == chooseAtRuntime, then the `max` property is writable. Setting it must precede any allocation.
    Parameters:

    size_t `high` | new value for `max`

    Precondition high >= min, or minSize == chooseAtRuntime and min has not yet been initialized. Also high >= (void*).sizeof. Also, no allocation has been yet done with this allocator.

    Postcondition max == high

  ParentAllocator `parent`;
    The parent allocator. Depending on whether ParentAllocator holds state or not, this is a member variable or an alias for ParentAllocator.instance.
  alias `alignment` = ParentAllocator.`alignment`;
    Alignment offered.
  size_t `goodAllocSize`(size_t `bytes`);
    If maxSize == unbounded, returns parent.`goodAllocSize`(`bytes`). Otherwise, returns max for sizes in the interval [min, max], and parent.`goodAllocSize`(`bytes`) otherwise.

    Precondition If set at runtime, min and/or max must be initialized appropriately.

    Postcondition result >= bytes

  void[] `allocate`(size_t `n`);
    Allocates memory either off of the free list or from the parent allocator. If `n` is within [min, max] or if the free list is unchecked (minSize == 0 && maxSize == size_t.max), then the free list is consulted first. If not empty (hit), the block at the front of the free list is removed from the list and returned. Otherwise (miss), a new block of max bytes is allocated, truncated to `n` bytes, and returned.
    Parameters:

    size_t `n` | number of bytes to allocate

    Returns:
    The allocated block, or null.

    Precondition If set at runtime, min and/or max must be initialized appropriately.

    Postcondition result.length == bytes || result is null

  bool `deallocate`(void[] `block`);
    If `block`.length is within [min, max] or if the free list is unchecked (minSize == 0 && maxSize == size_t.max), then inserts the block at the front of the free list. For all others, forwards to parent.deallocate if Parent.`deallocate` is defined.
    Parameters:

    void[] `block` | Block to deallocate.

    Precondition If set at runtime, min and/or max must be initialized appropriately. The block must have been allocated with this freelist, and no dynamic changing of min or max is allowed to occur between allocation and deallocation.

  bool `deallocateAll`();
    Defined only if ParentAllocator defines `deallocateAll`. If so, forwards to it and resets the freelist.
  void `minimize`();
    Nonstandard function that minimizes the memory usage of the freelist by freeing each element in turn. Defined only if ParentAllocator defines deallocate. FreeList!(0, unbounded) does not have this function.
struct `ContiguousFreeList`(ParentAllocator, size_t minSize, size_t maxSize = minSize);
  Free list built on top of exactly one contiguous block of memory. The block is assumed to have been allocated with ParentAllocator, and is released in `ContiguousFreeList`'s destructor (unless ParentAllocator is NullAllocator).
  `ContiguousFreeList` has most advantages of FreeList but fewer disadvantages. It has better cache locality because items are closer to one another. It imposes less fragmentation on its parent allocator.
  The disadvantages of `ContiguousFreeList` over FreeList are its pay upfront model (as opposed to FreeList's pay-as-you-go approach), and a hard limit on the number of nodes in the list. Thus, a large number of long- lived objects may occupy the entire block, making it unavailable for serving allocations from the free list. However, an absolute cap on the free list size may be beneficial.
  The options minSize == unbounded and maxSize == unbounded are not available for `ContiguousFreeList`.
  Examples:

      import std.experimental.allocator.building_blocks.allocator_list
          : AllocatorList;
      import std.experimental.allocator.gc_allocator : GCAllocator;

      import std.experimental.allocator.common : unbounded;

      alias ScalableFreeList = AllocatorList!((n) =>
          ContiguousFreeList!(GCAllocator, 0, unbounded)(4096)
      );

  SParent `parent`;
    The parent allocator. Depending on whether ParentAllocator holds state or not, this is a member variable or an alias for ParentAllocator.instance.
  enum uint `alignment`;
    Alignment offered.
  this(ubyte[] `buffer`);
  this(ParentAllocator `parent`, ubyte[] `buffer`);
  this(size_t `bytes`);
  this(ParentAllocator `parent`, size_t `bytes`);
  this(size_t `bytes`, size_t `max`);
  this(ParentAllocator `parent`, size_t `bytes`, size_t `max`);
  this(size_t `bytes`, size_t `min`, size_t `max`);
  this(ParentAllocator `parent`, size_t `bytes`, size_t `min`, size_t `max`);
    Constructors setting up the memory structured as a free list.
    Parameters:

    ubyte[] `buffer` | Buffer to structure as a free list. If ParentAllocator is not NullAllocator, the buffer is assumed to be allocated by `parent` and will be freed in the destructor.
    ParentAllocator `parent` | Parent allocator. For construction from stateless allocators, use their instance static member.
    size_t `bytes` | Bytes (not items) to be allocated for the free list. Memory will be allocated during construction and deallocated in the destructor.
    size_t `max` | Maximum size eligible for freelisting. Construction with this parameter is defined only if maxSize == chooseAtRuntime or maxSize == unbounded.
    size_t `min` | Minimum size eligible for freelisting. Construction with this parameter is defined only if minSize == chooseAtRuntime. If this condition is met and no `min` parameter is present, `min` is initialized with `max`.

  size_t `goodAllocSize`(size_t `n`);
    If `n` is eligible for freelisting, returns max. Otherwise, returns parent.`goodAllocSize`(`n`).

    Precondition If set at runtime, min and/or max must be initialized appropriately.

    Postcondition result >= bytes

  void[] `allocate`(size_t `n`);
    Allocate `n` bytes of memory. If `n` is eligible for freelist and the freelist is not empty, pops the memory off the free list. In all other cases, uses the parent allocator.
  Ternary `owns`(void[] `b`);
    Defined if ParentAllocator defines it. Checks whether the block belongs to this allocator.
  bool `deallocate`(void[] `b`);
    Deallocates `b`. If it's of eligible size, it's put on the free list. Otherwise, it's returned to parent.

    Precondition `b` has been allocated with this allocator, or is null.

  bool `deallocateAll`();
    Deallocates everything from the parent.
  Ternary `empty`();
    Returns Ternary.yes if no memory is currently allocated with this allocator, Ternary.no otherwise. This method never returns Ternary.unknown.
struct `SharedFreeList`(ParentAllocator, size_t minSize, size_t maxSize = minSize, size_t approxMaxNodes = unbounded);
  FreeList shared across threads. Allocation and deallocation are lock-free. The parameters have the same semantics as for FreeList.
  expand is defined to forward to ParentAllocator.expand (it must be also shared).
  Examples:

      import std.experimental.allocator.common : chooseAtRuntime;
      import std.experimental.allocator.mallocator : Mallocator;

      shared SharedFreeList!(Mallocator, chooseAtRuntime, chooseAtRuntime) a;
      a.setBounds(64, 128);
      writeln(a.max); // 128
      writeln(a.min); // 64

  Examples:

      import std.experimental.allocator.common : chooseAtRuntime;
      import std.experimental.allocator.mallocator : Mallocator;

      shared SharedFreeList!(Mallocator, 50, 50, chooseAtRuntime) a;
      // Set the maxSize first so setting the minSize doesn't throw
      a.approxMaxLength = 128;
      writeln(a.approxMaxLength); // 128
      a.approxMaxLength = 1024;
      writeln(a.approxMaxLength); // 1024
      a.approxMaxLength = 1;
      writeln(a.approxMaxLength); // 1

  @property size_t `min`();
  @property void `min`(size_t `newMinSize`);
  @property size_t `max`();
  @property void `max`(size_t `newMaxSize`);
  void `setBounds`(size_t `newMin`, size_t `newMax`);
    Properties for getting (and possibly setting) the bounds. Setting bounds is allowed only once , and before any allocation takes place. Otherwise, the primitives have the same semantics as those of FreeList.
  shared const @property size_t `approxMaxLength`();
  shared @property void `approxMaxLength`(size_t `x`);
    Properties for getting (and possibly setting) the approximate maximum length of a shared freelist.
  shared ParentAllocator `parent`;
    The parent allocator. Depending on whether ParentAllocator holds state or not, this is a member variable or an alias for ParentAllocator.instance.
  enum uint `alignment`;
  shared size_t `goodAllocSize`(size_t `bytes`);
  shared const Ternary `owns`(const void[] `b`);
  shared bool `reallocate`(ref void[] `b`, size_t `s`);
  shared void[] `allocate`(size_t `bytes`);
  shared bool `deallocate`(void[] `b`);
  shared bool `deallocateAll`();
    Standard primitives.
  shared void `minimize`();
    Nonstandard function that minimizes the memory usage of the freelist by freeing each element in turn. Defined only if ParentAllocator defines deallocate.

Copyright © 1999-2023 by the D Language Foundation | Page generated by Ddoc on Wed Feb 1 17:27:35 2023