Mercurial > projects > ldc
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 |