[Trick] Упгрейд для синглтона
От: remark Россия http://www.1024cores.net/
Дата: 29.08.07 10:20
Оценка:
Вот подумалось.

Бывают сервисы (синглтоны), создание/разрушение которых контролируют вручную. Т.е. в коде инициализации/деинициализации приложения прописано что и в каком порядке создавать.

Бывают ленивые сервисы (синглтоны), которые создаются по первому требованию. Их традиционно сопутствует проблема защиты от многопоточного создания. На них либо можно вешать мьютексы (с некоторыми мьютексами возникает рекурсивная проблема их создания), либо использовать DCL, для элиминации цены на захват/освобождение мьютекса каждый раз.
Всё идеально, если такой синглтон гарантированно создавать в однопоточном окружении, тогда о синхронизации заботиться просто не надо. Но тут возникает одно НО. Надо гарантировать, что пользователь "дёрнет" этот синглтон в однопоточном окружении, т.е. во время создания глобальных объектов или в main() до запуска потоков. А если он этого не сделает, а будет его "дёргать" только из рабочих потоков?

Так вот, допустим есть такой h-ник с описанием сервиса:
// some_service.h

/** Интерфейс сервиса
 */
struct some_service
{
    void make_something() {}
};

/** Получение инстанса сервиса
 */
some_service& get_service();


Фишка в cpp с реализацией:
// some_service.cpp
some_service& get_service()
{
    static some_service instance;
    return instance;
}

static some_service& local = some_service(); // <-----------------


Теперь мы гарантируем, с одной стороны, что сервис будет создан по первому требованию, и с другой стороны, если первого требования не будет во время создания глобальных объектов, он всё равно будет создан во время создания глобальных объектов.

Имхо, такая схема практически идеально подходит для создания низкоуровневых, ни-от-чего-не-зависящих глобальных сервисов. Например, сервис конвертации utf-8 <-> ucs-2, которому надо инициализировать таблицу конвертации символов, или сервис подсчёта crc, которому надо инициализировать таблицу кодов, или простенький сервис логирования, которому надо открыть файл. А так же, кстати, все сервисы, которым надо создать мьютекс, в однопоточном окружении это пока можно сделать безопасно, и использовать мьютекс уже в многопоточном окружении.

С этим трюком такие сервисы можно делать ещё немного более инкапсулированными и готовыми для повторного использования.


Какие-нибудь мысли?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.