【问题标题】:Linux/POSIX equivalent for Win32's CreateEvent, SetEvent, WaitForSingleObjectLinux/POSIX 等效于 Win32 的 CreateEvent、SetEvent、WaitForSingleObject
【发布时间】:2016-01-10 22:52:25
【问题描述】:

我编写了一个小类,用于同步 Linux(实际上是 Android)和 Windows 的线程。

这是我的界面的 Win32 实现:

    class SyncObjectWin32 : public SyncObject
    {
    private:

        const HANDLE m_hEvent;

    public:

        SyncObjectWin32()
          : m_hEvent( ::CreateEvent( NULL, FALSE, FALSE ) )
        {
            if( NULL == m_hEvent )
                throw core::Exception( "sys::SyncObjectWin32::SyncObjectWin32() - Failed to create event." );
        }

        ~SyncObjectWin32()
        {
            ::CloseHandle( m_hEvent );
        }

        void WaitForSignal()
        {
            ::WaitForSingleObject( m_hEvent );
        }

        void Signal()
        {
            ::SetEvent( m_hEvent );
        }
    };

问题是我不确定 POSIX 等价物是什么。 到目前为止,我已经基于this SO question 编写了以下课程,但由于答案不完整,我不确定如何完成我的课程:

    class SyncObjectPosix
    {
    private:

        pthread_mutex_t m_oMutex;

    public:

        SyncObjectPosix()
        {
            pthread_mutex_lock( m_oMutex );                 // lock mutex
            bool & signalled = find_signal( condition );  // find predicate
            signalled = true;                          // set predicate
            pthread_mutex_unlock( m_oMutex );               // unlock mutex
            pthread_cond_signal( condition );            // signal condition variable
        }

        ~SyncObjectPosix()
        {

        }

        void WaitForSignal()
        {
            pthread_mutex_lock(mutex);                         // lock mutex
            bool & signalled = find_signal( condition );          // find predicate
            while (!signalled)
            {
              pthread_cond_timedwait(condition, m_oMutex, timeout);
            }
            signalled = false;                                 // reset predicate
            pthread_mutex_unlock( m_oMutex );                       // unlock mutex
        }

        void Signal()
        {

        }
    };

【问题讨论】:

  • 构造函数中的代码看起来应该在Signal()中。
  • 好的,谢谢。你知道“条件”的类型是什么吗?另外我怎么能无限等待?这有多快?因为如果 pthread_cond_timedwait 等待,比如说 1 秒,那么在某些情况下会有 1 秒的延迟。
  • 没有等价物。一个类似的工具是 POSIX 条件变量。您需要阅读 pthread_cond_* 系列中的所有手册页,然后阅读一两个关于如何实际使用它们的教程。
  • Windows 和 POSIX 同步方法的语义不同,因此跨平台等效取决于您如何使用其中一种。从您使用SetEvent()WaitForSingleObject() 的方式来看,信号量也可以工作。请参阅 man7.org/linux/man-pages/man3/sem_post.3.htmlman7.org/linux/man-pages/man3/sem_wait.3.html sem_wait() 手册页上有一些很好的示例代码。
  • @AndrewHenle 感谢您的帮助。我会看看的。我还在这里找到了关于 POSIX 线程的详细文档(法语):univ-orleans.fr/lifo/Members/Sylvain.Jubertie/enseignement/… 如果它没有给我我需要的东西,我会看看信号量的东西。

标签: c linux multithreading pthreads posix


【解决方案1】:

您所描述的 POSIX 等价物是 POSIX 条件变量。请注意,条件变量必须始终与 POSIX 互斥锁配对使用,但经常有多个条件变量使用同一个互斥锁,因此如果您不打算将互斥锁专门用于条件变量,则不应将其放入班上。在您的情况下,Win32 和 POSIX API 之间的映射应该是:

CreateEvent -> pthread_cond_init

CloseHandle -> pthread_cond_destroy

WaitForSingleObject -> pthread_cond_waitpthread_cond_timedwait

SetEvent -> pthread_cond_signalpthread_cond_broadcast

幸运的是,有很多关于此的文档,尽管我推荐基本的Programming POSIX Threads

