终极共享内存:一个灵活的进程间内存共享类






4.81/5 (22投票s)
一个灵活的内存共享类,可在进程和线程之间共享,并支持锁定
- GitHub: 这是我多线程工具的一部分:https://github.com/WindowsNT/mt
引言
这是一个用于在 Windows 中跨线程或进程共享内存的模板类。它提供锁定机制、通知等等!
Using the Code
类的实例化
// usm(const wchar_t* string_id = 0,bool Init = false,size_t csz = 1048576,DWORD MaxTh = 100)
usm<char> sm(L"{4BF41A4E-ACF9-4E1D-A479-14DE9FF83BC2}",false,1000,100);
string_id
是一个string
,它唯一地标识此共享内存的内核对象。所有使用相同string_id
的usm
实例都在访问相同的内存。建议使用CLSID
值以避免与其他使用usm
的应用程序可能发生的冲突。
如果您传递0
,则对象保持未初始化状态。要初始化该对象,您必须调用CreateInit
,它采用与构造函数相同的参数。Init
指定对象的初始化是否必须包含在构造函数中。如果此值为true
并且发生错误,则构造函数将引发异常。csz
指定要分配的项目数。在上面的示例中,总内存分配为csz*sizeof(char)
。MaxTh
是将访问共享内存的最大线程数。在共享相同 string_id 的类的任何实例中,此数字必须相同,否则会发生内存损坏。
该库分配内存来存储每个线程的事件,因此在使用相同内存(即,相同的 string_id
)的类的所有实例中,MaxTh
必须相同。
类的初始化
// int Initialize();
此函数创建同步所需的内核对象句柄。调用 End()
会销毁这些句柄。 Initialize()
成功时返回 1
,出错时返回 -1
。如果 Initialize()
失败,则 End()
会清理所有剩余句柄。该类的析构函数也调用 End()
。
如果另一个线程正在写入共享内存,则此函数会等到写入完成为止。
读取共享内存
// unsigned long long ReadData(T* b,size_t sz,size_t offset = 0,bool FailIfNotReady = false);
此函数(在内部调用 BeginRead()
和 EndRead()
)执行以下操作
- 如果
FailfNotReady
为true
并且任何写入线程尚未完成写入,则该函数立即返回-1
。如果FailIfNotReady
为false
,则该函数会等到任何写入线程完成写入为止。 - 将调用线程的当前状态标记为正在读取。这会强制任何写入线程等待直到读取完成为止。
- 读取数据。
- 将调用线程的状态标记为未读取。这允许任何写入线程恢复(只要没有更多的读取线程)。
- 返回与
sz
相同的值。
写入共享内存
// unsigned long long WriteData(const T* b,size_t sz,size_t offset = 0,bool FailIfNotReady = false);
此函数(在内部调用 BeginWrite()
和 EndWrite()
)执行以下操作
- 如果
FailfNotReady
为true
并且任何其他线程正在写入或读取,则该函数立即返回-1
。如果FailIfNotReady
为false
,则该函数会等到任何其他写入或读取线程完成为止。 - 将调用线程的当前状态标记为正在写入。这会强制任何其他线程(读取或写入)等待直到写入完成为止。这也会强制任何使用
Initialize()
初始化对象的线程等待。 - 写入数据。
- 将调用线程的状态标记为未写入。这允许任何其他写入或读取线程恢复。该函数还会设置一个事件,指示内存已被写入。
- 返回与
sz
相同的值。
如果您需要指向数据的指针,则可以调用 BeginRead()
(必须随后调用 EndRead()
)和 BeginWrite()
(必须随后调用 EndWrite()
)。
const T* BeginRead(bool FailOnNotReady = false);
void EndRead();
T* BeginWrite(bool FailOnNotReady = false);
void EndWrite();
Notifications
// DWORD NotifyOnRead(bool Wait);
// DWORD NotifyWrite(bool Wait);
- 如果您调用
NotifyOnRead
,并且此函数的Wait == false
,则该函数返回-1
如果函数失败-2
如果没有其他已注册的线程WAIT_TIMEOUT
如果任何线程仍在读取WAIT_OBJECT_0
或更大的值,如果任何读取线程已完成
- 如果您使用
Wait == true
调用NotifyOnRead
,则返回值相同,只是如果所有线程仍在读取,则该函数不会返回。
如果线程刚刚完成写入,则 NotifyOnWrite
返回 WAIT_OBJECT_0
(请注意,此事件是自动重置的)。如果线程未写入或仍在写入,则 NotifyOnWrite
要么返回 WAIT_TIMEOUT
(如果您使用 Wait == false
调用它),要么等待直到线程完成写入。
希望这个类对您有帮助。它对我来说已经非常有用了。
祝您好运!
历史
- 2014年11月2日 - 增加了稍后初始化的能力,并添加了复制构造函数和运算符
=
,以及增加了读/写函数的偏移量 - 2014年11月1日 - 首次发布