英語版
このページの英語版を見る

std.experimental.allocator

アロケータ用の高レベルインターフェース。バンドルされたデータの割り当て/作成 structclassを含むデータの一括割り当て/作成、破棄/割り当て解除を実装する、 また、アロケーションに関連する配列プリミティブも実装する。このモジュールは このモジュールは、アロケータを利用したり、そのドキュメントを作成したりするための入り口である。

概要

// Allocate an int, initialize it with 42
int* p = theAllocator.make!int(42);
assert(*p == 42);
// Destroy and deallocate it
theAllocator.dispose(p);

// Allocate using the global process allocator
p = processAllocator.make!int(100);
assert(*p == 100);
// Destroy and deallocate
processAllocator.dispose(p);
// Create an array of 50 doubles initialized to -1.0
double[] arr = theAllocator.makeArray!double(50, -1.0);
// Append two zeros to it
theAllocator.expandArray(arr, 2, 0.0);
// On second thought, take that back
theAllocator.shrinkArray(arr, 2);
// Destroy and deallocate
theAllocator.dispose(arr);

層構造

Dのアロケータは、実装とドキュメントの両面でレイヤー構造になっている:
  1. 高レベルの動的型付けレイヤー(このモジュールの後半で説明する)。 モジュールで後述する)。と呼ばれるインターフェイスで構成される。 IAllocatorと呼ばれるインターフェイスで構成されている。 と呼ばれるインターフェイスで構成される。インターフェース・プリミティブ自身は、割り当てられるオブジェクトの型には無頓着である。 void[]インターフェイス・プリミティブ自体は、アロケートされるオブジェクトの型には無頓着である。 を扱うだけである。インターフェイスが(型パラメタライズドではなく)ダイナミックである必然性がある。 各スレッドはデフォルトで使用する現在のアロケータを持つ。 型の変数 theAllocator型である。 IAllocator.プロセスは というグローバル・アロケータがある。 processAllocatorと呼ばれるグローバル・アロケータがある。 IAllocator.新しいスレッドが作成されると processAllocatorにコピーされる。 にコピーされる。 theAllocator.アプリケーションは、これらの 参照を指すオブジェクトを変更できる。デフォルトでは、アプリケーション起動時に processAllocator はDのガベージコレクションされたヒープを使用するオブジェクトを参照する。このレイヤーはまた のような高レベル関数を含む。 makedisposeなどの高レベル関数も含まれる。 などの高レベル関数も含まれる。この このレイヤーは、アロケーション・プリミティブをカジュアルに使う場合に必要なものだ。
  2. 中レベルの静的型付けレイヤーは、複数のアロケータをひとつにまとめるためのものだ。 を1つにまとめる。作成されるオブジェクトの"@型"のプロパティを使用して、アロケーション要求を、場合によっては特殊化されたアロケータにルーティングする。 にルーティングする。このレイヤーは比較的薄い。 モジュールで実装され、文書化されている。 std.experimental.allocator.typedモジュールに実装されている。このレイヤーは比較的薄く、モジュールに実装され文書化されている。 アロケータを使い分けることができる。 全体的なパフォーマンスが向上する。
  3. 高度に汎用的なヒープ・ビルディング・ブロックの低レベル・コレクションである。 レゴブロックのようなもので、アプリケーション固有のアロケータを組み立てるのに使うことができる。 本当のアロケーションの賢さはこのレベルで発揮される。このレイヤーは このレイヤーは、独自のアロケータを構成したい高度なアプリケーションにとって興味深いものだ。 これらのビルディング・ブロックの典型的な使い方をよく表しているのが、モジュールである。 std.experimental.allocator.showcaseである。 モジュールである。実装とドキュメントの入り口は である。 std.experimental.allocator.building_blocks.設計上 プリミティブと同じシグネチャを持つ。 IAllocatorプリミティブと同じシグネチャを持つが、ほとんどの部分はオプションであり、静的イントロスペクションによって駆動される。 によって駆動される。パラメータ化されたクラス CAllocatorImplは の実装に静的な低レベルアロケータをパッケージ化するための即時かつ有用な手段を提供する。 の実装にパッケージ化することができる。 IAllocator.
  4. Coreアロケータ・オブジェクトは、D'sガベージコレクション・ヒープとのインターフェイスを持つ。 (std.experimental.allocator.gc_allocator)、Cのmalloc ファミリー (std.experimental.allocator.mallocator)、OS (std.experimental.allocator.mmap_allocator).ほとんどのカスタム・アロケータは ほとんどのカスタム・アロケータは、最終的にこれらのコア・アロケータのいずれかからメモリを取得する。

慣用的な std.experimental.allocator

