X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fio%2Feventreader.cpp;fp=source%2Fio%2Feventreader.cpp;h=a31a384f7bd3156a1fbd51028779e1ae81b5b8b2;hb=caa2f6ca5d0a803e47d6efb4858c92c505520527;hp=0000000000000000000000000000000000000000;hpb=a56e05106571f28dc3044296849ccd5127d7d859;p=libs%2Fcore.git diff --git a/source/io/eventreader.cpp b/source/io/eventreader.cpp new file mode 100644 index 0000000..a31a384 --- /dev/null +++ b/source/io/eventreader.cpp @@ -0,0 +1,140 @@ +#ifdef WIN32 +#include +#endif +#include +#include +#include "eventreader.h" +#include "handle_private.h" + +using namespace std; + +namespace Msp { +namespace IO { + +struct EventReader::Private +{ +#ifdef WIN32 + OVERLAPPED *overlapped; + Handle event; + unsigned buf_size; + char *buffer; + unsigned buf_avail; + char *buf_next; +#endif +}; + + +EventReader::EventReader(Handle &h, unsigned size): + handle(h), + priv(0) +{ +#ifdef WIN32 + 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; + + start(); +#else + (void)size; +#endif +} + +EventReader::~EventReader() +{ +#ifdef WIN32 + CloseHandle(*priv->event); + delete priv->overlapped; + delete[] priv->buffer; +#endif + delete priv; +} + +const Handle &EventReader::get_event() const +{ +#ifdef WIN32 + return priv->event; +#else + return handle; +#endif +} + +void EventReader::start() +{ +#ifdef WIN32 + 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); + } +#endif +} + +void EventReader::wait() +{ +#ifdef WIN32 + 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; + } +#endif +} + +unsigned EventReader::read(char *buf, unsigned len) +{ +#ifdef WIN32 + 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; +#else + return sys_read(handle, buf, len); +#endif +} + +} // namespace IO +} // namespace Msp