2019-01-26 13:14:37 -08:00
use std ::time ::{ self , Duration , Instant } ;
2018-09-19 15:05:14 -07:00
2018-12-09 10:15:49 -08:00
use actix_service ::{ NewService , Service } ;
2018-09-19 15:05:14 -07:00
use futures ::future ::{ ok , FutureResult } ;
2018-09-20 11:16:12 -07:00
use futures ::{ Async , Future , Poll } ;
2018-09-19 15:05:14 -07:00
use tokio_timer ::sleep ;
2018-10-02 22:18:07 -07:00
use super ::cell ::Cell ;
2018-09-20 11:16:12 -07:00
use super ::Never ;
2018-09-19 15:05:14 -07:00
#[ derive(Clone, Debug) ]
2018-10-29 15:48:56 -07:00
pub struct LowResTime ( Cell < Inner > ) ;
2018-09-19 15:05:14 -07:00
#[ derive(Debug) ]
struct Inner {
2018-10-08 15:38:52 -07:00
resolution : Duration ,
2018-09-19 15:05:14 -07:00
current : Option < Instant > ,
}
impl Inner {
2018-10-08 15:38:52 -07:00
fn new ( resolution : Duration ) -> Self {
2018-09-19 15:05:14 -07:00
Inner {
2018-10-08 15:38:52 -07:00
resolution ,
2018-09-20 11:16:12 -07:00
current : None ,
2018-09-19 15:05:14 -07:00
}
}
}
2018-10-29 15:48:56 -07:00
impl LowResTime {
pub fn with ( resolution : Duration ) -> LowResTime {
LowResTime ( Cell ::new ( Inner ::new ( resolution ) ) )
2018-09-19 15:05:14 -07:00
}
2018-09-20 11:16:12 -07:00
2018-10-29 15:48:56 -07:00
pub fn timer ( & self ) -> LowResTimeService {
LowResTimeService ( self . 0. clone ( ) )
2018-09-20 11:16:12 -07:00
}
2018-09-19 15:05:14 -07:00
}
2018-10-29 15:48:56 -07:00
impl Default for LowResTime {
2018-09-19 15:05:14 -07:00
fn default ( ) -> Self {
2018-10-29 15:48:56 -07:00
LowResTime ( Cell ::new ( Inner ::new ( Duration ::from_secs ( 1 ) ) ) )
2018-09-19 15:05:14 -07:00
}
}
2019-02-01 19:53:13 -08:00
impl NewService for LowResTime {
type Request = ( ) ;
2018-09-19 15:05:14 -07:00
type Response = Instant ;
2018-09-20 11:16:12 -07:00
type Error = Never ;
type InitError = Never ;
2018-10-29 15:48:56 -07:00
type Service = LowResTimeService ;
2018-09-19 15:05:14 -07:00
type Future = FutureResult < Self ::Service , Self ::InitError > ;
fn new_service ( & self ) -> Self ::Future {
2018-09-20 11:16:12 -07:00
ok ( self . timer ( ) )
2018-09-19 15:05:14 -07:00
}
}
#[ derive(Clone, Debug) ]
2018-10-29 15:48:56 -07:00
pub struct LowResTimeService ( Cell < Inner > ) ;
2018-09-19 15:05:14 -07:00
2018-10-29 15:48:56 -07:00
impl LowResTimeService {
pub fn with ( resolution : Duration ) -> LowResTimeService {
LowResTimeService ( Cell ::new ( Inner ::new ( resolution ) ) )
2018-09-19 15:05:14 -07:00
}
2018-09-20 11:16:12 -07:00
/// Get current time. This function has to be called from
/// future's poll method, otherwise it panics.
2018-10-29 15:40:10 -07:00
pub fn now ( & self ) -> Instant {
2019-01-26 13:14:37 -08:00
let cur = self . 0. get_ref ( ) . current ;
2018-09-19 15:05:14 -07:00
if let Some ( cur ) = cur {
2018-09-20 11:16:12 -07:00
cur
2018-09-19 15:05:14 -07:00
} else {
let now = Instant ::now ( ) ;
2019-01-26 13:14:37 -08:00
let mut inner = self . 0. clone ( ) ;
2018-09-19 15:05:14 -07:00
let interval = {
2019-01-26 13:14:37 -08:00
let mut b = inner . get_mut ( ) ;
2018-09-19 15:05:14 -07:00
b . current = Some ( now ) ;
2018-10-08 15:38:52 -07:00
b . resolution
2018-09-19 15:05:14 -07:00
} ;
2019-01-26 13:14:37 -08:00
tokio_current_thread ::spawn ( sleep ( interval ) . map_err ( | _ | panic! ( ) ) . and_then (
move | _ | {
inner . get_mut ( ) . current . take ( ) ;
Ok ( ( ) )
} ,
) ) ;
2018-09-20 11:16:12 -07:00
now
2018-09-19 15:05:14 -07:00
}
}
}
2018-09-20 11:16:12 -07:00
2019-02-01 19:53:13 -08:00
impl Service for LowResTimeService {
type Request = ( ) ;
2018-09-20 11:16:12 -07:00
type Response = Instant ;
type Error = Never ;
type Future = FutureResult < Self ::Response , Self ::Error > ;
fn poll_ready ( & mut self ) -> Poll < ( ) , Self ::Error > {
Ok ( Async ::Ready ( ( ) ) )
}
fn call ( & mut self , _ : ( ) ) -> Self ::Future {
ok ( self . now ( ) )
}
}
2019-01-26 13:14:37 -08:00
#[ derive(Clone, Debug) ]
pub struct SystemTime ( Cell < SystemTimeInner > ) ;
#[ derive(Debug) ]
struct SystemTimeInner {
resolution : Duration ,
current : Option < time ::SystemTime > ,
}
impl SystemTimeInner {
fn new ( resolution : Duration ) -> Self {
SystemTimeInner {
resolution ,
current : None ,
}
}
}
#[ derive(Clone, Debug) ]
pub struct SystemTimeService ( Cell < SystemTimeInner > ) ;
impl SystemTimeService {
pub fn with ( resolution : Duration ) -> SystemTimeService {
SystemTimeService ( Cell ::new ( SystemTimeInner ::new ( resolution ) ) )
}
/// Get current time. This function has to be called from
/// future's poll method, otherwise it panics.
pub fn now ( & self ) -> time ::SystemTime {
let cur = self . 0. get_ref ( ) . current . clone ( ) ;
if let Some ( cur ) = cur {
cur
} else {
let now = time ::SystemTime ::now ( ) ;
let mut inner = self . 0. clone ( ) ;
let interval = {
let mut b = inner . get_mut ( ) ;
b . current = Some ( now ) ;
b . resolution
} ;
tokio_current_thread ::spawn ( sleep ( interval ) . map_err ( | _ | panic! ( ) ) . and_then (
move | _ | {
inner . get_mut ( ) . current . take ( ) ;
Ok ( ( ) )
} ,
) ) ;
now
}
}
}
2019-01-26 13:21:56 -08:00
#[ cfg(test) ]
mod tests {
use super ::* ;
use futures ::future ;
use std ::time ::{ Duration , SystemTime } ;
/// State Under Test: Two calls of `SystemTimeService::now()` return the same value if they are done within resolution interval of `SystemTimeService`.
///
/// Expected Behavior: Two back-to-back calls of `SystemTimeService::now()` return the same value.
#[ test ]
fn system_time_service_time_does_not_immediately_change ( ) {
let resolution = Duration ::from_millis ( 50 ) ;
let _ = actix_rt ::System ::new ( " test " ) . block_on ( future ::lazy ( | | {
let time_service = SystemTimeService ::with ( resolution ) ;
assert_eq! ( time_service . now ( ) , time_service . now ( ) ) ;
Ok ::< ( ) , ( ) > ( ( ) )
} ) ) ;
}
/// State Under Test: Two calls of `LowResTimeService::now()` return the same value if they are done within resolution interval of `SystemTimeService`.
///
/// Expected Behavior: Two back-to-back calls of `LowResTimeService::now()` return the same value.
#[ test ]
fn lowres_time_service_time_does_not_immediately_change ( ) {
let resolution = Duration ::from_millis ( 50 ) ;
let _ = actix_rt ::System ::new ( " test " ) . block_on ( future ::lazy ( | | {
let time_service = LowResTimeService ::with ( resolution ) ;
assert_eq! ( time_service . now ( ) , time_service . now ( ) ) ;
Ok ::< ( ) , ( ) > ( ( ) )
} ) ) ;
}
/// State Under Test: `SystemTimeService::now()` updates returned value every resolution period.
///
/// Expected Behavior: Two calls of `LowResTimeService::now()` made in subsequent resolution interval return different values
/// and second value is greater than the first one at least by a resolution interval.
#[ test ]
fn system_time_service_time_updates_after_resolution_interval ( ) {
let resolution = Duration ::from_millis ( 100 ) ;
let wait_time = Duration ::from_millis ( 150 ) ;
let _ = actix_rt ::System ::new ( " test " ) . block_on ( future ::lazy ( | | {
let time_service = SystemTimeService ::with ( resolution ) ;
let first_time = time_service
. now ( )
. duration_since ( SystemTime ::UNIX_EPOCH )
. unwrap ( ) ;
sleep ( wait_time ) . then ( move | _ | {
let second_time = time_service
. now ( )
. duration_since ( SystemTime ::UNIX_EPOCH )
. unwrap ( ) ;
assert! ( second_time - first_time > = wait_time ) ;
Ok ::< ( ) , ( ) > ( ( ) )
} )
} ) ) ;
}
/// State Under Test: `LowResTimeService::now()` updates returned value every resolution period.
///
/// Expected Behavior: Two calls of `LowResTimeService::now()` made in subsequent resolution interval return different values
/// and second value is greater than the first one at least by a resolution interval.
#[ test ]
fn lowres_time_service_time_updates_after_resolution_interval ( ) {
let resolution = Duration ::from_millis ( 100 ) ;
let wait_time = Duration ::from_millis ( 150 ) ;
let _ = actix_rt ::System ::new ( " test " ) . block_on ( future ::lazy ( | | {
let time_service = LowResTimeService ::with ( resolution ) ;
let first_time = time_service . now ( ) ;
sleep ( wait_time ) . then ( move | _ | {
let second_time = time_service . now ( ) ;
assert! ( second_time - first_time > = wait_time ) ;
Ok ::< ( ) , ( ) > ( ( ) )
} )
} ) ) ;
}
}