comparison tango/tango/sys/Pipe.d @ 132:1700239cab2e trunk

[svn r136] MAJOR UNSTABLE UPDATE!!! Initial commit after moving to Tango instead of Phobos. Lots of bugfixes... This build is not suitable for most things.
author lindquist
date Fri, 11 Jan 2008 17:57:40 +0100
parents
children
comparison
equal deleted inserted replaced
131:5825d48b27d1 132:1700239cab2e
1 /*******************************************************************************
2 copyright: Copyright (c) 2006 Juan Jose Comellas. All rights reserved
3 license: BSD style: $(LICENSE)
4 author: Juan Jose Comellas <juanjo@comellas.com.ar>
5 *******************************************************************************/
6
7 module tango.sys.Pipe;
8
9 private import tango.sys.Common;
10 private import tango.io.Buffer;
11 private import tango.io.DeviceConduit;
12
13 private import tango.core.Exception;
14
15 version (Posix)
16 {
17 private import tango.stdc.posix.unistd;
18 }
19
20 debug (PipeConduit)
21 {
22 private import tango.io.Stdout;
23 }
24
25
26 /**
27 * Conduit for pipes.
28 *
29 * Each PipeConduit can only read or write, depending on the way it has been
30 * created.
31 */
32 class PipeConduit: DeviceConduit
33 {
34 version (OLD)
35 {
36 alias DeviceConduit.fileHandle fileHandle;
37 alias DeviceConduit.copy copy;
38 alias DeviceConduit.read read;
39 alias DeviceConduit.write write;
40 alias DeviceConduit.close close;
41 alias DeviceConduit.error error;
42 }
43
44 static const uint DefaultBufferSize = 8 * 1024;
45
46 private uint _bufferSize;
47
48
49 /**
50 * Create a PipeConduit with the provided handle and access permissions.
51 *
52 * Params:
53 * handle = handle of the operating system pipe we will wrap inside
54 * the PipeConduit.
55 * style = access flags for the pipe (readable, writable, etc.).
56 * bufferSize = buffer size.
57 */
58 private this(ISelectable.Handle handle,
59 uint bufferSize = DefaultBufferSize)
60 {
61 version (Win32)
62 this.handle = cast(HANDLE) handle;
63 else
64 this.handle = handle;
65 _bufferSize = bufferSize;
66 }
67
68 /**
69 * Destructor.
70 */
71 public ~this()
72 {
73 close();
74 }
75
76 /**
77 * Returns the buffer size for the PipeConduit.
78 */
79 public override uint bufferSize()
80 {
81 return _bufferSize;
82 }
83
84 /**
85 * Returns the name of the device.
86 */
87 public override char[] toString()
88 {
89 return "<pipe>";
90 }
91
92 version (OLD)
93 {
94 /**
95 * Read a chunk of bytes from the file into the provided array
96 * (typically that belonging to an IBuffer)
97 */
98 protected override uint read (void[] dst)
99 {
100 uint result;
101 DWORD read;
102 void *p = dst.ptr;
103
104 if (!ReadFile (handle, p, dst.length, &read, null))
105 {
106 if (SysError.lastCode() == ERROR_BROKEN_PIPE)
107 {
108 return Eof;
109 }
110 else
111 {
112 error();
113 }
114 }
115
116 if (read == 0 && dst.length > 0)
117 {
118 return Eof;
119 }
120 return read;
121 }
122
123 /**
124 * Write a chunk of bytes to the file from the provided array
125 * (typically that belonging to an IBuffer).
126 */
127 protected override uint write (void[] src)
128 {
129 DWORD written;
130
131 if (!WriteFile (handle, src.ptr, src.length, &written, null))
132 {
133 error();
134 }
135 return written;
136 }
137 }
138 }
139
140 /**
141 * Factory class for Pipes.
142 */
143 class Pipe
144 {
145 private PipeConduit _source;
146 private PipeConduit _sink;
147
148 /**
149 * Create a Pipe.
150 */
151 public this(uint bufferSize = PipeConduit.DefaultBufferSize)
152 {
153 version (Windows)
154 {
155 this(bufferSize, null);
156 }
157 else version (Posix)
158 {
159 int fd[2];
160
161 if (pipe(fd) == 0)
162 {
163 _source = new PipeConduit(cast(ISelectable.Handle) fd[0], bufferSize);
164 _sink = new PipeConduit(cast(ISelectable.Handle) fd[1], bufferSize);
165 }
166 else
167 {
168 error();
169 }
170 }
171 else
172 {
173 assert(false, "Unknown platform");
174 }
175 }
176
177 version (Windows)
178 {
179 /**
180 * Helper constructor for pipes on Windows with non-null security
181 * attributes.
182 */
183 package this(uint bufferSize, SECURITY_ATTRIBUTES *sa)
184 {
185 HANDLE sourceHandle;
186 HANDLE sinkHandle;
187
188 if (CreatePipe(&sourceHandle, &sinkHandle, sa, cast(DWORD) bufferSize))
189 {
190 _source = new PipeConduit(cast(ISelectable.Handle) sourceHandle);
191 _sink = new PipeConduit(cast(ISelectable.Handle) sinkHandle);
192 }
193 else
194 {
195 error();
196 }
197 }
198 }
199
200 /**
201 * Return the PipeConduit that you can write to.
202 */
203 public PipeConduit sink()
204 {
205 return _sink;
206 }
207
208 /**
209 * Return the PipeConduit that you can read from.
210 */
211 public PipeConduit source()
212 {
213 return _source;
214 }
215
216 /**
217 *
218 */
219 private final void error ()
220 {
221 throw new IOException("Pipe error: " ~ SysError.lastMsg);
222 }
223 }
224