X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fio%2Fwindows%2Feventreader.cpp;fp=source%2Fio%2Fwindows%2Feventreader.cpp;h=62c9763d9fa92595385f658b36710d68087e09b8;hp=0000000000000000000000000000000000000000;hb=609c9a508cfdc7b42c46c4f21d17639204165a00;hpb=b4806214e905752617691f851717033fd3f266c2 diff --git a/source/io/windows/eventreader.cpp b/source/io/windows/eventreader.cpp new file mode 100644 index 0000000..62c9763 --- /dev/null +++ b/source/io/windows/eventreader.cpp @@ -0,0 +1,115 @@ +#include +#include +#include +#include "eventreader.h" +#include "handle_private.h" + +using namespace std; + +namespace Msp { +namespace IO { + +struct EventReader::Private +{ + OVERLAPPED *overlapped; + Handle event; + unsigned buf_size; + char *buffer; + unsigned buf_avail; + char *buf_next; +}; + + +EventReader::EventReader(Handle &h, unsigned size): + handle(h), + priv(new Private) +{ + priv->overlapped = 0; + *priv->event = CreateEvent(0, true, false, 0); + priv->buf_size = size; + priv->buffer = new char[priv->buf_size]; + priv->buf_avail = 0; + priv->buf_next = priv->buffer; +} + +EventReader::~EventReader() +{ + CloseHandle(*priv->event); + delete priv->overlapped; + delete[] priv->buffer; + delete priv; +} + +const Handle &EventReader::get_event() +{ + start(); + return priv->event; +} + +void EventReader::start() +{ + if(priv->buf_avail || priv->overlapped) + return; + + priv->overlapped = new OVERLAPPED; + memset(priv->overlapped, 0, sizeof(OVERLAPPED)); + priv->overlapped->hEvent = *priv->event; + + DWORD ret; + priv->buf_next = priv->buffer; + if(!ReadFile(*handle, priv->buffer, priv->buf_size, &ret, priv->overlapped)) + { + unsigned err = GetLastError(); + if(err!=ERROR_IO_PENDING) + throw system_error("ReadFile"); + } + else + { + priv->buf_avail = ret; + delete priv->overlapped; + priv->overlapped = 0; + SetEvent(*priv->event); + } +} + +void EventReader::wait() +{ + if(!priv->overlapped) + return; + + DWORD ret; + if(!GetOverlappedResult(*handle, priv->overlapped, &ret, true)) + throw system_error("GetOverlappedResult"); + else + { + priv->buf_avail = ret; + delete priv->overlapped; + priv->overlapped = 0; + } +} + +unsigned EventReader::read(char *buf, unsigned len) +{ + if(!priv->buf_avail) + { + // No data in buffer, try to get some + start(); + wait(); + } + + len = min(len, priv->buf_avail); + memcpy(buf, priv->buf_next, len); + priv->buf_next += len; + priv->buf_avail -= len; + + if(!priv->buf_avail) + { + ResetEvent(*priv->event); + start(); + } + + return len; +} + +} // namespace IO +} // namespace Msp