2018-11-07 21:24:08 +01:00
|
|
|
/*
|
|
|
|
* IXEventFd.cpp
|
|
|
|
* Author: Benjamin Sergeant
|
|
|
|
* Copyright (c) 2018 Machine Zone, Inc. All rights reserved.
|
|
|
|
*/
|
|
|
|
|
|
|
|
//
|
|
|
|
// Linux/Android has a special type of virtual files. select(2) will react
|
|
|
|
// when reading/writing to those files, unlike closing sockets.
|
|
|
|
//
|
|
|
|
// https://linux.die.net/man/2/eventfd
|
|
|
|
// http://www.sourcexr.com/articles/2013/10/26/lightweight-inter-process-signaling-with-eventfd
|
|
|
|
//
|
|
|
|
// eventfd was added in Linux kernel 2.x, and our oldest Android (Kitkat 4.4)
|
|
|
|
// is on Kernel 3.x
|
|
|
|
//
|
2019-02-21 03:59:07 +01:00
|
|
|
// cf Android/Kernel table here
|
2018-11-07 21:24:08 +01:00
|
|
|
// https://android.stackexchange.com/questions/51651/which-android-runs-which-linux-kernel
|
|
|
|
//
|
2019-03-14 07:09:45 +01:00
|
|
|
// On macOS we use UNIX pipes to wake up select.
|
|
|
|
//
|
2018-11-07 21:24:08 +01:00
|
|
|
|
|
|
|
#include "IXEventFd.h"
|
|
|
|
|
|
|
|
#ifdef __linux__
|
|
|
|
# include <sys/eventfd.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <unistd.h> // for write
|
2019-03-14 07:09:45 +01:00
|
|
|
#include <fcntl.h>
|
2018-11-07 21:24:08 +01:00
|
|
|
|
2019-02-21 03:59:07 +01:00
|
|
|
namespace ix
|
2018-11-07 21:24:08 +01:00
|
|
|
{
|
2019-03-14 07:09:45 +01:00
|
|
|
EventFd::EventFd()
|
2018-11-07 21:24:08 +01:00
|
|
|
{
|
|
|
|
#ifdef __linux__
|
2019-03-14 07:09:45 +01:00
|
|
|
_eventfd = -1;
|
2018-11-07 21:24:08 +01:00
|
|
|
_eventfd = eventfd(0, 0);
|
2019-03-14 07:09:45 +01:00
|
|
|
fcntl(_eventfd, F_SETFL, O_NONBLOCK);
|
|
|
|
#else
|
|
|
|
_fildes[0] = -1;
|
|
|
|
_fildes[1] = -1;
|
|
|
|
|
|
|
|
pipe(_fildes);
|
|
|
|
fcntl(_fildes[0], F_SETFL, O_NONBLOCK);
|
|
|
|
fcntl(_fildes[1], F_SETFL, O_NONBLOCK);
|
2018-11-07 21:24:08 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
EventFd::~EventFd()
|
|
|
|
{
|
|
|
|
#ifdef __linux__
|
|
|
|
::close(_eventfd);
|
2019-03-14 07:09:45 +01:00
|
|
|
#else
|
|
|
|
::close(_fildes[0]);
|
|
|
|
::close(_fildes[1]);
|
|
|
|
_fildes[0] = -1;
|
|
|
|
_fildes[1] = -1;
|
2018-11-07 21:24:08 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2019-03-14 07:09:45 +01:00
|
|
|
bool EventFd::notify(uint64_t value)
|
2018-11-07 21:24:08 +01:00
|
|
|
{
|
2019-03-14 07:09:45 +01:00
|
|
|
int fd;
|
|
|
|
|
2018-11-07 21:24:08 +01:00
|
|
|
#if defined(__linux__)
|
2019-03-14 07:09:45 +01:00
|
|
|
fd = _eventfd;
|
|
|
|
#else
|
|
|
|
// File descriptor at index 1 in _fildes is the write end of the pipe
|
|
|
|
fd = _fildes[1];
|
|
|
|
#endif
|
2018-11-07 21:24:08 +01:00
|
|
|
|
2019-03-14 07:09:45 +01:00
|
|
|
if (fd == -1) return false;
|
2018-11-07 21:24:08 +01:00
|
|
|
|
|
|
|
// we should write 8 bytes for an uint64_t
|
2019-03-14 07:09:45 +01:00
|
|
|
return write(fd, &value, sizeof(value)) == 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: return max uint64_t for errors ?
|
|
|
|
uint64_t EventFd::read()
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
|
|
|
#if defined(__linux__)
|
|
|
|
fd = _eventfd;
|
2018-11-07 21:24:08 +01:00
|
|
|
#else
|
2019-03-14 07:09:45 +01:00
|
|
|
fd = _fildes[0];
|
2018-11-07 21:24:08 +01:00
|
|
|
#endif
|
2019-03-14 07:09:45 +01:00
|
|
|
uint64_t value = 0;
|
|
|
|
::read(fd, &value, sizeof(value));
|
|
|
|
return value;
|
2018-11-07 21:24:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool EventFd::clear()
|
|
|
|
{
|
|
|
|
#if defined(__linux__)
|
|
|
|
if (_eventfd == -1) return false;
|
|
|
|
|
2019-02-21 03:59:07 +01:00
|
|
|
// 0 is a special value ; select will not wake up
|
2018-11-07 21:24:08 +01:00
|
|
|
uint64_t value = 0;
|
|
|
|
|
|
|
|
// we should write 8 bytes for an uint64_t
|
|
|
|
return write(_eventfd, &value, sizeof(value)) == 8;
|
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
int EventFd::getFd()
|
|
|
|
{
|
2019-03-14 07:09:45 +01:00
|
|
|
#if defined(__linux__)
|
2018-11-07 21:24:08 +01:00
|
|
|
return _eventfd;
|
2019-03-14 07:09:45 +01:00
|
|
|
#else
|
|
|
|
return _fildes[0];
|
|
|
|
#endif
|
2018-11-07 21:24:08 +01:00
|
|
|
}
|
|
|
|
}
|