gwr_components/flow_controls/
credit_issuer.rs1use std::cell::RefCell;
14use std::rc::Rc;
15
16use async_trait::async_trait;
17use gwr_engine::engine::Engine;
18use gwr_engine::port::{InPort, OutPort, PortStateResult};
19use gwr_engine::traits::{Runnable, SimObject};
20use gwr_engine::types::{SimError, SimResult};
21use gwr_model_builder::EntityDisplay;
22use gwr_track::entity::Entity;
23use gwr_track::trace;
24
25use crate::types::Credit;
26use crate::{connect_tx, port_rx, take_option};
27
28#[derive(EntityDisplay)]
29pub struct CreditIssuer<T>
30where
31 T: SimObject,
32{
33 pub entity: Rc<Entity>,
34 tx: RefCell<Option<OutPort<T>>>,
35 credit_tx: RefCell<Option<OutPort<Credit>>>,
36 rx: RefCell<Option<InPort<T>>>,
37}
38
39impl<T> CreditIssuer<T>
40where
41 T: SimObject,
42{
43 pub fn new_and_register(engine: &Engine, parent: &Rc<Entity>) -> Result<Rc<Self>, SimError> {
44 let entity = Rc::new(Entity::new(parent, "credit_issue"));
45 let tx = OutPort::new(&entity, "tx");
46 let credit_tx = OutPort::new(&entity, "credit_tx");
47 let rx = InPort::new(&entity, "rx");
48 let rc_self = Rc::new(Self {
49 entity,
50 tx: RefCell::new(Some(tx)),
51 credit_tx: RefCell::new(Some(credit_tx)),
52 rx: RefCell::new(Some(rx)),
53 });
54 engine.register(rc_self.clone());
55 Ok(rc_self)
56 }
57
58 pub fn connect_port_tx(&self, port_state: PortStateResult<T>) -> SimResult {
59 connect_tx!(self.tx, connect ; port_state)
60 }
61
62 pub fn port_rx(&self) -> PortStateResult<T> {
63 port_rx!(self.rx, state)
64 }
65
66 pub fn connect_port_credit_tx(&self, port_state: PortStateResult<Credit>) -> SimResult {
67 connect_tx!(self.credit_tx, connect ; port_state)
68 }
69}
70
71#[async_trait(?Send)]
72impl<T> Runnable for CreditIssuer<T>
73where
74 T: SimObject,
75{
76 async fn run(&self) -> SimResult {
77 let rx = take_option!(self.rx);
78 let credit_tx = take_option!(self.credit_tx);
79 let tx = take_option!(self.tx);
80
81 loop {
82 let value = rx.get()?.await;
83 trace!(self.entity ; "issue credit");
84 credit_tx.put(Credit(1))?.await;
85 tx.put(value)?.await;
86 }
87 }
88}