Andrea Ciliberti
3 years ago
10 changed files with 133 additions and 239 deletions
@ -0,0 +1,44 @@ |
|||||||
|
use crate::Error; |
||||||
|
use std::sync::Mutex; |
||||||
|
pub(crate) struct ServiceReference { |
||||||
|
counter: &'static Mutex<usize>, |
||||||
|
close: Box<dyn Fn()>, |
||||||
|
} |
||||||
|
|
||||||
|
impl ServiceReference { |
||||||
|
pub fn new<S, E>( |
||||||
|
counter: &'static Mutex<usize>, |
||||||
|
allow_multiple: bool, |
||||||
|
start: S, |
||||||
|
close: E, |
||||||
|
) -> crate::Result<Self> |
||||||
|
where |
||||||
|
S: FnOnce() -> crate::Result<()>, |
||||||
|
E: Fn() + 'static, |
||||||
|
{ |
||||||
|
let mut value = counter.lock().unwrap(); // todo: handle poisoning
|
||||||
|
|
||||||
|
if *value == 0 { |
||||||
|
start()?; |
||||||
|
} else if !allow_multiple { |
||||||
|
return Err(Error::ServiceAlreadyActive); |
||||||
|
} |
||||||
|
|
||||||
|
*value += 1; |
||||||
|
|
||||||
|
Ok(Self { |
||||||
|
counter, |
||||||
|
close: Box::new(close), |
||||||
|
}) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Drop for ServiceReference { |
||||||
|
fn drop(&mut self) { |
||||||
|
let mut value = self.counter.lock().unwrap(); // should probably handle poisoning - could just map_err to ignore it.
|
||||||
|
*value -= 1; |
||||||
|
if *value == 0 { |
||||||
|
(self.close)(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -1,53 +1,20 @@ |
|||||||
use once_cell::sync::Lazy; |
pub struct Srv(()); |
||||||
use std::sync::Mutex; |
|
||||||
|
|
||||||
use crate::services::ServiceReference; |
|
||||||
|
|
||||||
#[non_exhaustive] |
|
||||||
pub struct Srv { |
|
||||||
_service_handler: ServiceReference, |
|
||||||
} |
|
||||||
|
|
||||||
static SRV_ACTIVE: Lazy<Mutex<usize>> = Lazy::new(|| Mutex::new(0)); |
|
||||||
|
|
||||||
impl Srv { |
impl Srv { |
||||||
pub fn init() -> crate::Result<Self> { |
pub fn init() -> crate::Result<Srv> { |
||||||
let _service_handler = ServiceReference::new( |
unsafe { |
||||||
&SRV_ACTIVE, |
let r = ctru_sys::srvInit(); |
||||||
true, |
|
||||||
|| { |
|
||||||
let r = unsafe { ctru_sys::srvInit() }; |
|
||||||
if r < 0 { |
if r < 0 { |
||||||
return Err(r.into()); |
Err(r.into()) |
||||||
|
} else { |
||||||
|
Ok(Srv(())) |
||||||
|
} |
||||||
} |
} |
||||||
|
|
||||||
Ok(()) |
|
||||||
}, |
|
||||||
|| unsafe { |
|
||||||
ctru_sys::srvExit(); |
|
||||||
}, |
|
||||||
)?; |
|
||||||
|
|
||||||
Ok(Self { _service_handler }) |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
|
||||||
#[cfg(test)] |
impl Drop for Srv { |
||||||
mod tests { |
fn drop(&mut self) { |
||||||
use super::*; |
unsafe { ctru_sys::srvExit() }; |
||||||
|
|
||||||
#[test] |
|
||||||
fn srv_duplicate() { |
|
||||||
let _srv = Srv::init().unwrap(); |
|
||||||
|
|
||||||
let value = *SRV_ACTIVE.lock().unwrap(); |
|
||||||
|
|
||||||
assert_eq!(value, 1); |
|
||||||
|
|
||||||
drop(_srv); |
|
||||||
|
|
||||||
let value = *SRV_ACTIVE.lock().unwrap(); |
|
||||||
|
|
||||||
assert_eq!(value, 0); |
|
||||||
} |
} |
||||||
} |
} |
||||||
|
Loading…
Reference in new issue