Relax type bounds (#17)

* relax type bounds

* remove Send bound on NoOperator

* fix tests

* remove bound on service message

* re-add type bound on Relay

* remove duplicate PhantomBound
This commit is contained in:
Giacomo Pasini 2023-01-17 14:45:22 +01:00 committed by GitHub
parent 6d12e83c35
commit 4efc467d84
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 25 deletions

View File

@ -3,13 +3,13 @@
// crates
use crate::overwatch::commands::{OverwatchCommand, OverwatchLifeCycleCommand, SettingsCommand};
use crate::overwatch::Services;
use crate::services::ServiceData;
use tokio::runtime::Handle;
use tokio::sync::mpsc::Sender;
use tracing::{error, info, instrument};
// internal
use crate::services::relay::Relay;
use crate::services::ServiceCore;
/// Handler object over the main Overwatch runner
/// It handles communications to the main Overwatch runner.
@ -28,8 +28,8 @@ impl OverwatchHandle {
}
}
/// Request for a relay to an specific service by type
pub fn relay<S: ServiceCore>(&self) -> Relay<S> {
/// Request for a relay
pub fn relay<S: ServiceData>(&self) -> Relay<S> {
Relay::new(self.clone())
}

View File

@ -6,14 +6,14 @@ use crate::overwatch::handle::OverwatchHandle;
use crate::services::relay::{relay, InboundRelay, OutboundRelay};
use crate::services::settings::{SettingsNotifier, SettingsUpdater};
use crate::services::state::{StateHandle, StateOperator, StateUpdater};
use crate::services::{ServiceCore, ServiceId, ServiceState};
use crate::services::{ServiceCore, ServiceData, ServiceId, ServiceState};
// TODO: Abstract handle over state, to diferentiate when the service is running and when it is not
// that way we can expose a better API depending on what is happenning. Would get rid of the probably
// unnecessary Option and cloning.
/// Service handle
/// This is used to access different parts of the service
pub struct ServiceHandle<S: ServiceCore> {
pub struct ServiceHandle<S: ServiceData> {
/// Message channel relay
/// Would be None if service is not running
/// Will contain the channel if service is running
@ -26,7 +26,7 @@ pub struct ServiceHandle<S: ServiceCore> {
/// Service core resources
/// It contains whatever is necessary to start a new service runner
pub struct ServiceStateHandle<S: ServiceCore> {
pub struct ServiceStateHandle<S: ServiceData> {
/// Relay channel to communicate with the service runner
pub inbound_relay: InboundRelay<S::Message>,
/// Overwatch handle
@ -38,12 +38,12 @@ pub struct ServiceStateHandle<S: ServiceCore> {
/// Main service executor
/// It is the object that hold the necessary information for the service to run
pub struct ServiceRunner<S: ServiceCore> {
pub struct ServiceRunner<S: ServiceData> {
service_state: ServiceStateHandle<S>,
state_handle: StateHandle<S::State, S::StateOperator>,
}
impl<S: ServiceCore> ServiceHandle<S> {
impl<S: ServiceData> ServiceHandle<S> {
pub fn new(
settings: S::Settings,
overwatch_handle: OverwatchHandle,
@ -109,7 +109,7 @@ impl<S: ServiceCore> ServiceHandle<S> {
}
}
impl<S: ServiceCore> ServiceStateHandle<S> {
impl<S: ServiceData> ServiceStateHandle<S> {
pub fn id(&self) -> ServiceId {
S::SERVICE_ID
}

View File

@ -36,7 +36,7 @@ pub trait ServiceData {
/// State operator
type StateOperator: StateOperator<StateInput = Self::State> + Clone;
/// Service messages that the service itself understands and can react to
type Message: RelayMessage + Debug + Send + Sync;
type Message: RelayMessage + Debug;
}
/// Main trait for Services initialization and main loop hook

View File

@ -14,7 +14,7 @@ use tracing::{error, instrument};
// internal
use crate::overwatch::commands::{OverwatchCommand, RelayCommand, ReplyChannel};
use crate::overwatch::handle::OverwatchHandle;
use crate::services::{ServiceCore, ServiceId};
use crate::services::{ServiceData, ServiceId};
#[derive(Error, Debug)]
pub enum RelayError {
@ -66,20 +66,21 @@ pub struct OutboundRelay<M> {
}
#[derive(Debug)]
pub struct Relay<S: ServiceCore> {
_marker: PhantomData<S>,
pub struct Relay<S> {
overwatch_handle: OverwatchHandle,
_bound: PhantomBound<S>,
}
impl<S: ServiceCore> Clone for Relay<S> {
fn clone(&self) -> Self {
Self {
_marker: PhantomData,
overwatch_handle: self.overwatch_handle.clone(),
}
}
// Like PhantomData<T> but without
// ownership of T
#[derive(Debug)]
struct PhantomBound<T> {
_inner: PhantomData<*const T>,
}
unsafe impl<T> Send for PhantomBound<T> {}
unsafe impl<T> Sync for PhantomBound<T> {}
impl<M> Clone for OutboundRelay<M> {
fn clone(&self) -> Self {
Self {
@ -142,11 +143,13 @@ impl<M: Send + 'static> OutboundRelay<M> {
}
}
impl<S: ServiceCore> Relay<S> {
impl<S: ServiceData> Relay<S> {
pub fn new(overwatch_handle: OverwatchHandle) -> Self {
Self {
overwatch_handle,
_marker: PhantomData,
_bound: PhantomBound {
_inner: PhantomData,
},
}
}

View File

@ -1,7 +1,7 @@
// std
use std::marker::PhantomData;
use std::pin::Pin;
use std::sync::Arc;
// crates
use async_trait::async_trait;
use futures::StreamExt;
@ -54,14 +54,23 @@ impl<T> Clone for NoOperator<T> {
}
#[async_trait]
impl<StateInput: ServiceState + Send> StateOperator for NoOperator<StateInput> {
impl<StateInput: ServiceState> StateOperator for NoOperator<StateInput> {
type StateInput = StateInput;
fn from_settings<Settings>(_settings: Settings) -> Self {
NoOperator(PhantomData::default())
}
async fn run(&mut self, _state: Self::StateInput) {}
fn run<'borrow, 'fut>(
&'borrow mut self,
_state: Self::StateInput,
) -> Pin<Box<dyn std::future::Future<Output = ()> + Send + 'fut>>
where
'borrow: 'fut,
Self: 'fut,
{
Box::pin(async {})
}
}
/// Empty state