現時点では std.experimental.allocatorは、D言語の newの組み込み演算子とは統合されていない。 配列連結演算子など、メモリを確保するD言語の組み込み演算子とは統合されていない。つまり std.experimental.allocatorは オプトイン-アプリケーションが明示的に使用する必要がある。
動的に割り当てられたオブジェクトのカジュアルな生成と破棄には make, disposeおよび配列固有の関数" を使用する。 makeArray, expandArrayおよび shrinkArray.これらはデフォルトでDのガベージ・コレクト・ヒープを使用する。 が収集したヒープを使用するが、より良いコンフィギュレーション・オプションをアプリケーションに開放する。これらの これらのプリミティブは、theAllocator でも動作するが、ヒープ・ビルディング・ブロックを組み合わせて得られるアロケータでも動作する。 でも動作する。例えば、以下のようなものがある:
void fun(size_t n)
{
    // Use the current allocator
    int[] a1 = theAllocator.makeArray!int(n);
    scope(exit) theAllocator.dispose(a1);
    ...
}
代替のアロケータを試すには theAllocatorを設定する。 に設定する。例えば、多くの8バイト・オブジェクトを割り当てるアプリケーションを考えてみよう。 オブジェクトを多数割り当てるアプリケーションを考えてみよう。これらはデフォルトのアロケータではうまくサポートされていない。 フリー・リスト・アロケータを推奨する。 mainそのため、フリー・リスト・アロケータを使用することを推奨する:
void main()
{
    import std.experimental.allocator.building_blocks.free_list
        : FreeList;
    theAllocator = allocatorObject(FreeList!8());
    ...
}

IAllocator リファレンスを後で使うために保存する

他のグローバルリソースと同様に、theAllocatorprocessAllocator を頻繁に、そして気軽に設定すべきではない。特に 特に、あるアロケータでメモリを確保し、別のアロケータで メモリを解放すると、未定義の動作を引き起こす。 一般的に、これらの変数はアプリケーションの初期化段階で設定され、アプリケーションの間中、設定され続ける。 アプリケーションの最後まで続く。
これを避けるために、割り当てや再割り当て、割り当て解除を比較的頻繁に行う必要がある長寿命オブジェクトは、このような変数を使用しない方がよいだろう、 アロケーション、再アロケーション、デアロケーションを比較的頻繁に実行する必要がある長寿命オブジェクトは、これを避けるため への参照を保存しておくといいだろう。その場合 を使う代わりに、theAllocator 。 を使うことになる。例えば、ユーザー定義のハッシュ・テーブルを考えてみよう:
struct HashTable
{
    private IAllocator allocator;
    this(size_t buckets, IAllocator allocator = theAllocator) {
        this.allocator = allocator;
        ...
    }
    // Getter and setter
    IAllocator allocator() { return allocator; }
    void allocator(IAllocator a) { assert(empty); allocator = a; }
}
初期化後、HashTableallocatorオブジェクトを使用する。さらに HashTable.allocatorを別のアロケータを指すように設定することは合法でなければならない。 そうでなければ、オブジェクトは既存の状態をデアロケートすることができない。 そうでなければ、オブジェクトは既存の状態をデアロケートできない。

を使わずにアロケータを使うIAllocator

ヒープ・ビルディング・ブロックから組み立てられたアロケータは、ヒープ・ビルディング・ブロックを経由しなくても使える。 IAllocator を通す必要はない。アロケータはIAllocator と同じプリミティブを持っている。 で動作する。 make, makeArray, disposeなどで動作する。だから アロケータ・オブジェクトを適当に作り、適切に使用すれば十分なのだ:
void fun(size_t n)
{
    // Use a stack-installed allocator for up to 64KB
    StackFront!65536 myAllocator;
    int[] a2 = myAllocator.makeArray!int(n);
    scope(exit) myAllocator.dispose(a2);
    ...
}
この場合、myAllocatorIAllocator インターフェースには従わない。 プリミティブを実装しているので、ダック型付けによってmakeArray 。 型 "を使用する。
このセットアップで注意すべき重要な点は、静的に型付けされたアセンブルされたアロケータは、ダック型付けを経由するアロケータよりもほとんど常に高速であるということである。 を経由するアロケータよりも速いということだ。 IAllocator.重要な経験則は、「アセンブル・アロケータが先で、 に適応するのは後」である。 IAllocator 。優れたアロケータは、テンプレート・アセンブリによって複雑なロジックを実装している。 テンプレート・アセンブリによって複雑なロジックを実装し、IAllocator (通常は allocatorObject)でラップされるのは、クライアント・レベルで一度だけだ。

