Контейнеры STL в разделяемой памяти (Windows)

Я работаю над приложением, которое состоит из 2 процессов, которые должны совместно использовать некоторые структуры данных. Эти классы организованы в разных библиотеках, а библиотеки используются в разных приложениях.

  • Моя первая попытка была использовать Именованная общая память в Win32, но проблема в том, что я не могу использовать контейнеры STL.
  • В поисках решения я нашел Boost Interprocess и, если я понимаю, я должен изменить все контейнеры STL в моих классах на контейнеры Boost Interprocess «STL».

Итак, есть ли какой-либо другой метод для обмена классами или структурами с использованием STL (в Windows)? Цель состоит в том, чтобы не создавать слишком большую зависимость от Boost в наших библиотеках.

Спасибо

3

Решение

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

Контейнерные классы Boost.Interprocess являются полностью совместимыми реализациями стандартных контейнеров, поэтому вы можете использовать их в качестве вставных замен для стандартных контейнеров и переключаться на предоставленные поставщиком контейнеры, когда они зафиксированы для поддержки стандартного протокола распределителя.

Я не уверен, могу ли я объяснить это лучше, чем документация, но самая большая проблема заключается в том, что разделяемая память отображается в разные процессы по разным виртуальным адресам, поэтому любые указатели, используемые в контейнере должен быть родственник указатель (например, с начала сегмента). Стандартная модель распределителя поддерживает это, но контейнер должен также поддерживать это, используя Allocator::pointer вместо T *, Когда все реализации исправлены для поддержки этого, контейнеры Boost.Interprocess больше не будут нужны.

Или вы может быть в состоянии отобразить память по одному и тому же виртуальному адресу в каждом процессе; если вы сделаете это, то можете использовать контейнеры вашей существующей реализации, так как необработанные указатели будут работать правильно.

7

Другие решения

Лично я бы избегал подхода с общей структурой. Альтернативой может стать передача структуры одному из двух процессов. Другой процесс получит к нему доступ, отправив сообщения первому процессу.

Если вы абсолютно настроены на использование разделяемой памяти, то вы наверняка можете использовать ее с STL. Сначала вам нужно будет создать собственный распределитель для ваших контейнеров. Распределитель будет выделять память из блока общей памяти. Кроме того, поскольку контейнеры STL не являются потокобезопасными, вам придется написать синхронизированную оболочку для контейнеров, используя именованный мьютекс.

1

Реальная проблема с использованием совместимых со стандартами коллекций STL с boost :: interprocess заключается в том, что стандарт явно позволяет коллекциям предполагать, что распределители одного и того же типа эквивалентны, что распределителям не требуется сохраненное состояние и что тип указателя можно игнорировать и T * может использоваться вместо.

Документация boost :: interprocess объясняет это лучше, чем я, но мое резюме таково:

  • Стандарт C ++ допускает размещение без сохранения состояния или с сохранением состояния
  • Стандарт C ++ позволяет использовать T * для указателей, даже если распределитель указывает другой тип
  • boost :: interprocess ТРЕБУЕТ поддержки поддержки распределителя состояний (чтобы сегмент памяти-владелец мог использоваться во всех распределениях)
  • для большинства применений boost :: interprocess использует альтернативные типы указателей — для нетривиальных приложений это будет offset_ptr
  • коллекции boost :: interprocess — map / vector / etc — (в настоящее время это typedefs типов boost :: container) предоставляют все эти дополнительные подробности реализации, которые требуются для boost :: interprocess

Таким образом, даже если ваши текущие коллекции STL поддерживают требования boost :: interprocess, и, вероятно, они этого не делают, НЕТ гарантии, предоставляемой стандартом C ++, что они будут продолжать обеспечивать эти требования в будущем. Единственный разумный подход к коллекциям, используемым в приложении boost :: interprocess, — это использовать коллекции boost, которые гарантируют соответствие требованиям boost: interprocess — либо из boost :: container, либо boost: interprocess: collection

1