В этот раз, в качестве идиом, будет описано использование атрибута функций @nogc, а также будет рассмотрен прием, с помощью которого можно обходить встроенный в язык сборщик мусора.
Атрибут функций @nogc говорит о том, что функция никогда не выделяет память с помощью сборщика мусора (GC):
void processStuff(double[] data) @nogc { double[] tempBuffer; // Ошибка ! Установка свойства length потенциально может использовать GC tempBuffer.length = data.length; ... }
Этот атрибут можно использовать для написания понятного кода работы с памятью, а также в потоках реального времени.
Однако, не все функции стандартной библиотеки помечены атрибутом @nogc, а вам может потребоваться в одной из точек программы вызвать функцию так, как будто бы она имеет такой атрибут.
Вот один из способов сделать это:
import std.traits; // Приведение функции или делегата к функции/делегату @nogc auto assumeNoGC(T) (T t) if (isFunctionPointer!T || isDelegate!T) { enum attrs = functionAttributes!T | FunctionAttribute.nogc; return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; } // функция, не являющаяся nogc-функцией void funcThatMightUseGC(int timeout) { if (unlikelyCondition(timeout)) throw new Exception("The world actually imploded."); doMoreStuff(); } // обходной маневр: и теперь можно использовать нашу функцию, так // как будто она с атрибутом @nogc void funcThatCantAffortGC() @nogc { // using a casted delegate literal to call non-@nogc code assumeNoGC( (int timeout) { funcThatMightUseGC(timeout); })(10000); }