interface IAllocator;
動的アロケータ・インターフェース。アロケータを定義するコードは最終的にこのインターフェイスを実装する。 このインターフェイスを実装する。これは、様々なアロケータ実装をカプセル化するために統一された型が必要な場合に使用される。 これは、様々なアロケータ実装をカプセル化するために統一された型が必要な場合に使用されるべきである。
アロケータをこのレベルで合成することは推奨されない。 動的インターフェースの柔軟性に欠け、カスケードされた多重呼び出しによる非効率性があるためである。 による非効率性のためである。その代わり、アロケータは で定義されている std.experimental.allocator.building_blocks, で定義された静的インターフェースを使ってアロケータを構成し、構成された アロケータを IAllocator(に適合させる。 CAllocatorImplに適応させる。)
Ternary を返すメソッドは、成功するとTernary.yes を返す、 Ternary.no プリミティブがアロケータ・インスタンスに実装されていない場合はTernary.unknown を返す。 を返す。
abstract nothrow @property uint alignment();
提供されたアライメントを返す。
abstract nothrow size_t goodAllocSize(size_t s);
内部の断片化がゼロであることを保証するアロケーションサイズを返す。 を返す。
abstract nothrow void[] allocate(size_t, TypeInfo ti = null);
n バイトのメモリを割り当てる。
abstract nothrow void[] alignedAllocate(size_t n, uint a);
指定されたアラインメントで nバイトのメモリを指定されたアラインメントで割り当てる。 a.このプリミティブをサポートしていない このプリミティブをサポートしていない実装は、常にnull を返すべきである。
abstract nothrow void[] allocateAll();
このアロケータが利用可能なすべてのメモリを割り当てて返す。 このプリミティブをサポートしていない実装は、常に null.
abstract nothrow bool expand(ref void[], size_t);
メモリブロックをその場で展開し、成功すればtrue を返す。 このプリミティブをサポートしない実装は、常に以下を返すべきである。 false.
abstract nothrow bool reallocate(ref void[], size_t);
メモリ・ブロックの再割り当てを行う。
abstract nothrow bool alignedReallocate(ref void[] b, size_t size, uint alignment);
指定されたアラインメントでメモリブロックを再割り当てする。
abstract nothrow Ternary owns(void[] b);
Ternary.yes 指定されたアラインメントでメモリブロックを再割り当てする。 bアロケータが所有している場合はTernary.no を返し、アロケータが所有していない場合は を返す。 アロケータが所有していない場合は b所有者がわからない場合はTernary.unknown を返す。 を返す。このプリミティブをサポートしていない実装では をサポートしていない実装は、常にTernary.unknown を返すべきである。
abstract nothrow Ternary resolveInternalPointer(const void* p, ref void[] result);
割り当てられたフルブロックへの内部ポインタを解決する。このプリミティブをサポートしていない は常にTernary.unknown を返すべきである。
abstract nothrow bool deallocate(void[] b);
メモリブロックを解放する。このプリミティブをサポートしない実装は、常に を返すべきである。 プリミティブは常にfalse を返すべきである。アロケータが を呼び出すことである。 deallocate(null).
abstract nothrow bool deallocateAll();
を呼び出すことである。このプリミティブをサポートしていない実装は、常に を返すべきである。 をサポートしていない実装は、常にfalse を返すべきである。
abstract nothrow Ternary empty();
このアロケータから現在メモリが割り当てられていない場合はTernary.yes を返す。 Ternary.no を返す。 Ternary.unknown を返す。
abstract pure nothrow @nogc @safe void incRef();
このインターフェイスを実装する具象クラスの参照カウントを増やす。 インタフェースを実装する具象クラスの参照カウントを増やす。
ステートレスアロケータでは、これは何もしない。
abstract pure nothrow @nogc @safe bool decRef();
このインタフェースを実装する具象クラスの参照カウントを減少させる。 このインタフェースを実装する具象クラスの参照カウントを減少させる。 参照カウントが0 になると、オブジェクトは自己破壊する。
Returns:
true 参照カウントが と より大きい場合、オブジェクトは自滅する。 になると、 を返す。ステートレスアロケータでは、常に を返す。0 false 0 true
struct RCIAllocator;
動的アロケータ・インターフェースをラップする参照カウント構造体。 様々なアロケータ実装をカプセル化するために統一された型が必要な場合は、これを使うべきである。 これは、様々なアロケータ実装をカプセル化するために統一された型が必要な場合に使用されるべきである。
アロケータを定義するコードは、最終的に動的アロケータ・インターフェースを実装する。 IAllocator インターフェイスを実装する。 CAllocatorImplインターフェイスを実装し RCIAllocatorを構築する。
このレベルでは、アロケーターの合成は推奨されない。 動的インターフェイスの柔軟性の欠如と、カスケードされた多重呼び出しによる非効率性のためである。 による非効率性のためである。代わりに、アロケータは で定義された std.experimental.allocator.building_blocksで定義された静的インターフェースを使ってアロケータを合成し、合成された アロケータを RCIAllocator(に適合させる。 allocatorObjectに適応させる。)
interface ISharedAllocator;
動的共有アロケータ・インターフェース。スレッド間で共有可能なアロケータを定義するコードは を定義するコードは、最終的にこのインターフェイスを実装することになる。これは 様々なアロケータをカプセル化するために統一された型が必要な場合に使用される。 の実装をカプセル化するために統一された型が必要な場合に使用されるべきである。
アロケータをこのレベルで合成することは推奨されない。 動的インターフェースの柔軟性に欠け、カスケードされた多重呼び出しによる非効率性があるためだ。 による非効率性のためである。その代わり、アロケータは で定義されている std.experimental.allocator.building_blocks, で定義された静的インターフェースを使ってアロケータを構成し、構成された アロケータを ISharedAllocator(に適合させる。 CSharedAllocatorImplに適応させる。)
Ternary を返すメソッドは、成功するとTernary.yes を返す、 Ternary.no プリミティブがアロケータ・インスタンスに実装されていない場合はTernary.unknown を返す。 を返す。
abstract shared nothrow @property uint alignment();
提供されたアライメントを返す。
abstract shared nothrow size_t goodAllocSize(size_t s);
内部の断片化がゼロであることを保証するアロケーションサイズを返す。 を返す。
abstract shared nothrow void[] allocate(size_t, TypeInfo ti = null);
n バイトのメモリを割り当てる。
abstract shared nothrow void[] alignedAllocate(size_t n, uint a);
指定されたアラインメントで nバイトのメモリを指定されたアラインメントで割り当てる。 a.このプリミティブをサポートしていない このプリミティブをサポートしていない実装は、常にnull を返すべきである。
abstract shared nothrow void[] allocateAll();
このアロケータが利用可能なすべてのメモリを割り当てて返す。 このプリミティブをサポートしていない実装は、常に null.
abstract shared nothrow bool expand(ref void[], size_t);
メモリブロックをその場で展開し、成功すればtrue を返す。 このプリミティブをサポートしない実装は、常に以下を返すべきである。 false.
abstract shared nothrow bool reallocate(ref void[], size_t);
メモリ・ブロックの再割り当てを行う。
abstract shared nothrow bool alignedReallocate(ref void[] b, size_t size, uint alignment);
指定されたアラインメントでメモリブロックを再割り当てする。
abstract shared nothrow Ternary owns(void[] b);
Ternary.yes 指定されたアラインメントでメモリブロックを再割り当てする。 bアロケータが所有している場合はTernary.no を返し、アロケータが所有していない場合は を返す。 アロケータが所有していない場合は b所有者がわからない場合はTernary.unknown を返す。 を返す。このプリミティブをサポートしていない実装では をサポートしていない実装は、常にTernary.unknown を返すべきである。
abstract shared nothrow Ternary resolveInternalPointer(const void* p, ref void[] result);
割り当てられたフルブロックへの内部ポインタを解決する。このプリミティブをサポートしていない は常にTernary.unknown を返すべきである。
abstract shared nothrow bool deallocate(void[] b);
メモリブロックを解放する。このプリミティブをサポートしない実装は、常に を返すべきである。 プリミティブは常にfalse を返すべきである。アロケータが を呼び出すことである。 deallocate(null).
abstract shared nothrow bool deallocateAll();
を呼び出すことである。このプリミティブをサポートしていない実装は、常に を返すべきである。 をサポートしていない実装は、常にfalse を返すべきである。
abstract shared nothrow Ternary empty();
このアロケータから現在メモリが割り当てられていない場合はTernary.yes を返す。 Ternary.no を返す。 Ternary.unknown を返す。
abstract shared pure nothrow @nogc @safe void incRef();
このインターフェイスを実装する具象クラスの参照カウントを増やす。 インタフェースを実装する具象クラスの参照カウントを増やす。
ステートレスアロケータでは、これは何もしない。
abstract shared pure nothrow @nogc @safe bool decRef();
このインタフェースを実装する具象クラスの参照カウントを減少させる。 このインタフェースを実装する具象クラスの参照カウントを減少させる。 参照カウントが0 になると、オブジェクトは自己破壊する。
ステートレスアロケータでは、これは何もしない。
Returns:
true 参照カウントが および より大きい場合、 にぶつかる。 に当たった場合、 を返す。ステートレスアロケータでは、常に を返す。0 false 0 true
struct RCISharedAllocator;
動的共有アロケータ・インターフェースをラップする参照カウント構造体。 様々なアロケータ実装をカプセル化するために統一された型が必要な場合は、これを使うべきである。 これは、様々なアロケータ実装をカプセル化するために統一された型が必要な場合に使用されるべきである。
スレッド間で共有可能なアロケータを定義するコードは、最終的に、動的共有アロケータ・インターフェイスの ISharedAllocatorインターフェイスを実装する。 CSharedAllocatorImplインターフェイスを実装し RCISharedAllocatorを構築する。 を構築する。
このレベルでは、アロケーターの合成は推奨されない。 動的インターフェイスの柔軟性の欠如と、カスケードされた多重呼び出しによる非効率性のためである。 による非効率性のためである。代わりに、アロケータは で定義されている std.experimental.allocator.building_blocksで定義された静的インターフェースを使ってアロケータを合成し、合成されたアロケータを を RCISharedAllocator(に適合させる。 sharedAllocatorObjectに適応させる。)
nothrow @nogc @property ref @safe RCIAllocator theAllocator();

