- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有以下代码:
class TimeOutException
{};
template <typename T>
class MultiThreadedBuffer
{
public:
MultiThreadedBuffer()
{
InitializeCriticalSection(&m_csBuffer);
m_evtDataAvail = CreateEvent(NULL, TRUE, FALSE, NULL);
}
~MultiThreadedBuffer()
{
CloseHandle(m_evtDataAvail);
DeleteCriticalSection(&m_csBuffer);
}
void LockBuffer()
{
EnterCriticalSection(&m_csBuffer);
}
void UnlockBuffer()
{
LeaveCriticalSection(&m_csBuffer);
}
void Add(T val)
{
LockBuffer();
m_buffer.push_back(val);
SetEvent(m_evtDataAvail);
UnlockBuffer();
}
T Get(DWORD timeout)
{
T val;
if (WaitForSingleObject(m_evtDataAvail, timeout) == WAIT_OBJECT_0) {
LockBuffer();
if (!m_buffer.empty()) {
val = m_buffer.front();
m_buffer.pop_front();
}
if (m_buffer.empty()) {
ResetEvent(m_evtDataAvail);
}
UnlockBuffer();
} else {
throw TimeOutException();
}
return val;
}
bool IsDataAvail()
{
return (WaitForSingleObject(m_evtDataAvail, 0) == WAIT_OBJECT_0);
}
std::list<T> m_buffer;
CRITICAL_SECTION m_csBuffer;
HANDLE m_evtDataAvail;
};
单元测试表明,只要 T 的默认构造函数和复制/赋值运算符不抛出异常,此代码在单线程上使用时工作正常。因为我写的是 T,所以这是可以接受的。
我的问题是 Get 方法。如果没有可用数据(即未设置 m_evtDataAvail),则几个线程会阻塞 WaitForSingleObject 调用。当新数据可用时,它们都会进入 Lock() 调用。只有一个会通过并且可以取出数据并继续前进。在 Unlock() 之后,另一个线程可以继续前进,但会发现没有数据。目前它将返回默认对象。
我想要发生的是让第二个线程(和其他线程)返回到 WaitForSingleObject 调用。我可以添加一个解锁并执行 goto 的 else block ,但这感觉很糟糕。
该解决方案还增加了无限循环的可能性,因为每次返回都会重新开始超时。我可以添加一些代码来检查进入时的时钟并调整每次返回时的超时,但随后这个简单的 Get 方法开始变得非常复杂。
关于如何在保持可测试性和简单性的同时解决这些问题有什么想法吗?
哦,对于任何想知道的人来说,IsDataAvail 函数仅用于测试。它不会在生产代码中使用。添加和获取是将在非测试环境中使用的唯一方法。
最佳答案
您需要创建自动重置事件而不是手动重置事件。这保证了如果多个线程正在等待一个事件,并且当事件被设置时只有一个线程将被释放。所有其他线程将保持等待状态。您可以通过将 FALSE 传递给 CreateEvent 的第二个参数来创建自动重置事件应用程序接口(interface)。另外,请注意这段代码不是异常安全的,即在锁定缓冲区后,如果某些语句抛出异常,您的关键部分将不会被解锁。使用 RAII原则以确保即使在异常情况下也能解锁关键部分。
关于c++ - 通缉 : Elegant solution to race condition,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1406649/
我正在为下面的代码编写单元测试 public class Class1 { protected void execute(String a, String b) { try{
我想在Dart编辑器中使用一些UXL。恐怕我觉得UXL Overview上的示例代码已经过时或缺少一些关键的步骤来执行它。 (另请参见:What is Rikulo dart really?,它将人们
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在JUnit中测试Restful端点,并在 在save方法中作为参数存在的列表, **"Argument(s) are different! Wanted:"** save( "121", [co
我正在阅读很多关于 Cuckoo hashing 的 SO 答案. 有人知道 C# 中 Cuckoo 的良好实现吗? 最佳答案 如果您找到了 C 实现,那么将其转换为 C# 应该很简单......发布
我的问题可能是,“如何创建带有两个单行非环绕 TextView 的单行水平 LinearLayout,其中左侧 TextView 始终占据可用屏幕宽度的 1/3,右侧 TextView 始终占据 2/
有一个“API Monitor”程序,但似乎已停产。在我的系统上不起作用。有没有这样的工具,可以在 Windows 7 x64 上运行?我需要记录来自选定集合的 API 调用,最好是参数值。 最佳答案
我需要的是:绘图创建、插值的东西、计算诸如此类的东西 和 其中 L(x) 是从原始已知函数 f(x) 生成的一些数据(点)构建的插值。这意味着我们知道原始功能。我们有一个范围 (-a, a) - 已知
写累了 Pattern p = Pattern.compile(... Matcher m = p.matcher(str); if (m.find()) { ... 在我的代码中一遍又一遍。我
我有以下代码: class TimeOutException {}; template class MultiThreadedBuffer { public: MultiThreadedBu
我正在尝试用 C 语言实现一个单向链表。您在互联网上看到的一个常见实现类似于 typedef struct { int head; Node *tail; } Node; 用像这样的方法 No
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
服务类: public void createManualEvaluationReductionChangeHistory(Long key, String accountId, RegisterRe
我正在寻找一种方法来进行(实际上很常见)可视化,即通过一组 N 个象形图将 N 个单位的总体划分为几个类别 - 我更喜欢实心方块;在报纸等中,人们可能会看到很小的人形形状——每个象形图根据第 n 个单
我不确定这个问题的标题是否切中要点。我用 C C++ 为 Windows 编写了一个大型软件系统,并希望为该系统的用户提供向其添加编译代码的选项。用户应该能够执行基本操作,并与我的程序交换数据。 目前
我需要一个哈希算法,它接受一个字符串并返回一个可以存储在 UInt16 中的数字。 .我需要它来计算一个小的校验和数。 .Net 有这方面的算法吗? 最佳答案 也许您正在寻找crc16 . Here是
我用 Laravel 制作了页面,并使用一个漂亮的 URL 路由它们但是我正在开发一个房地产网站,我想要以下 URL显示一个房子信息的页面:houseinfo/{town}/{neighborhood
我有几个线程获取互斥量然后终止。 互斥量存储在主存储库中,并在程序存在时适当释放。但是,当分配互斥量的线程存在时,互斥量会自动释放,并随后获取 AbandonedMutexException(同样根据
我知道一些 Javascript,但才意识到我对跨浏览器问题知之甚少。 IE 中事件回调中的 this 对象(如 xhr.onreadystatechange = function () { ...
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 5 年前。
我是一名优秀的程序员,十分优秀!