autumn-synchronized

Модуль ОСени для синхронизации исполнения методов желудей

Использование

Допустим в вашем желуде есть какой-то критичный участок кода, который не должен исполнятся параллельно, и вы хотите сделать его потокобезопасным

// МойЖелудь.os

Процедура МойВажныйКод() Экспорт
    // Потокоопасный код
КонецПроцедуры

Что-бы сделать его потокобезопасным нужно создавать Блокировку, корректно блокировать и разблокировать участки кода:

// МойЖелудь.os

Перем Блокировка;

Процедура МойВажныйКод() Экспорт

    Блокировка.Заблокировать();

    Попытка
        // Потокоопасный код
    Исключение
        Блокировка.Разблокировать();
        ВызватьИсключение ИнформацияОбОшибке().ПодробноеОписаниеОшибки();
    КонецПопытки;

    Блокировка.Разблокировать();

КонецПроцедуры

Блокировка = Новый БлокировкаРесурса();

И вот чтобы не писать весь этот бойлерплейт вам поможет данный модуль, нужно добавить всего лишь аннотацию Синхронизировано и ваш метод магическим образом становится потокобезопасным!

// МойЖелудь.os

&Синхронизировано
Процедура МойВажныйКод() Экспорт
    // Потокоопасный код
КонецПроцедуры

Объект синхронизации

По умолчанию синхронизация выполняется на самом желуде: все его методы с аннотацией Синхронизировано исполняются по очереди, а внешний код может встать в ту же очередь, заблокировав желудь:

Блокировка = Новый БлокировкаРесурса(МойЖелудь);

Чтобы синхронизировать методы разных желудей, передайте в аннотацию лямбда-выражение, которое вернёт общий объект синхронизации. Лямбда захватывает желудь, поэтому в ней доступны его поля, в том числе приватные, и экспортные методы:

// Отгрузка.os

&Пластилин
Перем Склад;

&Синхронизировано("() -> Склад")
Процедура Отгрузить() Экспорт
    // Код, работающий со складом
КонецПроцедуры

Все методы, синхронизированные на одном складе, в том числе в других желудях, исполняются по очереди.

Важно:
Лямбда вычисляется один раз при создании желудя, после внедрения полей с аннотацией Пластилин, но до ФинальныйШтрих. Она должна вернуть объект: строки, числа и другие примитивные значения для синхронизации не подходят. ЭтотОбъект внутри лямбды указывает на саму лямбду, а не на желудь; чтобы синхронизироваться на желуде, просто не передавайте лямбду.

Разработка

Установка зависимостей и прогон тестов (OneUnit):

opm install -l --dev
oscript_modules/bin/oneunit e