nothrow @nogc @property @system void theAllocator(RCIAllocator a);
現在のスレッドのアロケータを取得/設定する。これはデフォルトのアロケータである。 で、スレッドローカルメモリの割り当てに使われる。スレッド間で共有される を割り当てる場合は、processAllocator (下記)を使用する。デフォルトでは theAllocatorprocessAllocatorからメモリをフェッチする。 を使用する。
Examples:
// Install a new allocator that is faster for 128-byte allocations.
import std.experimental.allocator.building_blocks.free_list : FreeList;
import std.experimental.allocator.gc_allocator : GCAllocator;
auto oldAllocator = theAllocator;
scope(exit) theAllocator = oldAllocator;
theAllocator = allocatorObject(FreeList!(GCAllocator, 128)());
// Use the now changed allocator to allocate an array
const ubyte[] arr = theAllocator.makeArray!ubyte(128);
assert(arr.ptr);
//...
nothrow @nogc @property ref @trusted RCISharedAllocator processAllocator();

nothrow @nogc @property @system void processAllocator(ref RCISharedAllocator a);
現在のプロセスのアロケータを取得/設定する。このアロケータは を使わなければならない。この オブジェクトはshared にキャストできる。
auto make(T, Allocator, A...)(auto ref Allocator alloc, auto ref A args);
を使用して)動的にアロケートする。 allocを使用して) 動的に割り当て、割り当てられたメモリに を使用してT 型のオブジェクトを作成する。 args(を使用する。 を使って初期化する。初期化は割り当てられたメモリ内で行われ、それ以外は と意味的には同じである。 T(args). (と同じである。 alloc.make!(T[])を使うと、配列ではなく(空の)配列へのポインタが作成されることに注意されたい)。 Tへのポインタを作成することに注意。アロケータを使って を使う。 alloc.makeArray!Tを使う。)
Parameters:
T 作成されるオブジェクトの型。
Allocator alloc 必要なメモリを確保するためのアロケータ。これは、アロケータ用の静的インターフェイスを実装した アロケータ用の静的インターフェイスを実装したオブジェクト、あるいはIAllocator 参照である。
A args 作成されたオブジェクトの初期化に使われるオプションの引数。もし 存在しない場合、オブジェクトはデフォルトで構築される。
Returns:
T がクラス型の場合、作成されたオブジェクトへの参照を返す。T オブジェクトへの参照を返す。そうでない場合は、作成されたオブジェクトを指すT* を返す。すべての場合において 割り当てに失敗した場合は、null を返す。
Throws:
T のコンストラクタがスローした場合、割り当てられたメモリを解放し、例外を伝搬する。 例外を伝播する。
Examples:
// Dynamically allocate one integer
const int* p1 = theAllocator.make!int;
// It's implicitly initialized with its .init value
writeln(*p1); // 0
// Dynamically allocate one double, initialize to 42.5
const double* p2 = theAllocator.make!double(42.5);
writeln(*p2); // 42.5

