У меня есть древнее приложение C ++, изначально построенное на Visual C ++ 6.0, которое использует очень сложную DLL-библиотеку разделяемой памяти для обмена данными между примерно 8 EXE-файлами и DLL, которые имеют пул значений, которые можно заменить одним или двумя словарями со строками для ключи и записи для значений. Приложение является многопоточным и многопроцессным. Существует три основных исполняемых файла, которые читают и записывают в область общей памяти, а некоторые из исполняемых файлов имеют 3 или более потоков, которые читают / пишут или «ставят в очередь» информацию в эту область объединенной памяти. Около нескольких сотен мест, Структурная обработка исключений (SEH) __try
а также __except
используется для фильтрации исключений и для обработки нарушений доступа путем изменения размера разделяемой памяти, которые находятся в сегментах, управляемых классом с именем CGMMF
что означает растущий файл с отображенной памятью.
Наиболее важные детали показаны здесь, потому что я не могу найти никакого связного источника документации по используемой технике или ее безопасности и пригодности. Экспериментально я обнаружил, что эта библиотека не очень хорошо работала в одноядерной системе в 1998 году, она работает в некоторой степени на одноядерной виртуальной машине под управлением Windows XP, и что она совсем не работает на современной мультиформатной системе 2+ ГГц Windows 7 64-разрядных систем в 2013 году. Я пытаюсь восстановить или заменить его.
#define ResAddrSpace(pvAddress, dwSize) \
(m_hFileMapRes = CreateFileMapping(HFILE_PAGEFILE, &m_SecAttr, \
PAGE_READWRITE| SEC_RESERVE, 0, dwSize, m_szRegionName), \
(m_hFileMapRes == NULL) ? NULL : \
MapViewOfFileEx(m_hFileMapRes, FILE_MAP_ALL_ACCESS, 0, 0, dwSize, 0))void CGmmf::Create(void)
{
DWORD dwMaxRgnSize;
if (Gsinf.dwAllocationGranularity == 0)
{
GetSystemInfo(&Gsinf);
}
m_dwFileSizeMax = RoundUp(m_dwFileSizeMax, Gsinf.dwAllocationGranularity);
m_dwFileGrowInc = RoundUp(m_dwFileGrowInc, Gsinf.dwAllocationGranularity);
dwMaxRgnSize = m_dwFileSizeMax + m_dwOverrunBuf;
m_pbFile = (PBYTE)ResAddrSpace(NULL, dwMaxRgnSize);
Adjust(m_dwFileSizeNow);
}
void CGmmf::Adjust(IN DWORD dwDiskFileNow)
{
int nThreadPriority;
__try
{
//
// Boost our thread's priority so that another thread is
// less likely to use the same address space while
// we're changing it.
//
nThreadPriority = GetThreadPriority(GetCurrentThread());
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
//
// Restore the contents with the properly adjusted lengths
//
Construct(dwDiskFileNow);
}
__finally
{
//
// Make sure that we always restore our priority class and thread
// priority so that we do not continue to adversely affect other
// threads in the system.
//
SetThreadPriority(GetCurrentThread(), nThreadPriority);
}
}void CGmmf::Construct(IN DWORD dwDiskFileNow)
{
DWORD dwDiskFileNew = RoundUp(dwDiskFileNow, m_dwFileGrowInc),
dwStatus = ERROR_SUCCESS;
PBYTE pbTemp;
if (dwDiskFileNew > 0)
{
//
// Grow the MMF by creating a new file-mapping object.
//
// use VirtualAlloc() here to commit
// the requested memory: VirtualAlloc will not fail
// even if the memory block is already committed:
pbTemp = (PBYTE)VirtualAlloc(m_pbFile,dwDiskFileNew,MEM_COMMIT,PAGE_READWRITE);
if(NULL == pbTemp)
{
LogError(GetLastError(), MEM_CREATE_MMF, m_szRegionName);
//
// File-mapping could not be created, the disk is
// probably full.
//
RaiseException(EXCEPTION_GMMF_DISKFULL,
EXCEPTION_NONCONTINUABLE,
0,
NULL);
}
//
// Check to see if our region has been corrupted
// by another thread.
//
if (pbTemp != m_pbFile)
{
RaiseException(EXCEPTION_GMMF_CORRUPTEDRGN,
EXCEPTION_NONCONTINUABLE,
0,
NULL);
}
}
}
Пока что я могу заменить его, пытаясь заменить всю разделяемую память DCOM
(вне процесса COM) и COM
(в процессе COM), в зависимости от того, где находятся файлы, сопоставленные с памятью, и для защиты от проблем параллелизма вручную, используя синхронизацию / мьютекс / критический раздел или другие поточно-безопасные конструкции, в зависимости от ситуации.
Я хочу знать, есть ли уже какой-нибудь потокобезопасный тип словаря памяти, на который я мог бы заменить все это. Даже в приведенном выше фрагменте кода, который составляет менее 1% кода этой древней библиотеки совместно используемой памяти для визуального C ++ — 6, есть вещи, которые заставляют меня содрогнуться. Например, повышение приоритета потока в качестве стратегии, позволяющей избежать взаимоблокировок, условий гонки и общей коррупции. Возможно, из-за этого код перестал очень сильно зависать на 80486 процессоре с частотой 33 МГц. Shudder.
У меня есть код, который строит и работает в Visual C ++ 6.0, а также его ветвь работает в Visual C ++ 2008, и я, вероятно, смогу запустить его в Visual C ++ 2010. Что я мог бы использовать, чтобы дать мне словарную семантику, разделяемую память между процессами , а стабильно и надежно?
Обновить Под словарем я подразумеваю тип данных словаря, известный в Python, который в некоторых местах также называется «хранилищем ключей / значений», а в других (например, в стандартной библиотеке C ++) он известен как std::map
, Повысить документацию, которая обсуждает это Вот.
Похоже, вы должны взглянуть на Boost Interprocess. Вы можете использовать его, чтобы иметь std::map
-подобные объекты в общей памяти и многое другое. Прошло много лет с тех пор, как я использовал его в прошлый раз, поэтому не могу вдаваться в подробности, но документация к библиотеке хороша и содержит множество примеров, она должна помочь вам за 30 минут.
Других решений пока нет …