Chiharu の日記

絵描き C/C++ プログラマーの日記です。

Linux の eventfd を Win32 イベントオブジェクトのように使う

Linux の eventfd を Win32 イベントオブジェクトの SetEvent(), ResetEvent(), WaitForSingleObject() のように使いたかったので、やってみました。生成時に EFD_NONBLOCK を指定して、待機を select() で実施するのがポイントですね。

#include <sys/eventfd.h>
#include <sys/select.h>
#include <unistd.h>
#include <cerrno>

class Event {
 
public:
 Event():
  mEventFd(eventfd(0, EFD_NONBLOCK))
 {
 }
 
 ~Event()
 {
  close(mEventFd);
 }
 
 int wait(int iTimeout)
 {
  fd_set aFds;
  FD_ZERO(&aFds);
  FD_SET(mEventFd, &aFds);
  
  timeval* aTimeoutP, aTimeout;
  if (iTimeout == -1) {
   aTimeoutP = nullptr;
  } else {
   aTimeout.tv_sec = iTimeout / 1000;
   aTimeout.tv_usec = (iTimeout % 1000) * 1000;
   aTimeoutP = &aTimeout;
  }
  
  return select(mEventFd + 1, &aFds, nullptr, nullptr, aTimeoutP);
 }
 
 int set()
 {
  return eventfd_write(mEventFd, 1);
 }
 
 int reset()
 {
  eventfd_t aValue;
  auto aResult = eventfd_read(mEventFd, &aValue);
  if ((aResult == -1) && (errno == EAGAIN)) {
   aResult = 0;
  }
  return aResult;
 }
 
private:
 int mEventFd;
 
};

// test
#include <cstdio>

int main()
{
 Event aEvent;
 
 printf("Event::wait(0) = %d : 0\n", aEvent.wait(0));
 printf("Event::set() = %d : 0\n", aEvent.set());
 printf("Event::wait(-1) = %d : 1\n", aEvent.wait(-1));
 printf("Event::wait(0) = %d : 1\n", aEvent.wait(0));
 printf("Event::reset() = %d : 0\n", aEvent.reset());
 printf("Event::wait(0) = %d : 0\n", aEvent.wait(0));
 printf("Event::reset() = %d : 0\n", aEvent.reset());
 
 return 0;
}

余談ですが、WSL を初めて使いました。apt も使えてとても便利ですね。これで Cygwin / MSYS2 も卒業かな。