// Dynamically allocate a struct
static struct Point
{
    int x, y, z;
}
// Use the generated constructor taking field values in order
const Point* p = theAllocator.make!Point(1, 2);
assert(p.x == 1 && p.y == 2 && p.z == 0);

// Dynamically allocate a class object
static class Customer
{
    uint id = uint.max;
    this() {}
    this(uint id) { this.id = id; }
    // ...
}
Customer cust = theAllocator.make!Customer;
assert(cust.id == uint.max); // default initialized
cust = theAllocator.make!Customer(42);
writeln(cust.id); // 42

// explicit passing of outer pointer
static class Outer
{
    int x = 3;
    class Inner
    {
        auto getX() { return x; }
    }
}
auto outer = theAllocator.make!Outer();
auto inner = theAllocator.make!(Outer.Inner)(outer);
writeln(outer.x); // inner.getX
T[] makeArray(T, Allocator)(auto ref Allocator alloc, size_t length);

T[] makeArray(T, Allocator)(auto ref Allocator alloc, size_t length, T init);

Unqual!(ElementEncodingType!R)[] makeArray(Allocator, R)(auto ref Allocator alloc, R range)
if (isInputRange!R && !isInfinite!R);

T[] makeArray(T, Allocator, R)(auto ref Allocator alloc, R range)
if (isInputRange!R && !isInfinite!R);
要素を持つT の配列を作成する。 length要素の配列を作成する。 alloc.配列は、デフォルトで初期化されるか、あるいは initから取得した値で初期化される。 range.
Parameters:
T 作成される配列の要素型。
Allocator alloc メモリの確保に使われるアロケータ
size_t length 新しく作成される配列の長さ
T init 配列を埋めるために使われる要素
R range 配列要素の初期化に使われる範囲
Returns:
null 新しく作成された配列。 length0 、あるいは 割り当てに失敗した場合は
Throws:
最初の2つのオーバーロードは、以下の場合にのみスローする。 allocをスローする。最初の2つのオーバーロードは コピー初期化を含むオーバーロードは、メモリを解放し、コピー操作がスローした場合に例外を伝播する。 例外を伝播する。
Examples:
import std.algorithm.comparison : equal;
static void test(T)()
{
    T[] a = theAllocator.makeArray!T(2);
    assert(a.equal([0, 0]));
    a = theAllocator.makeArray!T(3, 42);
    assert(a.equal([42, 42, 42]));
    import std.range : only;
    a = theAllocator.makeArray!T(only(42, 43, 44));
    assert(a.equal([42, 43, 44]));
}
test!int();
test!(shared int)();
test!(const int)();
test!(immutable int)();
bool expandArray(T, Allocator)(auto ref Allocator alloc, ref T[] array, size_t delta);

