]> git.tdb.fi Git - libs/core.git/blob - source/io/eventreader.cpp
Use EventReader in pipe
[libs/core.git] / source / io / eventreader.cpp
1 #ifdef WIN32
2 #include <windows.h>
3 #endif
4 #include <algorithm>
5 #include <msp/core/systemerror.h>
6 #include "eventreader.h"
7 #include "handle_private.h"
8
9 using namespace std;
10
11 namespace Msp {
12 namespace IO {
13
14 struct EventReader::Private
15 {
16 #ifdef WIN32
17         OVERLAPPED *overlapped;
18         Handle event;
19         unsigned buf_size;
20         char *buffer;
21         unsigned buf_avail;
22         char *buf_next;
23 #endif
24 };
25
26
27 EventReader::EventReader(Handle &h, unsigned size):
28         handle(h),
29         priv(0)
30 {
31 #ifdef WIN32
32         priv = new Private;
33
34         priv->overlapped = 0;
35         *priv->event = CreateEvent(0, true, false, 0);
36         priv->buf_size = size;
37         priv->buffer = new char[priv->buf_size];
38         priv->buf_avail = 0;
39         priv->buf_next = priv->buffer;
40
41         start();
42 #else
43         (void)size;
44 #endif
45 }
46
47 EventReader::~EventReader()
48 {
49 #ifdef WIN32
50         CloseHandle(*priv->event);
51         delete priv->overlapped;
52         delete[] priv->buffer;
53 #endif
54         delete priv;
55 }
56
57 const Handle &EventReader::get_event() const
58 {
59 #ifdef WIN32
60         return priv->event;
61 #else
62         return handle;
63 #endif
64 }
65
66 void EventReader::start()
67 {
68 #ifdef WIN32
69         if(priv->buf_avail || priv->overlapped)
70                 return;
71
72         priv->overlapped = new OVERLAPPED;
73         memset(priv->overlapped, 0, sizeof(OVERLAPPED));
74         priv->overlapped->hEvent = *priv->event;
75
76         DWORD ret;
77         priv->buf_next = priv->buffer;
78         if(!ReadFile(*handle, priv->buffer, priv->buf_size, &ret, priv->overlapped))
79         {
80                 unsigned err = GetLastError();
81                 if(err!=ERROR_IO_PENDING)
82                         throw system_error("ReadFile");
83         }
84         else
85         {
86                 priv->buf_avail = ret;
87                 delete priv->overlapped;
88                 priv->overlapped = 0;
89                 SetEvent(*priv->event);
90         }
91 #endif
92 }
93
94 void EventReader::wait()
95 {
96 #ifdef WIN32
97         if(!priv->overlapped)
98                 return;
99
100         DWORD ret;
101         if(!GetOverlappedResult(*handle, priv->overlapped, &ret, true))
102                 throw system_error("GetOverlappedResult");
103         else
104         {
105                 priv->buf_avail = ret;
106                 delete priv->overlapped;
107                 priv->overlapped = 0;
108         }
109 #endif
110 }
111
112 unsigned EventReader::read(char *buf, unsigned len)
113 {
114 #ifdef WIN32
115         if(!priv->buf_avail)
116         {
117                 // No data in buffer, try to get some
118                 start();
119                 wait();
120         }
121
122         len = min(len, priv->buf_avail);
123         memcpy(buf, priv->buf_next, len);
124         priv->buf_next += len;
125         priv->buf_avail -= len;
126
127         if(!priv->buf_avail)
128         {
129                 ResetEvent(*priv->event);
130                 start();
131         }
132
133         return len;
134 #else
135         return sys_read(handle, buf, len);
136 #endif
137 }
138
139 } // namespace IO
140 } // namespace Msp