Skip to content

Instantly share code, notes, and snippets.

@geky
Last active April 26, 2017 11:12
Show Gist options
  • Save geky/7eee6937f3d55552d4e365bf02de114f to your computer and use it in GitHub Desktop.
Save geky/7eee6937f3d55552d4e365bf02de114f to your computer and use it in GitHub Desktop.
////// mbed poll //////
// poll for mbed FileHandles
int mbed_poll(FileHandle fhs[], unsigned nfhs, int timeout) {
Timer timer; // set timer to keep spurious wakeups from keeping us from exiting
if (timeout >= 0) {
timer.start();
}
// register semaphore release as sigio callback on all filehandles
Semaphore sema;
for (int i = 0; i < nfhs; i++) {
fhs[i].sigio(callback(&sema, &Semaphore::release));
}
while (true) {
// check if any filehandles have pending events
int count = 0;
for (int i = 0; i < nfhs; i++) {
if (fhs[i].poll()) {
count += 1;
}
}
if (count) {
return count;
}
// return if time has expired
if (timeout >= 0 && timer.read_ms() > timeout) {
return 0;
}
// wait for events
if (timeout >= 0) {
sema.wait(timeout - timer.read_ms());
} else {
sema.wait(osWaitForever);
}
}
}
////// FileHandle defaults //////
class FileHandle {
public:
// By default filehandle is always ready for read/write
virtual uint16_t poll(uint16_t events) {
return POLLIN | POLLOUT;
}
// By default sigio callbacks are called every second
virtual void sigio(Callback<void()> cb) {
if (cb) {
if (!_sigio_ticker) {
_sigio_ticker = new Ticker;
}
_sigio_ticker->attach_ms(cb, 1000);
} else {
delete _sigio_ticker;
_sigio_ticker = NULL;
}
}
// Make sure ticker is cleaned up
virtual ~FileHandle() {
sigio(NULL);
}
}
@kjbracey
Copy link

kjbracey commented Apr 26, 2017

Although should sockets just be implemented as blocking only at that point.

Sockets' default behaviour isn't the same as disk files' default behaviour. I don't think we'll ever have blocking-only sockets - we require non-blocking operation for them.

if you're using the poll function you wouldn't need to use sigio.

Disagree - you could be being event-driven, and using sigio to prompt non-blocking poll() calls. Which is what the PPP data pump is doing, if I recall correctly.

I think poll() is very much a core part of the system - to make it work across a variety of different file handle providers, there has to be this common agreement that they all get together and call that central point. It's not as if there will or can be multiple poll() implementations in a system - there can only be one.

There's not a lot of point in having a dynamic callback in every object and making them all point to that central point. Part of the API of being a FileHandle is that you work in mbed::poll(), as well as issuing SIGIO to users.

(I anticipate that maybe in future we define a subclass FileHandleWithoutPoll which gives you sigio(), but not the poll(). Abstracted Sockets could be that.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment