mirror of https://github.com/adamdruppe/arsd.git
edge triggering needs to be part of the interface
This commit is contained in:
parent
b32974869f
commit
0529eb46b3
41
eventloop.d
41
eventloop.d
|
@ -306,7 +306,7 @@ public struct FileEventDispatcher {
|
||||||
/// You can add a file to listen to here. Files can be OS handles or Phobos types. The handlers can be null, meaning use the default
|
/// You can add a file to listen to here. Files can be OS handles or Phobos types. The handlers can be null, meaning use the default
|
||||||
/// (see: setDefaultHandler), or callables with zero or one argument. If they take an argument, it will be the file being handled at this time.
|
/// (see: setDefaultHandler), or callables with zero or one argument. If they take an argument, it will be the file being handled at this time.
|
||||||
public void addFile(FileType, ReadEventHandler, WriteEventHandler, ErrorEventHandler)
|
public void addFile(FileType, ReadEventHandler, WriteEventHandler, ErrorEventHandler)
|
||||||
(FileType handle, ReadEventHandler readEventHandler = null, WriteEventHandler writeEventHandler = null, ErrorEventHandler errorEventHandler = null)
|
(FileType handle, ReadEventHandler readEventHandler = null, WriteEventHandler writeEventHandler = null, ErrorEventHandler errorEventHandler = null, bool edgeTriggered = true)
|
||||||
if(
|
if(
|
||||||
// FIXME: we should be able to take other Phobos types too, and correctly translate them up above
|
// FIXME: we should be able to take other Phobos types too, and correctly translate them up above
|
||||||
templateCheckHelper!(is(FileType == OsFileHandle), "The FileType must be an operating system file handle")
|
templateCheckHelper!(is(FileType == OsFileHandle), "The FileType must be an operating system file handle")
|
||||||
|
@ -339,7 +339,7 @@ public struct FileEventDispatcher {
|
||||||
listeners[handle] = handlerSet;
|
listeners[handle] = handlerSet;
|
||||||
|
|
||||||
|
|
||||||
addFileToLoop(handle, events);
|
addFileToLoop(handle, events, edgeTriggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeFile(OsFileHandle handle) {
|
public void removeFile(OsFileHandle handle) {
|
||||||
|
@ -395,11 +395,11 @@ public enum FileEvents : int {
|
||||||
/// buffers is already handled, since you won't get events for data that already exists
|
/// buffers is already handled, since you won't get events for data that already exists
|
||||||
|
|
||||||
// FIXME: do we want to be able to pass a function pointer to be a special handler?
|
// FIXME: do we want to be able to pass a function pointer to be a special handler?
|
||||||
public void addFileToLoop(OsFileHandle fd, /* FileEvents */ int events) {
|
public void addFileToLoop(OsFileHandle fd, /* FileEvents */ int events, bool edgeTriggered = true) {
|
||||||
if(insideLoop) {
|
if(insideLoop) {
|
||||||
addFileToLoopImplementation(fd, events);
|
addFileToLoopImplementation(fd, events, edgeTriggered);
|
||||||
} else {
|
} else {
|
||||||
backFilesForLoop ~= BackFilesForLoop(fd, events);
|
backFilesForLoop ~= BackFilesForLoop(fd, events, edgeTriggered);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,6 +408,7 @@ public void addFileToLoop(OsFileHandle fd, /* FileEvents */ int events) {
|
||||||
private struct BackFilesForLoop {
|
private struct BackFilesForLoop {
|
||||||
OsFileHandle file;
|
OsFileHandle file;
|
||||||
int events;
|
int events;
|
||||||
|
bool edgeTriggered;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BackFilesForLoop[] backFilesForLoop;
|
private BackFilesForLoop[] backFilesForLoop;
|
||||||
|
@ -416,7 +417,7 @@ private BackFilesForLoop[] backFilesForLoop;
|
||||||
private void addBackFilesToLoop() {
|
private void addBackFilesToLoop() {
|
||||||
assert(insideLoop);
|
assert(insideLoop);
|
||||||
foreach(bf; backFilesForLoop) {
|
foreach(bf; backFilesForLoop) {
|
||||||
addFileToLoop(bf.file, bf.events);
|
addFileToLoop(bf.file, bf.events, bf.edgeTriggered);
|
||||||
}
|
}
|
||||||
|
|
||||||
backFilesForLoop = null;
|
backFilesForLoop = null;
|
||||||
|
@ -448,7 +449,7 @@ version(linux) {
|
||||||
|
|
||||||
int epoll = -1;
|
int epoll = -1;
|
||||||
|
|
||||||
private void addFileToLoopImplementation(int fd, int events) {
|
private void addFileToLoopImplementation(int fd, int events, bool edgeTriggered = true) {
|
||||||
epoll_event ev;
|
epoll_event ev;
|
||||||
|
|
||||||
// I don't remember why I made it edge triggered in the first
|
// I don't remember why I made it edge triggered in the first
|
||||||
|
@ -460,7 +461,8 @@ version(linux) {
|
||||||
// OK I'm turning it back on because otherwise unhandled events
|
// OK I'm turning it back on because otherwise unhandled events
|
||||||
// cause an infinite loop. So when an event comes, you MUST starve
|
// cause an infinite loop. So when an event comes, you MUST starve
|
||||||
// the read to get all your info in a timely fashion. Gonna document this.
|
// the read to get all your info in a timely fashion. Gonna document this.
|
||||||
ev.events = EPOLL_EVENTS.EPOLLET; // edge triggered
|
if(edgeTriggered)
|
||||||
|
ev.events = EPOLL_EVENTS.EPOLLET; // edge triggered
|
||||||
|
|
||||||
// Oh I think I know why I did this: if it is level triggered
|
// Oh I think I know why I did this: if it is level triggered
|
||||||
// and the data is not actually handled, it infinite loops
|
// and the data is not actually handled, it infinite loops
|
||||||
|
@ -505,7 +507,7 @@ version(linux) {
|
||||||
// anything done before the loop is open needs to be caught up on
|
// anything done before the loop is open needs to be caught up on
|
||||||
addBackFilesToLoop();
|
addBackFilesToLoop();
|
||||||
|
|
||||||
addFileToLoop(pipes[0], FileEvents.read);
|
addFileToLoop(pipes[0], FileEvents.read, false);
|
||||||
|
|
||||||
epoll_event[16] events;
|
epoll_event[16] events;
|
||||||
|
|
||||||
|
@ -547,13 +549,22 @@ version(linux) {
|
||||||
break outer_loop;
|
break outer_loop;
|
||||||
} else {
|
} else {
|
||||||
auto flags = events[n].events;
|
auto flags = events[n].events;
|
||||||
if(flags & EPOLL_EVENTS.EPOLLIN)
|
import core.stdc.stdio;
|
||||||
|
if(flags & EPOLL_EVENTS.EPOLLIN) {
|
||||||
sendSync(FileReadyToRead(fd));
|
sendSync(FileReadyToRead(fd));
|
||||||
|
}
|
||||||
if(flags & EPOLL_EVENTS.EPOLLOUT) {
|
if(flags & EPOLL_EVENTS.EPOLLOUT) {
|
||||||
sendSync(FileReadyToWrite(fd));
|
sendSync(FileReadyToWrite(fd));
|
||||||
}
|
}
|
||||||
if((flags & EPOLL_EVENTS.EPOLLERR) || (flags & EPOLL_EVENTS.EPOLLHUP))
|
if((flags & EPOLL_EVENTS.EPOLLERR)) {
|
||||||
|
//import core.stdc.stdio; printf("ERROR on fd from epoll %d\n", fd);
|
||||||
sendSync(FileError(fd));
|
sendSync(FileError(fd));
|
||||||
|
break outer_loop;
|
||||||
|
}
|
||||||
|
if((flags & EPOLL_EVENTS.EPOLLHUP)) {
|
||||||
|
//import core.stdc.stdio; printf("HUP on fd from epoll %d\n", fd);
|
||||||
|
sendSync(FileHup(fd));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,8 +631,9 @@ private bool readFromEventPipe() {
|
||||||
for(;;) {
|
for(;;) {
|
||||||
auto read = unix.read(pipes[0], buffer.ptr, buffer.length);
|
auto read = unix.read(pipes[0], buffer.ptr, buffer.length);
|
||||||
if(read == -1) {
|
if(read == -1) {
|
||||||
if(errno == EAGAIN)
|
if(errno == EAGAIN) {
|
||||||
break; // we got it all
|
break; // we got it all
|
||||||
|
}
|
||||||
throw new Exception("read");
|
throw new Exception("read");
|
||||||
} else if(read == 0) {
|
} else if(read == 0) {
|
||||||
assert(0); // this is never supposed to happen
|
assert(0); // this is never supposed to happen
|
||||||
|
@ -749,6 +761,11 @@ struct FileError {
|
||||||
OsFileHandle fd; // file handle;
|
OsFileHandle fd; // file handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This is a low level event that is dispatched when a listened file (see: addFileToLoop) has a hang up event
|
||||||
|
struct FileHup {
|
||||||
|
OsFileHandle fd; // file handle;
|
||||||
|
}
|
||||||
|
|
||||||
/* **** */
|
/* **** */
|
||||||
// epoll
|
// epoll
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue