5 #include <msp/core/systemerror.h>
6 #include <msp/strings/formatter.h>
7 #include "handle_private.h"
18 OVERLAPPED *overlapped;
32 string name = format("\\\\.\\pipe\\%u.%p", GetCurrentProcessId(), this);
33 *handle[0] = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0);
35 throw system_error("CreateNamedPipe");
37 *handle[1] = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
40 unsigned err = GetLastError();
41 CloseHandle(*handle[0]);
42 throw system_error(format("CreateFile(%s)", name), err);
47 *priv->event = CreateEvent(0, true, false, 0);
48 priv->buf_size = 1024;
49 priv->buffer = new char[priv->buf_size];
51 priv->buf_next = priv->buffer;
55 throw system_error("pipe");
57 *handle[0] = pipe_fd[0];
58 *handle[1] = pipe_fd[1];
68 CloseHandle(*priv->event);
78 signal_flush_required.emit();
80 CloseHandle(*handle[0]);
81 CloseHandle(*handle[1]);
89 void Pipe::set_block(bool b)
91 mode = (mode&~M_NONBLOCK);
93 mode = (mode|M_NONBLOCK);
96 int flags = fcntl(*handle[0], F_GETFD);
97 fcntl(*handle[0], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
98 flags = fcntl(*handle[1], F_GETFD);
99 fcntl(*handle[1], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
103 unsigned Pipe::do_write(const char *buf, unsigned size)
110 if(!WriteFile(*handle[1], buf, size, &ret, 0))
111 throw system_error("WriteFile");
113 int ret = ::write(*handle[1], buf, size);
119 throw system_error("write");
126 unsigned Pipe::do_read(char *buf, unsigned size)
132 // Initiate overlapped read if needed
138 if(!GetOverlappedResult(*handle[0], priv->overlapped, &ret, !priv->buf_avail))
139 throw system_error("GetOverlappedResult");
142 priv->buf_avail += ret;
143 delete priv->overlapped;
144 priv->overlapped = 0;
148 unsigned ret = min(priv->buf_avail, size);
149 memcpy(buf, priv->buf_next, ret);
150 priv->buf_next += ret;
151 priv->buf_avail -= ret;
153 // Initiate another overlapped read in case someone is polling us
156 int ret = ::read(*handle[0], buf, size);
162 throw system_error("read");
169 signal_end_of_file.emit();
175 const Handle &Pipe::get_event_handle()
178 if(!priv->overlapped && !priv->buf_avail)
180 priv->overlapped = new OVERLAPPED;
181 memset(priv->overlapped, 0, sizeof(OVERLAPPED));
182 priv->overlapped->hEvent = *priv->event;
185 priv->buf_next = priv->buffer;
186 if(!ReadFile(*handle[0], priv->buffer, priv->buf_size, &ret, priv->overlapped))
188 unsigned err = GetLastError();
189 if(err!=ERROR_IO_PENDING)
190 throw system_error("ReadFile");
194 priv->buf_avail = ret;
195 delete priv->overlapped;
196 priv->overlapped = 0;
197 SetEvent(*priv->event);