Skip to content

Commit

Permalink
refactor bridges to use generics
Browse files Browse the repository at this point in the history
  • Loading branch information
youyuanwu committed Dec 31, 2023
1 parent 6d19b2f commit 0527f7f
Show file tree
Hide file tree
Showing 10 changed files with 117 additions and 113 deletions.
26 changes: 18 additions & 8 deletions crates/fabric/rs/src/runtime/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ use windows::core::implement;
use windows_core::{ComInterface, Error, Interface, HSTRING, PCWSTR};

use self::{
stateful::StatefulServiceFactory, stateful_bridge::StatefulServiceFactoryBridge,
stateless::StatelessServiceFactory, stateless_bridge::StatelessServiceFactoryBridge,
stateful::{StatefulServiceFactory, StatefulServiceReplica},
stateful_bridge::StatefulServiceFactoryBridge,
stateless::{StatelessServiceFactory, StatelessServiceInstance},
stateless_bridge::StatelessServiceFactoryBridge,
};

pub mod error;
Expand Down Expand Up @@ -61,11 +63,15 @@ impl Runtime {
Ok(Runtime { com_impl: com, rt })
}

pub fn register_stateless_service_factory(
pub fn register_stateless_service_factory<F, S>(
&self,
servicetypename: &HSTRING,
factory: Box<dyn StatelessServiceFactory>,
) -> windows_core::Result<()> {
factory: F,
) -> windows_core::Result<()>
where
F: StatelessServiceFactory<S>,
S: StatelessServiceInstance + 'static,
{
let rt_cp = self.rt.clone();
let bridge: IFabricStatelessServiceFactory =
StatelessServiceFactoryBridge::create(factory, rt_cp).into();
Expand All @@ -75,11 +81,15 @@ impl Runtime {
}
}

pub fn register_stateful_service_factory(
pub fn register_stateful_service_factory<F, R>(
&self,
servicetypename: &HSTRING,
factory: Box<dyn StatefulServiceFactory>,
) -> windows_core::Result<()> {
factory: F,
) -> windows_core::Result<()>
where
F: StatefulServiceFactory<R>,
R: StatefulServiceReplica + 'static,
{
let rt_cp = self.rt.clone();
let bridge: IFabricStatefulServiceFactory =
StatefulServiceFactoryBridge::create(factory, rt_cp).into();
Expand Down
7 changes: 5 additions & 2 deletions crates/fabric/rs/src/runtime/stateful.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,18 @@ use super::stateful_types::{
Epoch, OpenMode, ReplicaInfo, ReplicaSetConfig, ReplicaSetQuarumMode, Role,
};

pub trait StatefulServiceFactory {
pub trait StatefulServiceFactory<R>
where
R: StatefulServiceReplica,
{
fn create_replica(
&self,
servicetypename: &HSTRING,
servicename: &HSTRING,
initializationdata: &[u8],
partitionid: &::windows::core::GUID,
replicaid: i64,
) -> Result<Box<dyn StatefulServiceReplica>, Error>;
) -> Result<R, Error>;
}

// safe service instance
Expand Down
56 changes: 38 additions & 18 deletions crates/fabric/rs/src/runtime/stateful_bridge.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// stateful bridge is to wrap rs types into com to expose to SF

use std::sync::Arc;
use std::{marker::PhantomData, sync::Arc};

use log::info;
use tokio::runtime::Handle;
Expand Down Expand Up @@ -35,21 +35,35 @@ use super::stateful::{
};

#[implement(IFabricStatefulServiceFactory)]
pub struct StatefulServiceFactoryBridge {
inner: Box<dyn StatefulServiceFactory>,
pub struct StatefulServiceFactoryBridge<F, R>
where
F: StatefulServiceFactory<R>,
R: StatefulServiceReplica + 'static,
{
inner: F,
rt: Handle,
phantom: PhantomData<R>,
}

impl StatefulServiceFactoryBridge {
pub fn create(
factory: Box<dyn StatefulServiceFactory>,
rt: Handle,
) -> StatefulServiceFactoryBridge {
StatefulServiceFactoryBridge { inner: factory, rt }
impl<F, R> StatefulServiceFactoryBridge<F, R>
where
F: StatefulServiceFactory<R>,
R: StatefulServiceReplica,
{
pub fn create(factory: F, rt: Handle) -> StatefulServiceFactoryBridge<F, R> {
StatefulServiceFactoryBridge::<F, R> {
inner: factory,
rt,
phantom: PhantomData,
}
}
}

impl IFabricStatefulServiceFactory_Impl for StatefulServiceFactoryBridge {
impl<F, R> IFabricStatefulServiceFactory_Impl for StatefulServiceFactoryBridge<F, R>
where
F: StatefulServiceFactory<R>,
R: StatefulServiceReplica + 'static,
{
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn CreateReplica(
&self,
Expand Down Expand Up @@ -524,24 +538,30 @@ impl IFabricPrimaryReplicator_Impl for IFabricPrimaryReplicatorBridge {
// bridge from safe service instance to com
#[implement(IFabricStatefulServiceReplica)]

pub struct IFabricStatefulServiceReplicaBridge {
inner: Arc<Box<dyn StatefulServiceReplica>>,
pub struct IFabricStatefulServiceReplicaBridge<R>
where
R: StatefulServiceReplica + 'static,
{
inner: Arc<R>,
rt: Handle,
}

impl IFabricStatefulServiceReplicaBridge {
pub fn create(
rplctr: Box<dyn StatefulServiceReplica>,
rt: Handle,
) -> IFabricStatefulServiceReplicaBridge {
impl<R> IFabricStatefulServiceReplicaBridge<R>
where
R: StatefulServiceReplica,
{
pub fn create(rplctr: R, rt: Handle) -> IFabricStatefulServiceReplicaBridge<R> {
IFabricStatefulServiceReplicaBridge {
inner: Arc::new(rplctr),
rt,
}
}
}

impl IFabricStatefulServiceReplica_Impl for IFabricStatefulServiceReplicaBridge {
impl<R> IFabricStatefulServiceReplica_Impl for IFabricStatefulServiceReplicaBridge<R>
where
R: StatefulServiceReplica + 'static,
{
fn BeginOpen(
&self,
openmode: FABRIC_REPLICA_OPEN_MODE,
Expand Down
7 changes: 5 additions & 2 deletions crates/fabric/rs/src/runtime/stateless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,18 @@ impl StatelessServicePartition {
}

// safe factory
pub trait StatelessServiceFactory {
pub trait StatelessServiceFactory<T>
where
T: StatelessServiceInstance,
{
fn create_instance(
&self,
servicetypename: &HSTRING,
servicename: &HSTRING,
initializationdata: &[u8],
partitionid: &::windows::core::GUID,
instanceid: i64,
) -> Box<dyn StatelessServiceInstance + Send>;
) -> T;
}

// safe service instance
Expand Down
59 changes: 41 additions & 18 deletions crates/fabric/rs/src/runtime/stateless_bridge.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#![deny(non_snake_case)] // this file is safe rust

use std::sync::Arc;
use std::{marker::PhantomData, sync::Arc};

use crate::{
runtime::{stateless::StatelessServicePartition, BridgeContext},
Expand All @@ -22,21 +22,35 @@ use windows_core::{AsImpl, Error, HSTRING};
use super::stateless::{StatelessServiceFactory, StatelessServiceInstance};

#[implement(IFabricStatelessServiceFactory)]
pub struct StatelessServiceFactoryBridge {
inner: Box<dyn StatelessServiceFactory>,
pub struct StatelessServiceFactoryBridge<F, S>
where
F: StatelessServiceFactory<S>,
S: StatelessServiceInstance + 'static,
{
inner: F,
rt: Handle,
phantom: PhantomData<S>,
}

impl StatelessServiceFactoryBridge {
pub fn create(
factory: Box<dyn StatelessServiceFactory>,
rt: Handle,
) -> StatelessServiceFactoryBridge {
StatelessServiceFactoryBridge { inner: factory, rt }
impl<F, S> StatelessServiceFactoryBridge<F, S>
where
F: StatelessServiceFactory<S>,
S: StatelessServiceInstance,
{
pub fn create(factory: F, rt: Handle) -> StatelessServiceFactoryBridge<F, S> {
StatelessServiceFactoryBridge::<F, S> {
inner: factory,
rt,
phantom: PhantomData,
}
}
}

impl IFabricStatelessServiceFactory_Impl for StatelessServiceFactoryBridge {
impl<F, S> IFabricStatelessServiceFactory_Impl for StatelessServiceFactoryBridge<F, S>
where
F: StatelessServiceFactory<S>,
S: StatelessServiceInstance + 'static,
{
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn CreateInstance(
&self,
Expand Down Expand Up @@ -72,24 +86,33 @@ impl IFabricStatelessServiceFactory_Impl for StatelessServiceFactoryBridge {
// bridge from safe service instance to com
#[implement(IFabricStatelessServiceInstance)]

struct IFabricStatelessServiceInstanceBridge {
inner: Arc<Box<dyn StatelessServiceInstance>>,
struct IFabricStatelessServiceInstanceBridge<S>
where
S: StatelessServiceInstance + 'static,
{
inner: Arc<S>,
rt: Handle,
}

impl IFabricStatelessServiceInstanceBridge {
pub fn create(
instance: Box<dyn StatelessServiceInstance + Send>,
rt: Handle,
) -> IFabricStatelessServiceInstanceBridge {
impl<S> IFabricStatelessServiceInstanceBridge<S>
where
S: StatelessServiceInstance,
{
pub fn create(instance: S, rt: Handle) -> IFabricStatelessServiceInstanceBridge<S>
where
S: StatelessServiceInstance,
{
IFabricStatelessServiceInstanceBridge {
inner: Arc::new(instance),
rt,
}
}
}

impl IFabricStatelessServiceInstance_Impl for IFabricStatelessServiceInstanceBridge {
impl<S> IFabricStatelessServiceInstance_Impl for IFabricStatelessServiceInstanceBridge<S>
where
S: StatelessServiceInstance + 'static,
{
fn BeginOpen(
&self,
partition: ::core::option::Option<&IFabricStatelessServicePartition>,
Expand Down
6 changes: 3 additions & 3 deletions crates/samples/echo2/src/echo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@ use windows_core::HSTRING;
#[derive(Default)]
pub struct Factory {}

impl StatelessServiceFactory for Factory {
impl StatelessServiceFactory<Instance> for Factory {
fn create_instance(
&self,
servicetypename: &windows_core::HSTRING,
servicename: &windows_core::HSTRING,
initializationdata: &[u8],
partitionid: &windows::core::GUID,
instanceid: i64,
) -> Box<dyn StatelessServiceInstance + Send> {
) -> Instance {
info!(
"Factory::create_instance, servicetype {}, service {}, init len {}, ptid {:?}, iid {}",
servicetypename,
Expand All @@ -25,7 +25,7 @@ impl StatelessServiceFactory for Factory {
partitionid,
instanceid
);
Box::<Instance>::default()
Instance::default()
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/samples/echo2/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn main() -> windows::core::Result<()> {
let rt = tokio::runtime::Runtime::new().unwrap();

let runtime = Runtime::create(rt.handle().clone()).unwrap();
let factory = Box::<echo::Factory>::default();
let factory = echo::Factory::default();
runtime
.register_stateless_service_factory(&HSTRING::from("EchoAppService2"), factory)
.unwrap();
Expand Down
6 changes: 3 additions & 3 deletions crates/samples/kvstore/src/kvstore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ fn get_addr(port: u32, hostname: HSTRING) -> String {
addr
}

impl StatefulServiceFactory for Factory {
impl StatefulServiceFactory<Replica> for Factory {
fn create_replica(
&self,
servicetypename: &windows_core::HSTRING,
servicename: &windows_core::HSTRING,
initializationdata: &[u8],
partitionid: &windows::core::GUID,
replicaid: i64,
) -> Result<Box<dyn fabric_rs::runtime::stateful::StatefulServiceReplica>, Error> {
) -> Result<Replica, Error> {
info!(
"Factory::create_replica type {}, service {}, init data size {}",
servicetypename,
Expand Down Expand Up @@ -89,7 +89,7 @@ impl StatefulServiceFactory for Factory {
let svc = Service::new(kv, self.rt.clone());

let replica = Replica::new(proxy, svc);
Ok(Box::new(replica))
Ok(replica)
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/samples/kvstore/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn main() -> windows::core::Result<()> {
.get_endpoint_resource(&HSTRING::from("KvReplicatorEndpoint"))
.unwrap();

let factory = Box::new(Factory::create(endpoint.Port, rt.handle().clone()));
let factory = Factory::create(endpoint.Port, rt.handle().clone());
runtime
.register_stateful_service_factory(&HSTRING::from("KvStoreService"), factory)
.unwrap();
Expand Down
Loading

0 comments on commit 0527f7f

Please sign in to comment.