** Non-Boost ** STL-распределитель для общей памяти

Из-за политики, в которой я работаю, я не могу использовать версию Boost новее 1.33.1 и не могу использовать версию GCC новее 4.1.2. Да, это фигня, но я ничего не могу с этим поделать. Boost 1.33.1 не содержит межпроцессную библиотеку.

Тем не менее, один из моих проектов требует размещения std::map (или, скорее, std::unordered_map) в разделяемой памяти. Он записывается/изменяется ОДИН РАЗ, когда процесс загружается одним процессом ("сервером") и читается многими другими процессами. Я не делал IPC с общей памятью раньше, так что это довольно новая для меня территория. Я взглянул на shmget() но shmget() что я не могу постоянно использовать один и тот же ключ разделяемой памяти для выделения (как я полагаю, будет необходимо с распределителями контейнеров STL).

Существуют ли другие NON-BOOST STL-распределители, которые используют разделяемую память?

РЕДАКТИРОВАТЬ: Это было сделано раньше. У доктора Доббса была статья о том, как это сделать, еще в 2003 году, и я начал использовать ее в качестве справочного материала. Однако списки кодов неполные и ссылки на них перенаправляют на основной сайт.

РЕДАКТИРОВАТЬ РЕДАКТИРОВАТЬ: Единственная причина, по которой я не просто переписываю Boost.Interprocess, заключается в количестве кода. Мне было просто интересно, есть ли что-то относительно короткое и сжатое специально для разделяемой памяти POSIX, которое я мог бы переписать с нуля, поскольку передача данных между сетями также подлежит многодневному процессу утверждения...

Ответ 1

Указатели не работают в разделяемой памяти, если вы не можете назначить общую память по фиксированному адресу (согласованному во всех процессах). Таким образом, вам нужны конкретные классы, которые будут либо смежными (без указателя), либо иметь смещение (а не указатель) в область памяти, в которой отображается общая память.

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

Как мы это делаем, есть структуры POD (*) (некоторые из них включают атрибуты char xxx[N]; для хранения строк). Если вы можете ограничить свои струны, вы будете золотыми. И что касается map: он неэффективен для хранения только для чтения = сортируемый массив работает лучше (ура для локальности памяти). Поэтому я бы посоветовал пойти на это так:

struct Key {
    enum { Size = 318 };
    char value[Size];
};

struct Value {
    enum { Size = 412 };
    enum K { Int, Long, String };
    K kind;
    union { int i; long l; char string[Size]; } value;
};

И тогда просто получим массив std::pair<Key, Value>, который вы сортируете (std::sort) и по которому вы используете std::lower_bound для поиска. Вам нужно написать оператор сравнения для ключа, очевидно:

bool operator<(Key const& left, Key const& right) {
    return memcmp(left.value, right.value, Key::Size) < 0;
}

И я согласен с тем, что трюк enum + union менее привлекателен (интерфейс мудрый), чем вариант ускорения... это вам, чтобы улучшить интерфейс.

(*) Собственно, чистый POD не нужен. Совершенно нормально иметь частные атрибуты, конструкторы и конструкторы копирования, например. Все, что необходимо, - это избегать косвенности (указатели).

Ответ 2

Простой обходной путь. Создайте свой собственный "libNotBoost v1.0" из Boost 1.51. Библиотека Boost позволяет это. Поскольку он больше не Boost, вы в порядке.