remove bounds from trait definitions (#16)

This commit is contained in:
Giacomo Pasini 2023-01-11 10:30:50 +01:00 committed by GitHub
parent cc2d562d38
commit 6d12e83c35
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 21 deletions

View File

@ -70,7 +70,10 @@ impl OverwatchHandle {
}
#[instrument(skip(self))]
pub async fn update_settings<S: Services>(&self, settings: S::Settings) {
pub async fn update_settings<S: Services>(&self, settings: S::Settings)
where
S::Settings: Send,
{
if let Err(e) = self
.sender
.send(OverwatchCommand::Settings(SettingsCommand(Box::new(

View File

@ -55,15 +55,15 @@ impl From<super::DynError> for Error {
type FinishOverwatchSignal = ();
/// Marker trait for settings related elements
pub type AnySettings = Box<dyn Any + Send + 'static>;
pub type AnySettings = Box<dyn Any + Send>;
/// An overwatch run anything that implements this trait
/// An implementor of this trait would have to handle the inner [`ServiceCore`](crate::services::ServiceCore)
#[async_trait]
pub trait Services: Sized + Send + Sync {
pub trait Services: Sized {
/// Inner [`ServiceCore::Settings`](crate::services::ServiceCore) grouping type.
/// Normally this will be a settings object that group all the inner services settings.
type Settings: Debug + Send + 'static;
type Settings: Debug + 'static; // 'static is required for cast to `AnySetting`
/// Spawn a new instance of the Services object
/// It returns a `(ServiceId, Runtime)` where Runtime is the `tokio::runtime::Runtime` attached for each
@ -108,7 +108,7 @@ pub const OVERWATCH_THREAD_NAME: &str = "Overwatch";
impl<S> OverwatchRunner<S>
where
S: Services + 'static,
S: Services + Send + 'static,
{
/// Start the Overwatch runner process
/// It creates the `tokio::runtime::Runtime`, initialize the [`Services`] and start listening for

View File

@ -115,7 +115,12 @@ impl<S: ServiceCore> ServiceStateHandle<S> {
}
}
impl<S: ServiceCore> ServiceRunner<S> {
impl<S> ServiceRunner<S>
where
S::State: Send + Sync + 'static,
S::StateOperator: Send + 'static,
S: ServiceCore + 'static,
{
/// Spawn the service main loop and handle it lifecycle
/// Return a handle to abort execution manually

View File

@ -41,7 +41,7 @@ pub trait ServiceData {
/// Main trait for Services initialization and main loop hook
#[async_trait]
pub trait ServiceCore: ServiceData + Send + Sized + 'static {
pub trait ServiceCore: Sized + ServiceData {
/// Initialize the service with the given state
fn init(service_state: ServiceStateHandle<Self>) -> Result<Self, super::DynError>;

View File

@ -15,7 +15,7 @@ use tracing::error;
/// It defines what is needed for a service state to be initialized.
/// Need what set of settings information is required for it to be initialized [`ServiceState::Settings`]
/// which usually is bound to the service itself [`crate::services::ServiceData::Settings`]
pub trait ServiceState: Sized + Send + Sync + 'static {
pub trait ServiceState: Sized {
/// Settings object that the state can be initialized from
type Settings;
/// Errors that can occur during state initialization
@ -27,7 +27,7 @@ pub trait ServiceState: Sized + Send + Sync + 'static {
/// A state operator is an entity that can handle a state in a point of time
/// to perform any operation based on it.
#[async_trait]
pub trait StateOperator: Send {
pub trait StateOperator {
/// The type of state that the operator can handle
type StateInput: ServiceState;
/// Operator initialization method. Can be implemented over some subset of settings
@ -38,7 +38,13 @@ pub trait StateOperator: Send {
/// Operator that doesn't perform any operation upon state update
#[derive(Copy)]
pub struct NoOperator<StateInput>(PhantomData<StateInput>);
pub struct NoOperator<StateInput>(PhantomData<*const StateInput>);
// NoOperator does not actually hold anything and is thus Sync.
// Note that we don't use PhantomData<StateInput> as that would
// suggest we indeed hold an instance of StateInput, see
// https://doc.rust-lang.org/std/marker/struct.PhantomData.html#ownership-and-the-drop-check
unsafe impl<T> Send for NoOperator<T> {}
// auto derive introduces unnecessary Clone bound on T
impl<T> Clone for NoOperator<T> {
@ -48,7 +54,7 @@ impl<T> Clone for NoOperator<T> {
}
#[async_trait]
impl<StateInput: ServiceState> StateOperator for NoOperator<StateInput> {
impl<StateInput: ServiceState + Send> StateOperator for NoOperator<StateInput> {
type StateInput = StateInput;
fn from_settings<Settings>(_settings: Settings) -> Self {
@ -69,7 +75,7 @@ impl<T> Clone for NoState<T> {
}
}
impl<Settings: Send + Sync + 'static> ServiceState for NoState<Settings> {
impl<Settings> ServiceState for NoState<Settings> {
type Settings = Settings;
type Error = crate::DynError;
@ -82,15 +88,15 @@ impl<Settings: Send + Sync + 'static> ServiceState for NoState<Settings> {
/// Receiver part of the state handling mechanism.
/// A state handle watches a stream of incoming states and triggers the attached operator handling
/// method over it.
pub struct StateHandle<S: ServiceState, Operator: StateOperator<StateInput = S>> {
pub struct StateHandle<S, Operator> {
watcher: StateWatcher<S>,
operator: Operator,
}
// auto derive introduces unnecessary Clone bound on T
impl<S: ServiceState, Operator: StateOperator<StateInput = S>> Clone for StateHandle<S, Operator>
impl<S, O> Clone for StateHandle<S, O>
where
Operator: Clone,
O: Clone,
{
fn clone(&self) -> Self {
Self {
@ -159,12 +165,8 @@ where
}
}
impl<S, Operator> StateHandle<S, Operator>
where
S: ServiceState + Clone,
Operator: StateOperator<StateInput = S>,
{
pub fn new(initial_state: S, operator: Operator) -> (Self, StateUpdater<S>) {
impl<S, O> StateHandle<S, O> {
pub fn new(initial_state: S, operator: O) -> (Self, StateUpdater<S>) {
let (sender, receiver) = channel(initial_state);
let watcher = StateWatcher { receiver };
let updater = StateUpdater {
@ -173,7 +175,13 @@ where
(Self { watcher, operator }, updater)
}
}
impl<S, Operator> StateHandle<S, Operator>
where
S: ServiceState + Clone + Send + Sync + 'static,
Operator: StateOperator<StateInput = S>,
{
/// Wait for new state updates and run the operator handling method
pub async fn run(self) {
let Self {