在我们的项目中,我们需要为每个操作系统(linux,android,osx和win)实现依赖于操作系统的抽象(例如文件,套接字,线程...)。
实现os抽象的一般迭代是:
我在Windows中实现条件变量时遇到问题。
我需要将CriticalSection函数包装在Mutex类中,因为Windows中的ConditionVariable可以处理关键部分。当然,我在posix系统上使用标准posix解决方案。
这是代码:
1.a) header (Linux)- Cond.h
#pragma once
#include <pthread.h>
#include "Types.h"
#include "Mutex.h"
#include "OS.h"
Class Cond
{
public:
Cond();
~Cond();
void signal();
void wait(Mutex& mutex);
private:
pthread_cond_t m_cond;
};
1.b) header (获胜)- Cond.h
#pragam once
#include <windows.h>
#include "Types.h"
#include "Mutex.h"
#include "OS.h"
class Cond
{
public:
Cond();
~Cond();
void signal();
void wait(Mutex& mutex);
private:
CONDITION_VARIABLE m_cond;
};
如您所见,该接口(interface)是通用的,但类型不同。
2.a)实现(Linux)- Cond.cpp
#include "Cond.h"
//-----------------------------------------------------------------------------
Cond::Cond()
{
memset(&m_cond, 0, sizeof(pthread_cond_t));
pthread_cond_init(&m_cond, NULL);
}
//-----------------------------------------------------------------------------
Cond::~Cond()
{
pthread_cond_destroy(&m_cond);
}
//-----------------------------------------------------------------------------
void Cond::signal()
{
pthread_cond_signal(&m_cond);
}
//-----------------------------------------------------------------------------
void Cond::wait(Mutex& mutex)
{
pthread_cond_wait(&m_cond, &(mutex.m_mutex));
}
条件变量的linux实现效果很好!
2.b)实现(获胜)- Cond.cpp
#include "Cond.h"
Cond::Cond()
{
InitializeConditionVariable(&m_cond);
}
Cond::~Cond()
{
}
void Cond::signal()
{
WakeConditionVariable(&m_cond);
}
void Cond::wait(Mutex& mutex)
{
CRITICAL_SECTION cs = mutex.handle(); // returns CRITICAL_SECTION
SleepConditionVariableCS(&m_cond, &cs, INFINITE);
}
此实现可以编译,但不起作用(死锁)。
这是一个在Linux上有效而在Win上无效的示例:
void ResourceManager::flush()
{
check_load_queue();
while (true)
{
// Wait for all the resources to be loaded
// by the background thread
m_loading_mutex.lock();
while (m_loading_queue.size() > 0)
{
m_all_loaded.wait(m_loading_mutex); //Cond
}
m_loading_mutex.unlock();
// When all loaded, bring them online
bring_loaded_online();
return;
}
}
编辑:
Windows关键部分包装器-Mutex.h和Mutex.cpp
#pragma once
#include <windows.h>
#include "Types.h"
#include "OS.h"
class Mutex
{
public:
Mutex();
~Mutex();
void lock();
void unlock();
CRITICAL_SECTION handle();
private:
CRITICAL_SECTION m_cs;
friend class Cond;
};
#include "Mutex.h"
namespace crown
{
namespace os
{
//-----------------------------------------------------------------------------
Mutex::Mutex()
{
InitializeCriticalSection(&m_cs);
}
//-----------------------------------------------------------------------------
Mutex::~Mutex()
{
DeleteCriticalSection(&m_cs);
}
//-----------------------------------------------------------------------------
void Mutex::lock()
{
TryEnterCriticalSection(&m_cs);
}
//-----------------------------------------------------------------------------
void Mutex::unlock()
{
LeaveCriticalSection(&m_cs);
}
//-----------------------------------------------------------------------------
CRITICAL_SECTION Mutex::handle()
{
return m_cs;
}
你能解释一下为什么吗?解决方案?
谢谢!
最佳答案
这肯定是错误的:
CRITICAL_SECTION Mutex::handle()
{
return m_cs;
}
您将返回cannot do的CRITICAL_SECTION的拷贝。而是返回一个引用或指针。
如评论中所述,您还应该在Mutex和Cond类中实现私有(private)拷贝构造函数和赋值运算符,因为依赖于平台的互斥锁(例如pthread_mutex_t)和条件变量无法复制-这样做会导致使用这些对象时出现不确定的行为
关于c++ - 跨平台条件变量问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17087416/