Linux/POSIX 等同于 Win32 的 CreateEvent、SetEvent、WaitForSingleObject

Linux/POSIX equivalent for Win32's CreateEvent, SetEvent, WaitForSingleObject

我写了一个小的 class 用于同步 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,但由于答案不完整,我不确定如何完成我的 class :

    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()
        {

        }
    };

同时检查 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

您描述的 POSIX 等效项是 POSIX 条件变量。请注意,条件变量必须始终与 POSIX 互斥量一起使用,但多个条件变量经常使用相同的互斥量,因此如果您不打算专门为条件变量使用互斥量,则应该不要将它放在 class 中。在您的情况下,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

与您的代码等效的 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);
    }
};

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

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

https://github.com/neosmart/pevents

由于 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事件消息队列可以解决大部分请求,但它不提供超时能力,当你不想完全冻结你的process/thread时,这可能会导致一些问题。 12=]