Я хочу добавить сетевой контроль нескольких параметров, используемых службой (daemon), запущенной в встроенной системе Linux. Там нет необходимости в процедурных вызовах, каждый параметр может быть опробован очень естественным образом. Общая память кажется хорошим способом сохранить сетевой код вне демона и ограничить общий доступ к тщательно контролируемому набору переменных.
Так как я не хочу, чтобы частичные записи вызывали видимость значений, которые никогда не были написаны, я думал об использовании std::atomic<bool>
и std::atomic<int>
. Однако я обеспокоен тем, что std::atomic<T>
может быть реализован таким образом, который работает только с потоками С++ 11, а не с несколькими процессами (возможно, даже с потоками ОС). В частности, если реализация использует любые структуры данных, хранящиеся вне блока разделяемой памяти, в многопроцессорном сценарии это не сработает.
Я вижу некоторые требования, которые предполагают, что std::atomic
не будет содержать встроенный объект блокировки или указатель на дополнительные данные:
Атомные интегральные специализации и специализация
atomic<bool>
должны иметь стандартную компоновку. Каждый из них имеет тривиальный конструктор по умолчанию и тривиальный деструктор. Каждый из них должен поддерживать синтаксис синтаксической инициализации.Должны быть частичные специализации указателя шаблона атомного класса. Эти специализации должны иметь стандартную компоновку, тривиальные конструкторы по умолчанию и тривиальные деструкторы. Каждый из них должен поддерживать синтаксис синтаксической инициализации.
Тривиальная конструкция и разрушение по умолчанию, как мне кажется, исключают связанные данные об объекте, независимо от того, хранятся они внутри объекта, через переменную-член указателя или через внешнее сопоставление.
Однако я не вижу ничего, что исключает реализацию из использования одного глобального мьютекса/критического раздела (или даже глобальной коллекции, если элементы коллекции не связаны с отдельными атомными объектами - что-то вроде строк схема кэширования может быть использована для уменьшения ложных конфликтов). Очевидно, что доступ к нескольким процессам завершился неудачей при реализации с использованием глобального мьютекса, поскольку пользователи будут иметь независимые мьютексы и фактически не синхронизируются друг с другом.
Является ли реализация atomic<T>
разрешена делать вещи, которые несовместимы с общей памятью между процессами, или есть другие правила, которые делают ее безопасной?
Я только заметил, что тривиальная конструкция по умолчанию оставляет объект в состоянии неготовности, и требуется вызов atomic_init
. И в стандарте упоминается инициализация замков. Если они хранятся внутри объекта (и динамическое распределение памяти кажется невозможным, поскольку деструктор остается тривиальным), то они будут разделяться между процессами. Но меня все еще беспокоит возможность глобального мьютекса.
В любом случае гарантирование одного вызова atomic_init
для каждой переменной в общей области кажется трудным... поэтому я полагаю, что мне нужно будет уклониться от атомных типов С++ 11.