mirror of
https://github.com/denoland/deno.git
synced 2024-11-26 16:09:27 -05:00
Move eager functions into eager_unix.rs
This commit is contained in:
parent
58f0547e09
commit
ae00df73a2
3 changed files with 131 additions and 123 deletions
86
src/eager_unix.rs
Normal file
86
src/eager_unix.rs
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
// Copyright 2018 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use resources::{EagerAccept, EagerRead, EagerWrite, Resource};
|
||||||
|
use tokio_util;
|
||||||
|
use tokio_write;
|
||||||
|
|
||||||
|
use futures::future::{self, Either};
|
||||||
|
use std;
|
||||||
|
use std::io::{ErrorKind, Read, Write};
|
||||||
|
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
|
||||||
|
use tokio;
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio_io;
|
||||||
|
|
||||||
|
pub fn tcp_read<T: AsMut<[u8]>>(
|
||||||
|
tcp_stream: &TcpStream,
|
||||||
|
resource: Resource,
|
||||||
|
mut buf: T,
|
||||||
|
) -> EagerRead<Resource, T> {
|
||||||
|
// Unforunately we can't just call read() on tokio::net::TcpStream
|
||||||
|
let fd = (*tcp_stream).as_raw_fd();
|
||||||
|
let mut std_tcp_stream = unsafe { std::net::TcpStream::from_raw_fd(fd) };
|
||||||
|
let read_result = std_tcp_stream.read(buf.as_mut());
|
||||||
|
// std_tcp_stream will close when it gets dropped. Thus...
|
||||||
|
let _ = std_tcp_stream.into_raw_fd();
|
||||||
|
match read_result {
|
||||||
|
Ok(nread) => Either::B(future::ok((resource, buf, nread))),
|
||||||
|
Err(err) => {
|
||||||
|
if err.kind() == ErrorKind::WouldBlock {
|
||||||
|
Either::A(tokio_io::io::read(resource, buf))
|
||||||
|
} else {
|
||||||
|
Either::B(future::err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tcp_write<T: AsRef<[u8]>>(
|
||||||
|
tcp_stream: &TcpStream,
|
||||||
|
resource: Resource,
|
||||||
|
buf: T,
|
||||||
|
) -> EagerWrite<Resource, T> {
|
||||||
|
let fd = (*tcp_stream).as_raw_fd();
|
||||||
|
let mut std_tcp_stream = unsafe { std::net::TcpStream::from_raw_fd(fd) };
|
||||||
|
let write_result = std_tcp_stream.write(buf.as_ref());
|
||||||
|
// std_tcp_stream will close when it gets dropped. Thus...
|
||||||
|
let _ = std_tcp_stream.into_raw_fd();
|
||||||
|
match write_result {
|
||||||
|
Ok(nwrite) => Either::B(future::ok((resource, buf, nwrite))),
|
||||||
|
Err(err) => {
|
||||||
|
if err.kind() == ErrorKind::WouldBlock {
|
||||||
|
Either::A(tokio_write::write(resource, buf))
|
||||||
|
} else {
|
||||||
|
Either::B(future::err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tcp_accept(
|
||||||
|
tcp_listener: &TcpListener,
|
||||||
|
resource: Resource,
|
||||||
|
) -> EagerAccept {
|
||||||
|
let fd = (*tcp_listener).as_raw_fd();
|
||||||
|
let std_listener = unsafe { std::net::TcpListener::from_raw_fd(fd) };
|
||||||
|
let result = std_listener.accept();
|
||||||
|
// std_listener will close when it gets dropped. Thus...
|
||||||
|
let _ = std_listener.into_raw_fd();
|
||||||
|
match result {
|
||||||
|
Ok((std_stream, addr)) => {
|
||||||
|
let result = tokio::net::TcpStream::from_std(
|
||||||
|
std_stream,
|
||||||
|
&tokio::reactor::Handle::default(),
|
||||||
|
);
|
||||||
|
let tokio_stream = result.unwrap();
|
||||||
|
Either::B(future::ok((tokio_stream, addr)))
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
if err.kind() == ErrorKind::WouldBlock {
|
||||||
|
Either::A(tokio_util::accept(resource))
|
||||||
|
} else {
|
||||||
|
Either::B(future::err(err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,6 +36,9 @@ mod tokio_util;
|
||||||
mod tokio_write;
|
mod tokio_write;
|
||||||
mod version;
|
mod version;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
mod eager_unix;
|
||||||
|
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
static LOGGER: Logger = Logger;
|
static LOGGER: Logger = Logger;
|
||||||
|
|
165
src/resources.rs
165
src/resources.rs
|
@ -8,18 +8,18 @@
|
||||||
// descriptors". This module implements a global resource table. Ops (AKA
|
// descriptors". This module implements a global resource table. Ops (AKA
|
||||||
// handlers) look up resources by their integer id here.
|
// handlers) look up resources by their integer id here.
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use eager_unix as eager;
|
||||||
use errors::DenoError;
|
use errors::DenoError;
|
||||||
use tokio_util;
|
use tokio_util;
|
||||||
use tokio_write;
|
use tokio_write;
|
||||||
|
|
||||||
use futures;
|
use futures;
|
||||||
use futures::future::Either;
|
use futures::future::{Either, FutureResult};
|
||||||
use futures::future::FutureResult;
|
|
||||||
use futures::Poll;
|
use futures::Poll;
|
||||||
use std;
|
use std;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::io::Error;
|
use std::io::{Error, Read, Write};
|
||||||
use std::io::{Read, Write};
|
|
||||||
use std::net::{Shutdown, SocketAddr};
|
use std::net::{Shutdown, SocketAddr};
|
||||||
use std::sync::atomic::AtomicIsize;
|
use std::sync::atomic::AtomicIsize;
|
||||||
use std::sync::atomic::Ordering;
|
use std::sync::atomic::Ordering;
|
||||||
|
@ -194,161 +194,80 @@ pub fn lookup(rid: ResourceId) -> Option<Resource> {
|
||||||
table.get(&rid).map(|_| Resource { rid })
|
table.get(&rid).map(|_| Resource { rid })
|
||||||
}
|
}
|
||||||
|
|
||||||
type EagerRead<R, T> =
|
pub type EagerRead<R, T> =
|
||||||
Either<tokio_io::io::Read<R, T>, FutureResult<(R, T, usize), std::io::Error>>;
|
Either<tokio_io::io::Read<R, T>, FutureResult<(R, T, usize), std::io::Error>>;
|
||||||
|
|
||||||
#[cfg(windows)]
|
pub type EagerWrite<R, T> =
|
||||||
|
Either<tokio_write::Write<R, T>, FutureResult<(R, T, usize), std::io::Error>>;
|
||||||
|
|
||||||
|
pub type EagerAccept = Either<
|
||||||
|
tokio_util::Accept,
|
||||||
|
FutureResult<(tokio::net::TcpStream, std::net::SocketAddr), std::io::Error>,
|
||||||
|
>;
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
pub fn eager_read<T>(resource: Resource, mut buf: T) -> EagerRead<Resource, T>
|
pub fn eager_read<T: AsMut<[u8]>>(
|
||||||
where
|
|
||||||
T: AsMut<[u8]>,
|
|
||||||
{
|
|
||||||
Either::A(tokio_io::io::read(resource, buf)).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
|
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
fn eager_read_tcp<T: AsMut<[u8]>>(
|
|
||||||
tcp_stream: &TcpStream,
|
|
||||||
resource: Resource,
|
resource: Resource,
|
||||||
mut buf: T,
|
mut buf: T,
|
||||||
) -> EagerRead<Resource, T> {
|
) -> EagerRead<Resource, T> {
|
||||||
// Unforunately we can't just call read() on tokio::net::TcpStream
|
Either::A(tokio_io::io::read(resource, buf)).into()
|
||||||
let fd = (*tcp_stream).as_raw_fd();
|
}
|
||||||
let mut std_tcp_stream = unsafe { std::net::TcpStream::from_raw_fd(fd) };
|
|
||||||
let read_result = std_tcp_stream.read(buf.as_mut());
|
#[cfg(not(unix))]
|
||||||
// std_tcp_stream will close when it gets dropped. Thus...
|
pub fn eager_write<T: AsRef<[u8]>>(
|
||||||
let _ = std_tcp_stream.into_raw_fd();
|
resource: Resource,
|
||||||
match read_result {
|
buf: T,
|
||||||
Ok(nread) => Either::B(futures::future::ok((resource, buf, nread))),
|
) -> EagerWrite<Resource, T> {
|
||||||
Err(err) => {
|
Either::A(tokio_write::write(resource, buf)).into()
|
||||||
if err.kind() == std::io::ErrorKind::WouldBlock {
|
}
|
||||||
Either::A(tokio_io::io::read(resource, buf))
|
|
||||||
} else {
|
#[cfg(not(unix))]
|
||||||
Either::B(futures::future::err(err))
|
pub fn eager_accept(resource: Resource) -> EagerAccept {
|
||||||
}
|
Either::A(tokio_util::accept(resource)).into()
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is an optimization that Tokio should do.
|
// This is an optimization that Tokio should do.
|
||||||
// Attempt to call read() on the main thread.
|
// Attempt to call read() on the main thread.
|
||||||
#[cfg(not(windows))]
|
#[cfg(unix)]
|
||||||
pub fn eager_read<T>(resource: Resource, buf: T) -> EagerRead<Resource, T>
|
pub fn eager_read<T: AsMut<[u8]>>(
|
||||||
where
|
resource: Resource,
|
||||||
T: AsMut<[u8]>,
|
buf: T,
|
||||||
{
|
) -> EagerRead<Resource, T> {
|
||||||
let mut table = RESOURCE_TABLE.lock().unwrap();
|
let mut table = RESOURCE_TABLE.lock().unwrap();
|
||||||
let maybe_repr = table.get_mut(&resource.rid);
|
let maybe_repr = table.get_mut(&resource.rid);
|
||||||
match maybe_repr {
|
match maybe_repr {
|
||||||
None => panic!("bad rid"),
|
None => panic!("bad rid"),
|
||||||
Some(repr) => match repr {
|
Some(repr) => match repr {
|
||||||
Repr::TcpStream(ref mut tcp_stream) => {
|
Repr::TcpStream(ref mut tcp_stream) => {
|
||||||
eager_read_tcp(tcp_stream, resource, buf)
|
eager::tcp_read(tcp_stream, resource, buf)
|
||||||
}
|
}
|
||||||
_ => Either::A(tokio_io::io::read(resource, buf)),
|
_ => Either::A(tokio_io::io::read(resource, buf)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type EagerWrite<R, T> =
|
// This is an optimization that Tokio should do.
|
||||||
Either<tokio_write::Write<R, T>, FutureResult<(R, T, usize), std::io::Error>>;
|
// Attempt to call write() on the main thread.
|
||||||
|
#[cfg(unix)]
|
||||||
#[cfg(windows)]
|
pub fn eager_write<T: AsRef<[u8]>>(
|
||||||
pub fn eager_write<T>(resource: Resource, buf: T) -> EagerWrite<Resource, T>
|
|
||||||
where
|
|
||||||
T: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
Either::A(tokio_write::write(resource, buf)).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
fn eager_write_tcp<T: AsRef<[u8]>>(
|
|
||||||
tcp_stream: &TcpStream,
|
|
||||||
resource: Resource,
|
resource: Resource,
|
||||||
buf: T,
|
buf: T,
|
||||||
) -> EagerWrite<Resource, T> {
|
) -> EagerWrite<Resource, T> {
|
||||||
let fd = (*tcp_stream).as_raw_fd();
|
|
||||||
let mut std_tcp_stream = unsafe { std::net::TcpStream::from_raw_fd(fd) };
|
|
||||||
let write_result = std_tcp_stream.write(buf.as_ref());
|
|
||||||
// std_tcp_stream will close when it gets dropped. Thus...
|
|
||||||
let _ = std_tcp_stream.into_raw_fd();
|
|
||||||
match write_result {
|
|
||||||
Ok(nwrite) => Either::B(futures::future::ok((resource, buf, nwrite))),
|
|
||||||
Err(err) => {
|
|
||||||
if err.kind() == std::io::ErrorKind::WouldBlock {
|
|
||||||
Either::A(tokio_write::write(resource, buf))
|
|
||||||
} else {
|
|
||||||
Either::B(futures::future::err(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is an optimization that Tokio should do.
|
|
||||||
// Attempt to call write() on the main thread.
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
pub fn eager_write<T>(resource: Resource, buf: T) -> EagerWrite<Resource, T>
|
|
||||||
where
|
|
||||||
T: AsRef<[u8]>,
|
|
||||||
{
|
|
||||||
let mut table = RESOURCE_TABLE.lock().unwrap();
|
let mut table = RESOURCE_TABLE.lock().unwrap();
|
||||||
let maybe_repr = table.get_mut(&resource.rid);
|
let maybe_repr = table.get_mut(&resource.rid);
|
||||||
match maybe_repr {
|
match maybe_repr {
|
||||||
None => panic!("bad rid"),
|
None => panic!("bad rid"),
|
||||||
Some(repr) => match repr {
|
Some(repr) => match repr {
|
||||||
Repr::TcpStream(ref mut tcp_stream) => {
|
Repr::TcpStream(ref mut tcp_stream) => {
|
||||||
eager_write_tcp(tcp_stream, resource, buf)
|
eager::tcp_write(tcp_stream, resource, buf)
|
||||||
}
|
}
|
||||||
_ => Either::A(tokio_write::write(resource, buf)),
|
_ => Either::A(tokio_write::write(resource, buf)),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type EagerAccept = Either<
|
#[cfg(unix)]
|
||||||
tokio_util::Accept,
|
|
||||||
FutureResult<(TcpStream, SocketAddr), std::io::Error>,
|
|
||||||
>;
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
pub fn eager_accept(resource: Resource) -> EagerAccept {
|
|
||||||
Either::A(tokio_util::accept(resource)).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
fn eager_accept_tcp(
|
|
||||||
tcp_listener: &tokio::net::TcpListener,
|
|
||||||
resource: Resource,
|
|
||||||
) -> EagerAccept {
|
|
||||||
let fd = (*tcp_listener).as_raw_fd();
|
|
||||||
let std_listener = unsafe { std::net::TcpListener::from_raw_fd(fd) };
|
|
||||||
let result = std_listener.accept();
|
|
||||||
// std_listener will close when it gets dropped. Thus...
|
|
||||||
let _ = std_listener.into_raw_fd();
|
|
||||||
match result {
|
|
||||||
Ok((std_stream, addr)) => {
|
|
||||||
let result = tokio::net::TcpStream::from_std(
|
|
||||||
std_stream,
|
|
||||||
&tokio::reactor::Handle::default(),
|
|
||||||
);
|
|
||||||
let tokio_stream = result.unwrap();
|
|
||||||
Either::B(futures::future::ok((tokio_stream, addr)))
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
if err.kind() == std::io::ErrorKind::WouldBlock {
|
|
||||||
Either::A(tokio_util::accept(resource))
|
|
||||||
} else {
|
|
||||||
Either::B(futures::future::err(err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is an optimization that Tokio should do.
|
|
||||||
// Attempt to call write() on the main thread.
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
pub fn eager_accept(resource: Resource) -> EagerAccept {
|
pub fn eager_accept(resource: Resource) -> EagerAccept {
|
||||||
let mut table = RESOURCE_TABLE.lock().unwrap();
|
let mut table = RESOURCE_TABLE.lock().unwrap();
|
||||||
let maybe_repr = table.get_mut(&resource.rid);
|
let maybe_repr = table.get_mut(&resource.rid);
|
||||||
|
@ -356,7 +275,7 @@ pub fn eager_accept(resource: Resource) -> EagerAccept {
|
||||||
None => panic!("bad rid"),
|
None => panic!("bad rid"),
|
||||||
Some(repr) => match repr {
|
Some(repr) => match repr {
|
||||||
Repr::TcpListener(ref mut tcp_listener) => {
|
Repr::TcpListener(ref mut tcp_listener) => {
|
||||||
eager_accept_tcp(tcp_listener, resource)
|
eager::tcp_accept(tcp_listener, resource)
|
||||||
}
|
}
|
||||||
_ => Either::A(tokio_util::accept(resource)),
|
_ => Either::A(tokio_util::accept(resource)),
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue