use crate::actor::{Prep, State};
use crate::cell::cell::{ActorCell, ActorCellOwner};
use crate::queue::FnOnceQueue;
use crate::rc::count::CountAndState;
use crate::{Core, Deferrer, LogID, Ret, Stakker, StopCause};
use std::cell::Cell;
use std::mem;
use std::rc::Rc;
struct ActorBox<A> {
strong: Cell<CountAndState>, notify: Cell<Option<Ret<StopCause>>>, deferrer: Deferrer, #[cfg(feature = "logger")]
id: LogID,
inner: ActorCell<Inner<A>>, }
enum Inner<A> {
Prep(Prep),
Ready(A),
Zombie,
}
pub(crate) struct ActorRc<A: 'static>(Rc<ActorBox<A>>);
impl<A> ActorRc<A> {
pub fn new(core: &mut Core, notify: Option<Ret<StopCause>>, _parent_id: LogID) -> Self {
Self(Rc::new(ActorBox {
strong: Cell::new(CountAndState::new()),
notify: Cell::new(notify),
#[cfg(feature = "logger")]
id: core.log_span_open(std::any::type_name::<A>(), _parent_id, |_| {}),
inner: core.actor_maker.cell(Inner::Prep(Prep {
queue: FnOnceQueue::new(),
})),
deferrer: core.deferrer(),
}))
}
#[inline]
pub fn id(&self) -> LogID {
#[cfg(feature = "logger")]
{
self.0.id
}
#[cfg(not(feature = "logger"))]
0
}
#[inline]
fn strong(&self) -> &Cell<CountAndState> {
&self.0.strong
}
pub fn strong_inc(&self) {
self.strong().replace(self.strong().get().inc());
}
pub fn strong_dec(&self) -> bool {
let (count, went_to_zero) = self.strong().get().dec();
self.strong().replace(count);
went_to_zero
}
#[inline]
pub fn is_zombie(&self) -> bool {
self.strong().get().is_zombie()
}
#[inline]
pub fn is_prep(&self) -> bool {
self.strong().get().is_prep()
}
pub fn to_ready(&self, s: &mut Stakker, val: A) {
let inner = s.actor_owner.rw(&self.0.inner);
match mem::replace(inner, Inner::Ready(val)) {
Inner::Prep(mut prep) => {
self.strong()
.replace(self.strong().get().set_state(State::Ready));
prep.queue.execute(s);
}
Inner::Ready(_) => panic!("Actor::to_ready() called twice"),
Inner::Zombie => *inner = Inner::Zombie,
}
}
pub fn to_zombie(&self, s: &mut Stakker) -> Option<Ret<StopCause>> {
self.strong()
.replace(self.strong().get().set_state(State::Zombie));
*s.actor_owner.rw(&self.0.inner) = Inner::Zombie;
self.0.notify.replace(None)
}
pub fn borrow_ready<'a>(&'a self, o: &'a mut ActorCellOwner) -> Option<&'a mut A> {
match o.rw(&self.0.inner) {
Inner::Ready(val) => Some(val),
_ => None,
}
}
pub fn borrow_prep<'a>(&'a self, o: &'a mut ActorCellOwner) -> Option<&'a mut Prep> {
match o.rw(&self.0.inner) {
Inner::Prep(prep) => Some(prep),
_ => None,
}
}
#[inline]
pub fn access_deferrer(&self) -> &Deferrer {
&self.0.deferrer
}
}
impl<A> Clone for ActorRc<A> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}