【讨论】:

  • 感谢您的回答。会看看这个。
  • 不,posix 条件变量不是信号的直接替代品。真可惜。
  • @SergeyA 我并不是说这些是平等的。但条件变量适合这种情况。
  • pthread(和 C++11)条件变量与 Windows 信号有很大的不同,尤其是手动重置事件,它们不需要互斥锁即可工作。
【解决方案2】:

还要检查eventfd。如果您只需要一个消费者和一个生产者,它似乎几乎等同于CreateEvent

CreateEvent --> eventfd

CloseHandle --> close

SetEvent --> write

WaitForSingleObject --> read

WaitForMultipleObjects --> selectread对应fd

更多阅读 http://www.sourcexr.com/articles/2013/10/26/lightweight-inter-process-signaling-with-eventfd

【讨论】:

  • 感谢您的帮助。我认为这是 linux 的东西而不是 POSIX 对吗?只要 Android NDK 支持它们,我也可以使用 linux API。
  • 是的,这是 Linux 特有的,我不知道 Android 是否支持,但有可能。
  • 这里是关于eventfdpthread_cond 系统issues.apache.org/jira/browse/TS-2137 性能的有趣读物,似乎eventfd 快了5 倍。
  • 这是正确答案,唯一的问题是,它不是 Posix。但是 Posix 根本没有信号。
  • @j123b567,这里没有惊喜。
【解决方案3】:

与您的代码等效的 pthreads 是:

class SyncObjectPosix
{
private:

    bool signalled;
    pthread_mutex_t mutex;
    pthread_cond_t cond;

public:

    SyncObjectPosix()
    {
        signalled = false;
        pthread_mutex_init(&mutex, NULL);
        pthread_cond_init(&cond, NULL);
    }

    ~SyncObjectPosix()
    {
        pthread_mutex_destroy(&mutex);
        pthread_cond_destroy(&cond);
    }

    void WaitForSignal()
    {
        pthread_mutex_lock(&mutex);
        while (!signalled)
        {
            pthread_cond_wait(&cond, &mutex);
        }
        signalled = false;
        pthread_mutex_unlock(&mutex);
    }

    void Signal()
    {
        pthread_mutex_lock(&mutex);
        signalled = true;
        pthread_mutex_unlock(&mutex);
        pthread_cond_signal(&cond);
    }
};

【讨论】:

    【解决方案4】:

    我们的开源pevents 库是针对所有平台的实现。这是一段非常小的(单文件)C++ 代码,您只需将其添加到现有项目中,即可访问构建在 pthreads 同步原语之上的 Windows 事件 API。

    最重要的花絮是它包括WaitForMultipleObjects 支持。

    https://github.com/neosmart/pevents

    【讨论】:

    • 这是一个非常简单的解决方案,效果很好!
    【解决方案5】:

    由于 Win32 的 CreateEvent 使用文件路径之类的键来缩进事件,我不认为所有这些答案都是好的。

    查看UNIX:System V IPC

    int project_id = 1;
    std::string path = "[path]";
    
    //CreateEvent
    key_t ipc_key = ftok(path.c_str(),project_id);
    int event_id = msgget(ipc_key , IPC_CREAT);
    
    //OpenEvent
    key_t ipc_key = ftok(path.c_str(),project_id);
    int event_id = msgget(ipc_key , 0);
    
    //SetEvent
    std::string send_message = "trump 2024|America first|life equally matter|build the #$% wall"; //
    
    msgsnd(event_id, send_message.c_str(), send_message.size(), IPC_NOWAIT); //NO Block
    msgsnd(event_id, send_message.c_str(), send_message.size(), 0); //Block
    
    //WaitForSingleObject
    std::string receive_message;
    receive_message.resize(128);
    
    msgrcv(event_id , &receive_message[0], receive_message.size(), 0,0);
    
    //CloseHandle
    msgctl(event_id , IPC_RMID,NULL);
    

    请注意,即使某些函数每次调用的速度可能会更快,但基于文件描述的函数不会像 CreateEvent 那样在进程间进行。

    使用 IPC 事件消息队列可能解决大部分请求,但它不提供超时能力,当您不想完成冻结进程/线程时,可能会导致一些问题。

    【讨论】:

      猜你喜欢
      • 2019-03-20
      • 2021-05-04
      • 2011-02-12
      • 1970-01-01
      • 2020-02-23
      • 1970-01-01
      • 2013-08-19
      • 1970-01-01
      • 2020-10-23
      相关资源
      最近更新 更多