1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The EventLoop and internal synchronous I/O interface.
15 use comm::{Sender, Receiver};
20 use option::{Option, Some, None};
28 use ai = io::net::addrinfo;
31 use io::net::ip::{IpAddr, SocketAddr};
32 use io::process::{ProcessConfig, ProcessExit};
33 use io::signal::Signum;
34 use io::{FileMode, FileAccess, FileStat, FilePermission};
43 fn callback(&mut self, arg: proc():Send);
44 fn pausable_idle_callback(&mut self, Box<Callback:Send>)
45 -> Box<PausableIdleCallback:Send>;
46 fn remote_callback(&mut self, Box<Callback:Send>)
47 -> Box<RemoteCallback:Send>;
49 /// The asynchronous I/O services. Not all event loops may provide one.
50 fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory>;
51 fn has_active_io(&self) -> bool;
54 pub trait RemoteCallback {
55 /// Trigger the remote callback. Note that the number of times the
56 /// callback is run is not guaranteed. All that is guaranteed is
57 /// that, after calling 'fire', the callback will be called at
58 /// least once, but multiple callbacks may be coalesced and
59 /// callbacks may be called more often requested. Destruction also
60 /// triggers the callback.
64 /// Data needed to make a successful open(2) call
65 /// Using unix flag conventions for now, which happens to also be what's supported
66 /// libuv (it does translation to windows under the hood).
67 pub struct FileOpenConfig {
68 /// Path to file to be opened
70 /// Flags for file access mode (as per open(2))
72 /// File creation mode, ignored unless O_CREAT is passed as part of flags
76 /// Description of what to do when a file handle is closed
77 pub enum CloseBehavior {
78 /// Do not close this handle when the object is destroyed
80 /// Synchronously close the handle, meaning that the task will block when
81 /// the handle is destroyed until it has been fully closed.
83 /// Asynchronously closes a handle, meaning that the task will *not* block
84 /// when the handle is destroyed, but the handle will still get deallocated
85 /// and cleaned up (but this will happen asynchronously on the local event
90 pub struct LocalIo<'a> {
91 factory: &'a mut IoFactory,
95 impl<'a> Drop for LocalIo<'a> {
97 // FIXME(pcwalton): Do nothing here for now, but eventually we may want
98 // something. For now this serves to make `LocalIo` noncopyable.
102 impl<'a> LocalIo<'a> {
103 /// Returns the local I/O: either the local scheduler's I/O services or
104 /// the native I/O services.
105 pub fn borrow() -> Option<LocalIo> {
106 // FIXME(#11053): bad
108 // This is currently very unsafely implemented. We don't actually
109 // *take* the local I/O so there's a very real possibility that we
110 // can have two borrows at once. Currently there is not a clear way
111 // to actually borrow the local I/O factory safely because even if
112 // ownership were transferred down to the functions that the I/O
113 // factory implements it's just too much of a pain to know when to
114 // relinquish ownership back into the local task (but that would be
115 // the safe way of implementing this function).
117 // In order to get around this, we just transmute a copy out of the task
118 // in order to have what is likely a static lifetime (bad).
119 let mut t: Box<Task> = Local::take();
120 let ret = t.local_io().map(|t| {
121 unsafe { cast::transmute_copy(&t) }
127 pub fn maybe_raise<T>(f: |io: &mut IoFactory| -> IoResult<T>)
130 match LocalIo::borrow() {
131 None => Err(io::standard_error(io::IoUnavailable)),
132 Some(mut io) => f(io.get()),
136 pub fn new<'a>(io: &'a mut IoFactory) -> LocalIo<'a> {
137 LocalIo { factory: io }
140 /// Returns the underlying I/O factory as a trait reference.
142 pub fn get<'a>(&'a mut self) -> &'a mut IoFactory {
143 // FIXME(pcwalton): I think this is actually sound? Could borrow check
144 // allow this safely?
146 cast::transmute_copy(&self.factory)
151 pub trait IoFactory {
153 fn tcp_connect(&mut self, addr: SocketAddr,
154 timeout: Option<u64>) -> IoResult<Box<RtioTcpStream:Send>>;
155 fn tcp_bind(&mut self, addr: SocketAddr)
156 -> IoResult<Box<RtioTcpListener:Send>>;
157 fn udp_bind(&mut self, addr: SocketAddr)
158 -> IoResult<Box<RtioUdpSocket:Send>>;
159 fn unix_bind(&mut self, path: &CString)
160 -> IoResult<Box<RtioUnixListener:Send>>;
161 fn unix_connect(&mut self, path: &CString,
162 timeout: Option<u64>) -> IoResult<Box<RtioPipe:Send>>;
163 fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
164 hint: Option<ai::Hint>) -> IoResult<~[ai::Info]>;
166 // filesystem operations
167 fn fs_from_raw_fd(&mut self, fd: c_int, close: CloseBehavior)
168 -> Box<RtioFileStream:Send>;
169 fn fs_open(&mut self, path: &CString, fm: FileMode, fa: FileAccess)
170 -> IoResult<Box<RtioFileStream:Send>>;
171 fn fs_unlink(&mut self, path: &CString) -> IoResult<()>;
172 fn fs_stat(&mut self, path: &CString) -> IoResult<FileStat>;
173 fn fs_mkdir(&mut self, path: &CString,
174 mode: FilePermission) -> IoResult<()>;
175 fn fs_chmod(&mut self, path: &CString,
176 mode: FilePermission) -> IoResult<()>;
177 fn fs_rmdir(&mut self, path: &CString) -> IoResult<()>;
178 fn fs_rename(&mut self, path: &CString, to: &CString) -> IoResult<()>;
179 fn fs_readdir(&mut self, path: &CString, flags: c_int) ->
181 fn fs_lstat(&mut self, path: &CString) -> IoResult<FileStat>;
182 fn fs_chown(&mut self, path: &CString, uid: int, gid: int) ->
184 fn fs_readlink(&mut self, path: &CString) -> IoResult<Path>;
185 fn fs_symlink(&mut self, src: &CString, dst: &CString) -> IoResult<()>;
186 fn fs_link(&mut self, src: &CString, dst: &CString) -> IoResult<()>;
187 fn fs_utime(&mut self, src: &CString, atime: u64, mtime: u64) ->
191 fn timer_init(&mut self) -> IoResult<Box<RtioTimer:Send>>;
192 fn spawn(&mut self, config: ProcessConfig)
193 -> IoResult<(Box<RtioProcess:Send>,
194 ~[Option<Box<RtioPipe:Send>>])>;
195 fn kill(&mut self, pid: libc::pid_t, signal: int) -> IoResult<()>;
196 fn pipe_open(&mut self, fd: c_int) -> IoResult<Box<RtioPipe:Send>>;
197 fn tty_open(&mut self, fd: c_int, readable: bool)
198 -> IoResult<Box<RtioTTY:Send>>;
199 fn signal(&mut self, signal: Signum, channel: Sender<Signum>)
200 -> IoResult<Box<RtioSignal:Send>>;
203 pub trait RtioTcpListener : RtioSocket {
204 fn listen(~self) -> IoResult<Box<RtioTcpAcceptor:Send>>;
207 pub trait RtioTcpAcceptor : RtioSocket {
208 fn accept(&mut self) -> IoResult<Box<RtioTcpStream:Send>>;
209 fn accept_simultaneously(&mut self) -> IoResult<()>;
210 fn dont_accept_simultaneously(&mut self) -> IoResult<()>;
211 fn set_timeout(&mut self, timeout: Option<u64>);
214 pub trait RtioTcpStream : RtioSocket {
215 fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
216 fn write(&mut self, buf: &[u8]) -> IoResult<()>;
217 fn peer_name(&mut self) -> IoResult<SocketAddr>;
218 fn control_congestion(&mut self) -> IoResult<()>;
219 fn nodelay(&mut self) -> IoResult<()>;
220 fn keepalive(&mut self, delay_in_seconds: uint) -> IoResult<()>;
221 fn letdie(&mut self) -> IoResult<()>;
222 fn clone(&self) -> Box<RtioTcpStream:Send>;
223 fn close_write(&mut self) -> IoResult<()>;
226 pub trait RtioSocket {
227 fn socket_name(&mut self) -> IoResult<SocketAddr>;
230 pub trait RtioUdpSocket : RtioSocket {
231 fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)>;
232 fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()>;
234 fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
235 fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
237 fn loop_multicast_locally(&mut self) -> IoResult<()>;
238 fn dont_loop_multicast_locally(&mut self) -> IoResult<()>;
240 fn multicast_time_to_live(&mut self, ttl: int) -> IoResult<()>;
241 fn time_to_live(&mut self, ttl: int) -> IoResult<()>;
243 fn hear_broadcasts(&mut self) -> IoResult<()>;
244 fn ignore_broadcasts(&mut self) -> IoResult<()>;
246 fn clone(&self) -> Box<RtioUdpSocket:Send>;
249 pub trait RtioTimer {
250 fn sleep(&mut self, msecs: u64);
251 fn oneshot(&mut self, msecs: u64) -> Receiver<()>;
252 fn period(&mut self, msecs: u64) -> Receiver<()>;
255 pub trait RtioFileStream {
256 fn read(&mut self, buf: &mut [u8]) -> IoResult<int>;
257 fn write(&mut self, buf: &[u8]) -> IoResult<()>;
258 fn pread(&mut self, buf: &mut [u8], offset: u64) -> IoResult<int>;
259 fn pwrite(&mut self, buf: &[u8], offset: u64) -> IoResult<()>;
260 fn seek(&mut self, pos: i64, whence: SeekStyle) -> IoResult<u64>;
261 fn tell(&self) -> IoResult<u64>;
262 fn fsync(&mut self) -> IoResult<()>;
263 fn datasync(&mut self) -> IoResult<()>;
264 fn truncate(&mut self, offset: i64) -> IoResult<()>;
267 pub trait RtioProcess {
268 fn id(&self) -> libc::pid_t;
269 fn kill(&mut self, signal: int) -> IoResult<()>;
270 fn wait(&mut self) -> ProcessExit;
274 fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
275 fn write(&mut self, buf: &[u8]) -> IoResult<()>;
276 fn clone(&self) -> Box<RtioPipe:Send>;
279 pub trait RtioUnixListener {
280 fn listen(~self) -> IoResult<Box<RtioUnixAcceptor:Send>>;
283 pub trait RtioUnixAcceptor {
284 fn accept(&mut self) -> IoResult<Box<RtioPipe:Send>>;
285 fn set_timeout(&mut self, timeout: Option<u64>);
289 fn read(&mut self, buf: &mut [u8]) -> IoResult<uint>;
290 fn write(&mut self, buf: &[u8]) -> IoResult<()>;
291 fn set_raw(&mut self, raw: bool) -> IoResult<()>;
292 fn get_winsize(&mut self) -> IoResult<(int, int)>;
293 fn isatty(&self) -> bool;
296 pub trait PausableIdleCallback {
298 fn resume(&mut self);
301 pub trait RtioSignal {}