bool expandArray(T, Allocator)(auto ref Allocator alloc, ref T[] array, size_t delta, auto ref T init);

bool expandArray(T, Allocator, R)(auto ref Allocator alloc, ref T[] array, R range)
if (isInputRange!R);
成長する arrayより多くの要素を追加することで delta要素が追加される。必要なメモリは を使用して割り当てられる。 alloc.追加された要素は、デフォルトの のコピーで満たされるか initのコピーで埋められるか、次の値で初期化される。 から取得した値で初期化される。 range.
Parameters:
T 作成される配列の要素型
Allocator alloc メモリの確保に使われるアロケータ
T[] array 増やされる配列への参照
size_t delta 追加する要素数(成功すると、新しい長さの arrayである)。 array.length + delta)
T init 配列の要素を埋める
R range 配列要素の初期化に使用する範囲
Returns:
true 成功した場合は、 。後者の場合 後者の場合false arrayは影響を受けない。
Throws:
最初の2つのオーバーロードは、以下の場合にのみスローする。 allocをスローする。最初の2つのオーバーロードは コピー初期化を含むオーバーロードは、メモリを解放し、コピー操作がスローした場合に例外を伝播する。 例外を伝播する。
Examples:
auto arr = theAllocator.makeArray!int([1, 2, 3]);
assert(theAllocator.expandArray(arr, 2));
writeln(arr); // [1, 2, 3, 0, 0]
import std.range : only;
assert(theAllocator.expandArray(arr, only(4, 5)));
writeln(arr); // [1, 2, 3, 0, 0, 4, 5]
bool shrinkArray(T, Allocator)(auto ref Allocator alloc, ref T[] array, size_t delta);
要素分だけ配列を縮小する。 delta要素だけ縮小する。
array.length < delta の場合は何もせず、false を返す。そうでなければ 配列の最後のarray.length - delta 要素を破棄する。 配列のバッファを再割り当てする。再割り当てに失敗した場合は、デフォルトで初期化されたデータで配列を埋める。 で埋める。
Parameters:
T 作成される配列の要素型
Allocator alloc メモリの確保に使われるアロケータ
T[] array 縮小される配列への参照。
size_t delta 削除する要素数(成功すると、新しい長さの arrayarray.length - delta)
Returns:
true 成功時、メモリを再割り当てできなかった場合は となる。後者の場合 後者の場合、スライス はデフォルトで初期化された 要素が残る。 false array[$ - delta .. $]
Throws:
最初の2つのオーバーロードは、以下の場合にのみスローする。 allocをスローする。最初の2つのオーバーロードは コピー初期化を含むオーバーロードは、メモリを解放し、コピー操作がスローした場合に例外を伝播する。 例外を伝播する。
Examples:
int[] a = theAllocator.makeArray!int(100, 42);
writeln(a.length); // 100
assert(theAllocator.shrinkArray(a, 98));
writeln(a.length); // 2
writeln(a); // [42, 42]
void dispose(A, T)(auto ref A alloc, auto ref T* p);

void dispose(A, T)(auto ref A alloc, auto ref T p)
if (is(T == class) || is(T == interface));

void dispose(A, T)(auto ref A alloc, auto ref T[] array);
が指すオブジェクトを破壊し、その後(次のようにして)デアロケートする。 allocを使用して)オブジェクトを破壊し、その後デアロケートする。 ポインタが指すオブジェクト、class またはinterface 参照によって参照されるクラス・オブジェクト、または配列全体を破棄する。それぞれの実体は同じアロケータで割り当てられたものとする。 同じアロケータで割り当てられたものとする。
auto makeMultidimensionalArray(T, Allocator, size_t N)(auto ref Allocator alloc, size_t[N] lengths...);
T型の要素からなる多次元配列を確保する。
Parameters:
N 次元数
T 多次元配列の要素の型。
Allocator alloc メモリの確保に使用されるアロケータ
size_t[N] lengths 各次元のサイズを含む静的配列
Returns:
T型の要素を持つN次元配列。
Examples:
import std.experimental.allocator.mallocator : Mallocator;

auto mArray = Mallocator.instance.makeMultidimensionalArray!int(2, 3, 6);

// deallocate when exiting scope
scope(exit)
{
    Mallocator.instance.disposeMultidimensionalArray(mArray);
}

