我有一个最初在Visual C ++ 6.0中构建的古老C ++应用程序,它使用一个非常复杂的共享内存DLL在大约8个EXE和DLL之间共享数据,这些EXE和DLL都有一个值可以被一个或两个词典替换的值池使用字符串键和值的记录。该应用程序是多线程和多进程的。有三个主要可执行文件读取和写入共享内存区域,并且几个可执行文件具有3个或更多个线程,这些线程将读取/写入或“排队”信息放入此池化内存区域。大约有几百个地方,__try
和__except
的结构化异常处理(SEH)用于过滤异常,并尝试通过调整共享内存的大小来处理访问冲突,这些内存位于由一个名为CGMMF
的类,表示可增长的内存映射文件。
这里显示了最突出的细节,因为我找不到有关所用技术的任何内容的有凝聚力的来源,或者它的安全性和适用性。实验上我发现这个库在1998年的单个核心系统上运行得不是很好,它在运行Windows XP的单核虚拟机上有所作为,并且它在现代2+ ghz multi上根本不起作用 - 2013年核心Windows 7 64位系统。我正在尝试修复或替换它。
#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)中的所有共享内存替换为适合内存映射的位置文件,并手动防止并发问题,使用同步/ mutex / criticalsection或其他线程安全结构。
我想知道是否已经有一些线程安全的内存字典类型我可以替换所有这些。即使在上面的片段中,这个片段不到这个古老的共享内存库 - 视觉 - C ++ - 6代码的1%,也有些东西让我不寒而栗。例如,提高线程优先级作为避免死锁,竞争条件和一般损坏的策略。也许曾经使得这个代码在33 mhz的80486 CPU上停止崩溃。 发抖。
我在Visual C ++ 6.0中构建并运行代码,并且它的一个分支在Visual C ++ 2008中运行,我可能会在Visual C ++ 2010中使用它。我可以使用哪些内容会给我字典语义,共享跨进程的内存,稳定可靠吗?
更新“字典”我指的是Python中已知的字典数据类型,在某些地方也被称为“键/值存储”,在其他地方(如在C ++标准库中) ),它被称为std::map
。讨论此问题的Boost文档是here.
答案 0 :(得分:1)
听起来你应该看看Boost Interprocess。您可以使用它来拥有std::map
- 像共享内存中的对象一样,还有更多。自从我上次使用它以来已经好几年了,所以不能详细介绍,但是图书馆文档很好,有很多例子,它可以让你在30分钟内完成。