Idiomatic D. Использование атрибута @nogc [перевод]

В этот раз, в качестве идиом, будет описано использование атрибута функций @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);
}

Добавить комментарий