在我们的项目中,我们需要为每个操作系统(linux、android、osx 和 win)实现依赖于操作系统的抽象(如文件、套接字、线程......)。实现 os 抽象的一般迭代是:
- 编写一个独立于操作系统的类头,它定义了每个操作系统通用的方法(Cond)。
- 使用 os 函数(例如 pthread_cond、win32 ConditionVariable)编写一个 os依赖的实现。
- 通过 cmake 链接和构建。
我在 Windows 中实现条件变量时遇到了问题。我需要在我的 Mutex 类中包装 CriticalSection 函数,因为 Windows 中的 ConditionVariable 可用于关键部分。当然,我在 posix 系统上使用标准的 posix 解决方案。
这是代码:
1.a ) 标头 (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) 标头(获胜)- 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;
};
如您所见,接口是通用的,但类型不同。
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) 实施 (win) - 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;
}
你能解释一下为什么吗?解决方案?谢谢!