1
0
Fork 0
mirror of https://github.com/actix/actix-web.git synced 2024-10-21 17:33:59 +00:00

create default CpuPool

This commit is contained in:
Nikolay Kim 2018-03-07 14:56:53 -08:00
parent 67bf0ae79f
commit f55ef3a059
7 changed files with 71 additions and 25 deletions

View file

@ -74,6 +74,7 @@ net2 = "0.2"
bytes = "0.4"
byteorder = "1"
futures = "0.1"
futures-cpupool = "0.1"
tokio-io = "0.1"
tokio-core = "0.1"
trust-dns-resolver = "0.8"

View file

@ -44,8 +44,9 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
for &mut (ref prefix, ref mut handler) in &mut self.handlers {
let m = {
let path = &req.path()[self.prefix..];
path.starts_with(prefix) && (path.len() == prefix.len() ||
path.split_at(prefix.len()).1.starts_with('/'))
path.starts_with(prefix) && (
path.len() == prefix.len() ||
path.split_at(prefix.len()).1.starts_with('/'))
};
if m {
let path: &'static str = unsafe {

View file

@ -5,6 +5,7 @@ use std::net::SocketAddr;
use bytes::Bytes;
use cookie::Cookie;
use futures::{Async, Stream, Poll};
use futures_cpupool::CpuPool;
use failure;
use url::{Url, form_urlencoded};
use http::{header, Uri, Method, Version, HeaderMap, Extensions};
@ -129,12 +130,6 @@ impl HttpRequest<()> {
pub fn with_state<S>(self, state: Rc<S>, router: Router) -> HttpRequest<S> {
HttpRequest(self.0, Some(state), Some(router))
}
#[cfg(test)]
/// Construct new http request with state.
pub(crate) fn with_state_no_router<S>(self, state: Rc<S>) -> HttpRequest<S> {
HttpRequest(self.0, Some(state), None)
}
}
@ -156,7 +151,7 @@ impl<S> HttpRequest<S> {
#[inline]
/// Construct new http request without state.
pub(crate) fn without_state(&self) -> HttpRequest {
HttpRequest(self.0.clone(), None, None)
HttpRequest(self.0.clone(), None, self.2.clone())
}
/// get mutable reference for inner message
@ -184,12 +179,20 @@ impl<S> HttpRequest<S> {
self.1.as_ref().unwrap()
}
/// Protocol extensions.
/// Request extensions
#[inline]
pub fn extensions(&mut self) -> &mut Extensions {
&mut self.as_mut().extensions
}
/// Default `CpuPool`
#[inline]
#[doc(hidden)]
pub fn cpu_pool(&mut self) -> &CpuPool {
self.router().expect("HttpRequest has to have Router instance")
.server_settings().cpu_pool()
}
#[doc(hidden)]
pub fn prefix_len(&self) -> usize {
if let Some(router) = self.router() { router.prefix().len() } else { 0 }
@ -567,8 +570,9 @@ mod tests {
#[test]
fn test_url_for() {
let req = TestRequest::with_header(header::HOST, "www.rust-lang.org")
.finish_no_router();
let req2 = HttpRequest::default();
assert_eq!(req2.url_for("unknown", &["test"]),
Err(UrlGenerationError::RouterNotAvailable));
let mut resource = Resource::<()>::default();
resource.name("index");
@ -577,10 +581,8 @@ mod tests {
assert!(router.has_route("/user/test.html"));
assert!(!router.has_route("/test/unknown"));
assert_eq!(req.url_for("unknown", &["test"]),
Err(UrlGenerationError::RouterNotAvailable));
let req = req.with_state(Rc::new(()), router);
let req = TestRequest::with_header(header::HOST, "www.rust-lang.org")
.finish_with_router(router);
assert_eq!(req.url_for("unknown", &["test"]),
Err(UrlGenerationError::ResourceNotFound));

View file

@ -61,6 +61,7 @@ extern crate bitflags;
extern crate failure;
#[macro_use]
extern crate futures;
extern crate futures_cpupool;
extern crate tokio_io;
extern crate tokio_core;
extern crate mio;

View file

@ -84,13 +84,13 @@ impl<S: 'static> Route<S> {
}
/// Set handler object. Usually call to this method is last call
/// during route configuration, because it does not return reference to self.
/// during route configuration, so it does not return reference to self.
pub fn h<H: Handler<S>>(&mut self, handler: H) {
self.handler = InnerHandler::new(handler);
}
/// Set handler function. Usually call to this method is last call
/// during route configuration, because it does not return reference to self.
/// during route configuration, so it does not return reference to self.
pub fn f<F, R>(&mut self, handler: F)
where F: Fn(HttpRequest<S>) -> R + 'static,
R: Responder + 'static,
@ -133,7 +133,7 @@ impl<S: 'static> InnerHandler<S> {
#[inline]
pub fn handle(&self, req: HttpRequest<S>) -> Reply {
// reason: handler is unique per thread,
// handler get called from async code, and handler doesn't have side effects
// handler get called from async code only
#[allow(mutable_transmutes)]
#[cfg_attr(feature = "cargo-clippy", allow(borrowed_box))]
let h: &mut Box<RouteHandler<S>> = unsafe { mem::transmute(self.0.as_ref()) };

View file

@ -1,6 +1,8 @@
use std::net;
use std::{fmt, net};
use std::rc::Rc;
use std::cell::{Cell, RefCell, RefMut};
use std::sync::Arc;
use std::cell::{Cell, RefCell, RefMut, UnsafeCell};
use futures_cpupool::{Builder, CpuPool};
use helpers;
use super::channel::Node;
@ -12,14 +14,45 @@ pub struct ServerSettings {
addr: Option<net::SocketAddr>,
secure: bool,
host: String,
cpu_pool: Arc<InnerCpuPool>,
}
struct InnerCpuPool {
cpu_pool: UnsafeCell<Option<CpuPool>>,
}
impl fmt::Debug for InnerCpuPool {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CpuPool")
}
}
impl InnerCpuPool {
fn new() -> Self {
InnerCpuPool {
cpu_pool: UnsafeCell::new(None),
}
}
fn cpu_pool(&self) -> &CpuPool {
unsafe {
let val = &mut *self.cpu_pool.get();
if val.is_none() {
*val = Some(Builder::new().create());
}
val.as_ref().unwrap()
}
}
}
unsafe impl Sync for InnerCpuPool {}
impl Default for ServerSettings {
fn default() -> Self {
ServerSettings {
addr: None,
secure: false,
host: "localhost:8080".to_owned(),
cpu_pool: Arc::new(InnerCpuPool::new()),
}
}
}
@ -36,7 +69,8 @@ impl ServerSettings {
} else {
"localhost".to_owned()
};
ServerSettings { addr, secure, host }
let cpu_pool = Arc::new(InnerCpuPool::new());
ServerSettings { addr, secure, host, cpu_pool }
}
/// Returns the socket address of the local half of this TCP connection
@ -53,6 +87,11 @@ impl ServerSettings {
pub fn host(&self) -> &str {
&self.host
}
/// Returns default `CpuPool` for server
pub fn cpu_pool(&self) -> &CpuPool {
self.cpu_pool.cpu_pool()
}
}

View file

@ -431,12 +431,14 @@ impl<S> TestRequest<S> {
#[cfg(test)]
/// Complete request creation and generate `HttpRequest` instance
pub(crate) fn finish_no_router(self) -> HttpRequest<S> {
let TestRequest { state, method, uri, version, headers, params, cookies, payload } = self;
pub(crate) fn finish_with_router(self, router: Router) -> HttpRequest<S> {
let TestRequest { state, method, uri,
version, headers, params, cookies, payload } = self;
let req = HttpRequest::new(method, uri, version, headers, payload);
req.as_mut().cookies = cookies;
req.as_mut().params = params;
req.with_state_no_router(Rc::new(state))
req.with_state(Rc::new(state), router)
}
/// This method generates `HttpRequest` instance and runs handler