writeln(mArray.length); // 2
foreach (lvl2Array; mArray)
{
    writeln(lvl2Array.length); // 3
    foreach (lvl3Array; lvl2Array)
        writeln(lvl3Array.length); // 6
}
void disposeMultidimensionalArray(T, Allocator)(auto ref Allocator alloc, auto ref T[] array);
多次元配列がmakeMultidimensionalArrayで作成され、同じアロケータが使われたと仮定して、多次元配列を破棄し、その後デアロケートする。 makeMultidimensionalArrayで作成され、同じアロケータが使われたと仮定する。
Parameters:
T 多次元配列の要素の型。
Allocator alloc メモリの確保に使われたアロケータ
T[] array 解放される多次元配列。
Examples:
struct TestAllocator
{
    import std.experimental.allocator.common : platformAlignment;
    import std.experimental.allocator.mallocator : Mallocator;

    alias allocator = Mallocator.instance;

    private static struct ByteRange
    {
        void* ptr;
        size_t length;
    }

    private ByteRange[] _allocations;

    enum uint alignment = platformAlignment;

    void[] allocate(size_t numBytes)
    {
         auto ret = allocator.allocate(numBytes);
         _allocations ~= ByteRange(ret.ptr, ret.length);
         return ret;
    }

    bool deallocate(void[] bytes)
    {
        import std.algorithm.mutation : remove;
        import std.algorithm.searching : canFind;

        bool pred(ByteRange other)
        { return other.ptr == bytes.ptr && other.length == bytes.length; }

        assert(_allocations.canFind!pred);

         _allocations = _allocations.remove!pred;
         return allocator.deallocate(bytes);
    }

    ~this()
    {
        assert(!_allocations.length);
    }
}

TestAllocator allocator;

auto mArray = allocator.makeMultidimensionalArray!int(2, 3, 5, 6, 7, 2);

allocator.disposeMultidimensionalArray(mArray);
RCIAllocator allocatorObject(A)(auto ref A a)
if (!isPointer!A);

RCIAllocator allocatorObject(A)(A* pa);
与えられた静的型付けのアロケータを中心に構築された、動的型付けのCAllocator を返す。 型アロケータを中心に構築された動的に型付けされた aを中心に構築された動的型A を返す。アロケータへのポインタを渡すと へのポインタを渡すと、そのポインタが指すアロケータを中心に動的アロケータが作られる、 を作成する。アロケータを "値"または "参照"で渡すと、以下のように動作する。 参照でアロケータを渡すと、次のように動作する。
  • A "がステートを持っていない場合、結果のオブジェクトは静的共有ストレージに割り当てられる。 共有ストレージに割り当てられる。
  • A に状態がある場合、結果は std.algorithm.mutation.move 内のアロケータA a 。結果自体は、それ自身の静的に型付けされたアロケータ 自身の静的に型付けされたアロケータに割り当てられる。
Examples:
import std.experimental.allocator.mallocator : Mallocator;

RCIAllocator a = allocatorObject(Mallocator.instance);
auto b = a.allocate(100);
writeln(b.length); // 100
assert(a.deallocate(b));

// The in-situ region must be used by pointer
import std.experimental.allocator.building_blocks.region : InSituRegion;
auto r = InSituRegion!1024();
a = allocatorObject(&r);
b = a.allocate(200);
writeln(b.length); // 200
// In-situ regions can deallocate the last allocation
assert(a.deallocate(b));
nothrow RCISharedAllocator sharedAllocatorObject(A)(auto ref A a)
if (!isPointer!A);

RCISharedAllocator sharedAllocatorObject(A)(A* pa);
与えられた静的型付けのアロケータを中心に構築された、動的型付けのCSharedAllocator を返す。 型アロケータを中心に構築された動的に型付けされた aを中心に構築された動的型A を返す。アロケータへのポインタを渡すと へのポインタを渡すと、そのポインタが指すアロケータを中心に動的アロケータが作られる、 を作成する。アロケータを "値"または "参照"で渡すと、次のように動作する。 参照でアロケータを渡すと、次のように動作する。
  • A "がステートを持っていない場合、結果のオブジェクトは静的共有ストレージに割り当てられる。 共有ストレージに割り当てられる。
  • A 、状態がありコピー可能な場合、結果は以下のようになる。 std.algorithm.mutation.move内の提供されたアロケータA a 。 結果自身は、静的に型付けされたアロケータに割り当てられる。
  • A が状態を持ち、コピー可能でない場合、結果は渡された引数を結果の中に移動する。 渡された引数は結果の中に移動される。結果自体は、それ自身の に割り当てられる。
