X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fio%2Fpipe.cpp;h=0f206981f11c6d1e205d127d281655965559187e;hp=2975a0635074e981aea9dc909cdef5f872d3ca36;hb=651cfe05e867ffdef9028a831add3eca54d19d0d;hpb=378ec811c8df431f5b4e7094eb1949476d3a79fe diff --git a/source/io/pipe.cpp b/source/io/pipe.cpp index 2975a06..0f20698 100644 --- a/source/io/pipe.cpp +++ b/source/io/pipe.cpp @@ -1,9 +1,11 @@ #ifndef WIN32 #include #include +#include #endif #include -#include +#include +#include "handle_private.h" #include "pipe.h" using namespace std; @@ -11,74 +13,43 @@ using namespace std; namespace Msp { namespace IO { -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) + reader(read_handle, 1024) { + mode = M_RDWR; + #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) + *read_handle = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0); + if(!read_handle) throw system_error("CreateNamedPipe"); - handle[1] = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0); - if(handle[1]==INVALID_HANDLE_VALUE) + *write_handle = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0); + if(!write_handle) { unsigned err = GetLastError(); - CloseHandle(handle[0]); + CloseHandle(*read_handle); throw system_error(format("CreateFile(%s)", name), err); } - - 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) + int pipe_fd[2]; + if(pipe(pipe_fd)==-1) throw system_error("pipe"); + + *read_handle = pipe_fd[0]; + *write_handle = pipe_fd[1]; #endif set_events(P_INPUT); } Pipe::~Pipe() -{ - close(); -#ifdef WIN32 - CloseHandle(priv->event); - delete priv->buffer; -#endif - delete priv; -} - -void Pipe::close() { set_events(P_NONE); signal_flush_required.emit(); -#ifdef WIN32 - CloseHandle(handle[0]); - CloseHandle(handle[1]); -#else - ::close(handle[0]); - ::close(handle[1]); - signal_closed.emit(); -#endif + sys_close(read_handle); + sys_close(write_handle); } void Pipe::set_block(bool b) @@ -88,10 +59,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(*read_handle, F_GETFD); + fcntl(*read_handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); + flags = fcntl(*write_handle, F_GETFD); + fcntl(*write_handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); #endif } @@ -100,22 +71,7 @@ unsigned Pipe::do_write(const char *buf, unsigned size) if(size==0) return 0; -#ifdef WIN32 - DWORD ret; - if(!WriteFile(handle[1], buf, size, &ret, 0)) - throw system_error("WriteFile"); -#else - int ret = ::write(handle[1], buf, size); - if(ret==-1) - { - if(errno==EAGAIN) - return 0; - else - throw system_error("write"); - } -#endif - - return ret; + return sys_write(write_handle, buf, size); } unsigned Pipe::do_read(char *buf, unsigned size) @@ -123,80 +79,21 @@ unsigned Pipe::do_read(char *buf, unsigned size) if(size==0) return 0; -#ifdef WIN32 - // Initiate overlapped read if needed - get_event_handle(); - - if(priv->overlapped) - { - DWORD ret; - if(!GetOverlappedResult(handle[0], priv->overlapped, &ret, !priv->buf_avail)) - throw system_error("GetOverlappedResult"); - else - { - priv->buf_avail += ret; - delete priv->overlapped; - priv->overlapped = 0; - } - } - - 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); - if(ret==-1) - { - if(errno==EAGAIN) - return 0; - else - throw system_error("read"); - } -#endif - + unsigned ret = reader.read(buf, size); if(ret==0) - { - eof_flag = true; - signal_end_of_file.emit(); - } + set_eof(); return ret; } -Handle Pipe::get_event_handle() +const Handle &Pipe::get_handle(Mode m) { -#ifdef WIN32 - if(!priv->overlapped && !priv->buf_avail) - { - 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[0], 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); - } - } - - return priv->event; -#else - return handle[0]; -#endif + if(m==M_READ) + return read_handle; + else if(m==M_WRITE) + return write_handle; + else + throw invalid_argument("Pipe::get_handle"); } } // namespace IO