X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fio%2Fpipe.cpp;h=1b275e731667f4736929499aaad7e9a17745343b;hp=b3735aa63b6d43a7724aaa13d1109ce96a78b0d2;hb=31e72f50fbb34d86877e5110401c49ce3fefd4bb;hpb=c7afef88380ebebc8c2b04e48664d73281ec8848 diff --git a/source/io/pipe.cpp b/source/io/pipe.cpp index b3735aa..1b275e7 100644 --- a/source/io/pipe.cpp +++ b/source/io/pipe.cpp @@ -2,7 +2,9 @@ #include #include #endif +#include #include +#include "handle_private.h" #include "pipe.h" using namespace std; @@ -10,31 +12,50 @@ using namespace std; namespace Msp { namespace IO { -Pipe::Pipe() +struct Pipe::Private +{ +#ifdef WIN32 + OVERLAPPED *overlapped; + Handle event; + unsigned buf_size; + char *buffer; + unsigned buf_avail; + char *buf_next; +#endif +}; + + +Pipe::Pipe(): + priv(0) { #ifdef WIN32 string name = format("\\\\.\\pipe\\%u.%p", GetCurrentProcessId(), this); - handle[0] = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0); - if(handle[0]==INVALID_HANDLE_VALUE) - throw SystemError("Unable to create pipe", GetLastError()); + *handle[0] = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0); + if(!handle[0]) + throw system_error("CreateNamedPipe"); - handle[1] = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); - if(handle[1]==INVALID_HANDLE_VALUE) + *handle[1] = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); + if(!handle[1]) { unsigned err = GetLastError(); - CloseHandle(handle[0]); - throw SystemError("Unable to create pipe", err); + CloseHandle(*handle[0]); + throw system_error(format("CreateFile(%s)", name), err); } - overlapped = 0; - event = CreateEvent(0, true, false, 0); - buf_size = 1024; - buffer = new char[buf_size]; - buf_avail = 0; - buf_next = buffer; + priv = new Private; + priv->overlapped = 0; + *priv->event = CreateEvent(0, true, false, 0); + priv->buf_size = 1024; + priv->buffer = new char[priv->buf_size]; + priv->buf_avail = 0; + priv->buf_next = priv->buffer; #else - if(pipe(handle)==-1) - throw SystemError("Unable to create pipe", errno); + int pipe_fd[2]; + if(pipe(pipe_fd)==-1) + throw system_error("pipe"); + + *handle[0] = pipe_fd[0]; + *handle[1] = pipe_fd[1]; #endif set_events(P_INPUT); @@ -43,6 +64,11 @@ Pipe::Pipe() Pipe::~Pipe() { close(); +#ifdef WIN32 + CloseHandle(*priv->event); + delete priv->buffer; +#endif + delete priv; } void Pipe::close() @@ -51,11 +77,11 @@ void Pipe::close() signal_flush_required.emit(); #ifdef WIN32 - CloseHandle(handle[0]); - CloseHandle(handle[1]); + CloseHandle(*handle[0]); + CloseHandle(*handle[1]); #else - ::close(handle[0]); - ::close(handle[1]); + ::close(*handle[0]); + ::close(*handle[1]); signal_closed.emit(); #endif } @@ -67,10 +93,10 @@ void Pipe::set_block(bool b) mode = (mode|M_NONBLOCK); #ifndef WIN32 - int flags = fcntl(handle[0], F_GETFD); - fcntl(handle[0], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); - flags = fcntl(handle[1], F_GETFD); - fcntl(handle[1], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); + int flags = fcntl(*handle[0], F_GETFD); + fcntl(*handle[0], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); + flags = fcntl(*handle[1], F_GETFD); + fcntl(*handle[1], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); #endif } @@ -81,16 +107,16 @@ unsigned Pipe::do_write(const char *buf, unsigned size) #ifdef WIN32 DWORD ret; - if(!WriteFile(handle[1], buf, size, &ret, 0)) - throw SystemError("Writing to pipe failed", GetLastError()); + if(!WriteFile(*handle[1], buf, size, &ret, 0)) + throw system_error("WriteFile"); #else - int ret = ::write(handle[1], buf, size); + int ret = ::write(*handle[1], buf, size); if(ret==-1) { if(errno==EAGAIN) return 0; else - throw SystemError("Writing to pipe failed", errno); + throw system_error("write"); } #endif @@ -106,34 +132,34 @@ unsigned Pipe::do_read(char *buf, unsigned size) // Initiate overlapped read if needed get_event_handle(); - if(overlapped) + if(priv->overlapped) { DWORD ret; - if(!GetOverlappedResult(handle[0], overlapped, &ret, !buf_avail)) - throw SystemError("Reading from pipe failed", GetLastError()); + if(!GetOverlappedResult(*handle[0], priv->overlapped, &ret, !priv->buf_avail)) + throw system_error("GetOverlappedResult"); else { - buf_avail += ret; - delete overlapped; - overlapped = 0; + priv->buf_avail += ret; + delete priv->overlapped; + priv->overlapped = 0; } } - unsigned ret = min(buf_avail, size); - memcpy(buf, buf_next, ret); - buf_next += ret; - buf_avail -= ret; + unsigned ret = min(priv->buf_avail, size); + memcpy(buf, priv->buf_next, ret); + priv->buf_next += ret; + priv->buf_avail -= ret; // Initiate another overlapped read in case someone is polling us get_event_handle(); #else - int ret = ::read(handle[0], buf, size); + int ret = ::read(*handle[0], buf, size); if(ret==-1) { if(errno==EAGAIN) return 0; else - throw SystemError("Reading from pipe failed", errno); + throw system_error("read"); } #endif @@ -146,33 +172,33 @@ unsigned Pipe::do_read(char *buf, unsigned size) return ret; } -Handle Pipe::get_event_handle() +const Handle &Pipe::get_event_handle() { #ifdef WIN32 - if(!overlapped && !buf_avail) + if(!priv->overlapped && !priv->buf_avail) { - overlapped = new OVERLAPPED; - memset(overlapped, 0, sizeof(OVERLAPPED)); - overlapped->hEvent = event; + priv->overlapped = new OVERLAPPED; + memset(priv->overlapped, 0, sizeof(OVERLAPPED)); + priv->overlapped->hEvent = *priv->event; DWORD ret; - buf_next = buffer; - if(!ReadFile(handle[0], buffer, buf_size, &ret, overlapped)) + priv->buf_next = priv->buffer; + if(!ReadFile(*handle[0], priv->buffer, priv->buf_size, &ret, priv->overlapped)) { unsigned err = GetLastError(); if(err!=ERROR_IO_PENDING) - throw SystemError("Failed to start an overlapped read", err); + throw system_error("ReadFile"); } else { - buf_avail = ret; - delete overlapped; - overlapped = 0; - SetEvent(event); + priv->buf_avail = ret; + delete priv->overlapped; + priv->overlapped = 0; + SetEvent(*priv->event); } } - return event; + return priv->event; #else return handle[0]; #endif