5 #include <msp/core/systemerror.h>
6 #include <msp/strings/formatter.h>
17 OVERLAPPED *overlapped;
31 string name = format("\\\\.\\pipe\\%u.%p", GetCurrentProcessId(), this);
32 handle[0] = CreateNamedPipe(name.c_str(), PIPE_ACCESS_INBOUND|FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE, 1, 1024, 1024, 0, 0);
33 if(handle[0]==INVALID_HANDLE_VALUE)
34 throw system_error("CreateNamedPipe");
36 handle[1] = CreateFile(name.c_str(), GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
37 if(handle[1]==INVALID_HANDLE_VALUE)
39 unsigned err = GetLastError();
40 CloseHandle(handle[0]);
41 throw system_error(format("CreateFile(%s)", name), err);
46 priv->event = CreateEvent(0, true, false, 0);
47 priv->buf_size = 1024;
48 priv->buffer = new char[priv->buf_size];
50 priv->buf_next = priv->buffer;
53 throw system_error("pipe");
63 CloseHandle(priv->event);
73 signal_flush_required.emit();
75 CloseHandle(handle[0]);
76 CloseHandle(handle[1]);
84 void Pipe::set_block(bool b)
86 mode = (mode&~M_NONBLOCK);
88 mode = (mode|M_NONBLOCK);
91 int flags = fcntl(handle[0], F_GETFD);
92 fcntl(handle[0], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
93 flags = fcntl(handle[1], F_GETFD);
94 fcntl(handle[1], F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK));
98 unsigned Pipe::do_write(const char *buf, unsigned size)
105 if(!WriteFile(handle[1], buf, size, &ret, 0))
106 throw system_error("WriteFile");
108 int ret = ::write(handle[1], buf, size);
114 throw system_error("write");
121 unsigned Pipe::do_read(char *buf, unsigned size)
127 // Initiate overlapped read if needed
133 if(!GetOverlappedResult(handle[0], priv->overlapped, &ret, !priv->buf_avail))
134 throw system_error("GetOverlappedResult");
137 priv->buf_avail += ret;
138 delete priv->overlapped;
139 priv->overlapped = 0;
143 unsigned ret = min(priv->buf_avail, size);
144 memcpy(buf, priv->buf_next, ret);
145 priv->buf_next += ret;
146 priv->buf_avail -= ret;
148 // Initiate another overlapped read in case someone is polling us
151 int ret = ::read(handle[0], buf, size);
157 throw system_error("read");
164 signal_end_of_file.emit();
170 Handle Pipe::get_event_handle()
173 if(!priv->overlapped && !priv->buf_avail)
175 priv->overlapped = new OVERLAPPED;
176 memset(priv->overlapped, 0, sizeof(OVERLAPPED));
177 priv->overlapped->hEvent = priv->event;
180 priv->buf_next = priv->buffer;
181 if(!ReadFile(handle[0], priv->buffer, priv->buf_size, &ret, priv->overlapped))
183 unsigned err = GetLastError();
184 if(err!=ERROR_IO_PENDING)
185 throw system_error("ReadFile");
189 priv->buf_avail = ret;
190 delete priv->overlapped;
191 priv->overlapped = 0;
192 SetEvent(priv->event);