在我们的项目中,我们需要为每个操作系统(linux,android,osx和win)实现os 依赖抽象(如文件,套接字,线程...)。 实现os抽象的一般方法是:
我在Windows中遇到了实现条件变量的问题。 我需要在我的Mutex类中包装CriticalSection函数,因为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)标题(获胜) - 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)实施(获胜) - 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 Critical Section Wrapper - Mutex.h&amp; 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;
}
你可以解释一下为什么吗?解决方案?
谢谢!
答案 0 :(得分:2)
为什么呢?不知道。解决方案:使用可移植且免费提供的库来包装平台依赖项。
std::thread
用于多线程:#include <thread>
#include <boost/asio.hpp>
#include <boost/filesystem.hpp>
Boost库通常是标准库的前导码。几乎所有的线程功能都可以在最新的C ++ 11标准版之前几年Boost.Thread中获得。预计Boost.Asio和Boost.Filesystem也将构建标准化模块。
要让它在CMake中工作,install Boost并使用类似
的内容find_package(Boost COMPONENTS thread asio filesystem REQUIRED)
答案 1 :(得分:1)
这当然是错的:
CRITICAL_SECTION Mutex::handle()
{
return m_cs;
}
您将返回CRITICAL_SECTION的副本,即cannot do。改为返回引用或指针。
如评论中所述,您还应该在Mutex和Cond类中实现私有拷贝构造函数和赋值运算符,因为平台相关的互斥锁(例如pthread_mutex_t)和条件变量无法复制 - 这样做会导致使用时出现未定义的行为这些对象