class CAllocatorImpl(Allocator, Flag!"indirect" indirect = No.indirect): IAllocator;
Allocator を使ったIAllocator の実装。これは 静的に構築されたアロケータ型をIAllocator に適応させる。 非テンプレート・コードで直接使用できる。
通常 CAllocatorImplを呼び出すことで間接的に使われる。 theAllocator.
pure @nogc ref @safe Allocator impl();
実装はパブリック・メンバーとして利用できる。
pure @nogc @safe this(Allocator* pa);
実装はパブリック・メンバーとして利用可能である。
@property uint alignment();
戻り値 impl.alignment.
size_t goodAllocSize(size_t s);
戻り値 impl.goodAllocSize(s).
void[] allocate(size_t s, TypeInfo ti = null);
戻り値 impl.allocate(s).
void[] alignedAllocate(size_t s, uint a);
を返す。 impl.alignedAllocateが存在すれば、それを呼び出して結果を返す。 そうでない場合は、常にnull を返す。
Ternary owns(void[] b);
もしAllocatorownsを実装していれば、それに転送する。そうでない場合は Ternary.unknown.
bool expand(ref void[] b, size_t s);
定義されていればimpl.expand(b, s) を返し、そうでなければfalse を返す。
bool reallocate(ref void[] b, size_t s);
impl.reallocate(b, s) を返す。
bool alignedReallocate(ref void[] b, size_t s, uint a);
に転送する。 impl.alignedReallocatefalse に転送する。
bool deallocate(void[] b);
もし impl.deallocateが定義されていない場合、false を返す。そうでない場合は に転送する。
bool deallocateAll();
を呼び出す。 impl.deallocateAll()を呼び出し、定義されていればその結果を返す、 そうでない場合はfalse を返す。
Ternary empty();
に転送する。 impl.empty()Ternary.unknownに転送する。
void[] allocateAll();
を返す。 impl.allocateAll()null を返す。
class CSharedAllocatorImpl(Allocator, Flag!"indirect" indirect = No.indirect): ISharedAllocator;
Allocator を使ったISharedAllocator の実装。これは 静的に構築され、スレッド間で共有可能なアロケータ型を、非テンプレーテッド・コードで直接使用できるISharedAllocator に適応させる。
通常 CSharedAllocatorImplを呼び出すことで間接的に使われる。 processAllocator.
shared pure @nogc ref @safe Allocator impl();
実装はパブリック・メンバーとして利用できる。
shared pure @nogc @safe this(Allocator* pa);
実装はパブリック・メンバーとして利用可能である。
shared @property uint alignment();
戻り値 impl.alignment.
shared size_t goodAllocSize(size_t s);
戻り値 impl.goodAllocSize(s).
shared void[] allocate(size_t s, TypeInfo ti = null);
戻り値 impl.allocate(s).
shared void[] alignedAllocate(size_t s, uint a);
を返す。 impl.alignedAllocateが存在すれば、それを呼び出して結果を返す。 そうでない場合は、常にnull を返す。
shared Ternary owns(void[] b);
もしAllocatorownsを実装していれば、それに転送する。そうでない場合は Ternary.unknown.
shared bool expand(ref void[] b, size_t s);
定義されていればimpl.expand(b, s) を返し、そうでなければfalse を返す。
shared bool reallocate(ref void[] b, size_t s);
impl.reallocate(b, s) を返す。
shared bool alignedReallocate(ref void[] b, size_t s, uint a);
に転送する。 impl.alignedReallocatefalse に転送する。
shared bool deallocate(void[] b);
もし impl.deallocateが定義されていない場合、false を返す。そうでない場合は に転送する。
shared bool deallocateAll();
を呼び出す。 impl.deallocateAll()を呼び出し、定義されていればその結果を返す、 そうでない場合はfalse を返す。
shared Ternary empty();
に転送する。 impl.empty()Ternary.unknownに転送する。
shared void[] allocateAll();
を返す。 impl.allocateAll()null を返す。
struct ThreadLocal(A);
スレッドローカルストレージにアロケータオブジェクトを格納する(つまり、shared Dではない)。 グローバル)に格納する。 ThreadLocal!AA のサブタイプである。 Aのアロケータ・プリミティブを実装しているように見える。
A 状態を保持しなければならない。 ThreadLocal!Aはインスタンス化を拒否する。これは というのは、例えば ThreadLocal!MallocatorMallocatorは動作しない。 の状態は、Mallocator のメンバとして格納されているのではなく、Cライブラリの実装に隠されているからだ。 Cライブラリの実装に隠されているからだ。
Examples:
import std.experimental.allocator.building_blocks.free_list : FreeList;
import std.experimental.allocator.gc_allocator : GCAllocator;
import std.experimental.allocator.mallocator : Mallocator;

static assert(!is(ThreadLocal!Mallocator));
static assert(!is(ThreadLocal!GCAllocator));
alias Allocator = ThreadLocal!(FreeList!(GCAllocator, 0, 8));
auto b = Allocator.instance.allocate(5);
static assert(__traits(hasMember, Allocator, "allocate"));
static A instance;
アロケータ・インスタンス。
this();
ThreadLocal はすべてのコンストラクタを無効にする。意図した使い方は .ThreadLocal!A.instance