在我们的项目中,我们需要为每个操作系统(linux,android,osx和win)实现依赖于操作系统的抽象(例如文件,套接字,线程...)。
实现os抽象的一般迭代是:

  • 编写一个os独立的类头,该头定义每个os通用的方法(Cond)。
  • 使用os函数(例如pthread_cond,win32 ConditionVariable)编写os实现的实现。
  • 链接并通过cmake构建。

  • 我在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/

    10-11 18:57