Skip to main content

interchange/
lib.rs

1#![cfg_attr(not(test), no_std)]
2//! Implement a somewhat convenient and somewhat efficient way to perform RPC
3//! in an embedded context.
4//!
5//! The approach is inspired by Go's channels, with the restriction that
6//! there is a clear separation into a requester and a responder.
7//!
8//! Requests may be canceled, which the responder should honour on a
9//! best-effort basis.
10//!
11//! ### Example use cases
12//! - USB device interrupt handler performs low-level protocol details, hands off
13//!   commands from the host to higher-level logic running in the idle thread.
14//!   This higher-level logic need only understand clearly typed commands, as
15//!   moduled by variants of a given `Request` enum.
16//! - `trussed` crypto service, responding to crypto request from apps across
17//!   TrustZone for Cortex-M secure/non-secure boundaries.
18//! - Request to blink a few lights and reply on button press
19//!
20//!
21//! ### Approach
22//! It is assumed that all requests fit in a single `Request` enum, and that
23//! all responses fit in single `Response` enum. The [`Channel`]() and [`Interchange`]() structs allocate a single buffer in which either Request or Response fit and handle synchronization
24//! Both structures have `const` constructors, allowing them to be statically allocated.
25//!
26//! An alternative approach would be to use two heapless Queues of length one
27//! each for response and requests. The advantage of our construction is to
28//! have only one static memory region in use.
29//!
30//! ```
31//! # #![cfg(not(loom))]
32//! # use interchange::{State, Interchange};
33//! #[derive(Clone, Debug, PartialEq)]
34//! pub enum Request {
35//!     This(u8, u32),
36//!     That(i64),
37//! }
38//!
39//! #[derive(Clone, Debug, PartialEq)]
40//! pub enum Response {
41//!     Here(u8, u8, u8),
42//!     There(i16),
43//! }
44//!
45//! static INTERCHANGE: Interchange<Request, Response, 1> = Interchange::new();
46//!
47//! let (mut rq, mut rp) = INTERCHANGE.claim().unwrap();
48//!
49//! assert!(rq.state() == State::Idle);
50//!
51//! // happy path: no cancelation
52//! let request = Request::This(1, 2);
53//! assert!(rq.request(request).is_ok());
54//!
55//! let request = rp.take_request().unwrap();
56//! println!("rp got request: {:?}", request);
57//!
58//! let response = Response::There(-1);
59//! assert!(!rp.is_canceled());
60//! assert!(rp.respond(response).is_ok());
61//!
62//! let response = rq.take_response().unwrap();
63//! println!("rq got response: {:?}", response);
64//!
65//! // early cancelation path
66//! assert!(rq.request(request).is_ok());
67//!
68//! let request =  rq.cancel().unwrap().unwrap();
69//! println!("responder could cancel: {:?}", request);
70//!
71//! assert!(rp.take_request().is_none());
72//! assert!(State::Idle == rq.state());
73//!
74//! // late cancelation
75//! assert!(rq.request(request).is_ok());
76//! let request = rp.take_request().unwrap();
77//!
78//! println!("responder could cancel: {:?}", rq.cancel().unwrap().is_none());
79//! assert!(rp.is_canceled());
80//! assert!(rp.respond(response).is_err());
81//! assert!(rp.acknowledge_cancel().is_ok());
82//! assert!(State::Idle == rq.state());
83//!
84//! // building into request buffer
85//! impl Default for Request {
86//!   fn default() -> Self {
87//!     Request::That(0)
88//!   }
89//! }
90//!
91//! rq.with_request_mut(|r| *r = Request::This(1,2)).unwrap() ;
92//! assert!(rq.send_request().is_ok());
93//! let request = rp.take_request().unwrap();
94//! assert_eq!(request, Request::This(1, 2));
95//! println!("rp got request: {:?}", request);
96//!
97//! // building into response buffer
98//! impl Default for Response {
99//!   fn default() -> Self {
100//!     Response::There(1)
101//!   }
102//! }
103//!
104//! rp.with_response_mut(|r| *r = Response::Here(3,2,1)).unwrap();
105//! assert!(rp.send_response().is_ok());
106//! let response = rq.take_response().unwrap();
107//! assert_eq!(response, Response::Here(3,2,1));
108//!
109//! ```
110
111use core::fmt::{self, Debug};
112use core::sync::atomic::Ordering;
113
114#[cfg(loom)]
115use loom::{
116    cell::UnsafeCell,
117    sync::atomic::{AtomicBool, AtomicU8, AtomicUsize},
118};
119
120#[cfg(not(loom))]
121use core::{
122    cell::UnsafeCell,
123    sync::atomic::{AtomicBool, AtomicU8, AtomicUsize},
124};
125
126#[derive(Clone, Copy)]
127pub struct Error;
128
129impl Debug for Error {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> core::fmt::Result {
131        f.write_str("The interchange is busy, this operation could not be performed")
132    }
133}
134
135#[repr(u8)]
136#[derive(Copy, Clone, Debug, Eq, PartialEq)]
137/// State of the RPC interchange
138pub enum State {
139    /// The requester may send a new request.
140    Idle = 0,
141    /// The requester is building a request, using the pre-allocated static data as &mut Request
142    BuildingRequest = 1,
143    /// The request is pending either processing by responder or cancelation by requester.
144    Requested = 2,
145    /// The responder is building a response, using the pre-allocated static data as &mut Response
146    /// It may opportunitstically be canceled by requester.
147    BuildingResponse = 3,
148    /// The responder sent a response.
149    Responded = 4,
150
151    Canceled = 12,
152}
153
154impl PartialEq<u8> for State {
155    #[inline]
156    fn eq(&self, other: &u8) -> bool {
157        *self as u8 == *other
158    }
159}
160
161impl From<u8> for State {
162    fn from(byte: u8) -> Self {
163        match byte {
164            1 => State::BuildingRequest,
165            2 => State::Requested,
166            3 => State::BuildingResponse,
167            4 => State::Responded,
168            12 => State::Canceled,
169            _ => State::Idle,
170        }
171    }
172}
173
174/// Callback that can be called
175pub type Callback = fn();
176
177// the repr(u8) is necessary so MaybeUninit::zeroized.assume_init() is valid and corresponds to
178// None
179#[repr(u8)]
180enum Message<Rq, Rp> {
181    None,
182    Request(Rq),
183    Response(Rp),
184}
185
186impl<Rq, Rp> Message<Rq, Rp> {
187    fn is_request_state(&self) -> bool {
188        matches!(self, Self::Request(_))
189    }
190
191    fn is_response_state(&self) -> bool {
192        matches!(self, Self::Response(_))
193    }
194
195    fn take_rq(&mut self) -> Rq {
196        let this = core::mem::replace(self, Message::None);
197        match this {
198            Message::Request(r) => r,
199            _ => unreachable!(),
200        }
201    }
202
203    fn rq_ref(&self) -> &Rq {
204        match *self {
205            Self::Request(ref request) => request,
206            _ => unreachable!(),
207        }
208    }
209
210    fn rq_mut(&mut self) -> &mut Rq {
211        match *self {
212            Self::Request(ref mut request) => request,
213            _ => unreachable!(),
214        }
215    }
216
217    fn take_rp(&mut self) -> Rp {
218        let this = core::mem::replace(self, Message::None);
219        match this {
220            Message::Response(r) => r,
221            _ => unreachable!(),
222        }
223    }
224
225    fn rp_ref(&self) -> &Rp {
226        match *self {
227            Self::Response(ref response) => response,
228            _ => unreachable!(),
229        }
230    }
231
232    fn rp_mut(&mut self) -> &mut Rp {
233        match *self {
234            Self::Response(ref mut response) => response,
235            _ => unreachable!(),
236        }
237    }
238
239    fn from_rq(rq: Rq) -> Self {
240        Self::Request(rq)
241    }
242
243    fn from_rp(rp: Rp) -> Self {
244        Self::Response(rp)
245    }
246}
247
248/// Channel used for Request/Response mechanism.
249/// ```
250/// # #![cfg(not(loom))]
251/// # use interchange::{State, Channel};
252/// #[derive(Clone, Debug, PartialEq)]
253/// pub enum Request {
254///     This(u8, u32),
255///     That(i64),
256/// }
257///
258/// #[derive(Clone, Debug, PartialEq)]
259/// pub enum Response {
260///     Here(u8, u8, u8),
261///     There(i16),
262/// }
263///
264/// static CHANNEL: Channel<Request,Response> = Channel::new();
265///
266/// let (mut rq, mut rp) = CHANNEL.split().unwrap();
267///
268/// assert!(rq.state() == State::Idle);
269///
270/// // happy path: no cancelation
271/// let request = Request::This(1, 2);
272/// assert!(rq.request(request).is_ok());
273///
274/// let request = rp.take_request().unwrap();
275/// println!("rp got request: {:?}", request);
276///
277/// let response = Response::There(-1);
278/// assert!(!rp.is_canceled());
279/// assert!(rp.respond(response).is_ok());
280///
281/// let response = rq.take_response().unwrap();
282/// println!("rq got response: {:?}", response);
283///
284/// // early cancelation path
285/// assert!(rq.request(request).is_ok());
286///
287/// let request =  rq.cancel().unwrap().unwrap();
288/// println!("responder could cancel: {:?}", request);
289///
290/// assert!(rp.take_request().is_none());
291/// assert!(State::Idle == rq.state());
292///
293/// // late cancelation
294/// assert!(rq.request(request).is_ok());
295/// let request = rp.take_request().unwrap();
296///
297/// println!("responder could cancel: {:?}", rq.cancel().unwrap().is_none());
298/// assert!(rp.is_canceled());
299/// assert!(rp.respond(response).is_err());
300/// assert!(rp.acknowledge_cancel().is_ok());
301/// assert!(State::Idle == rq.state());
302///
303/// // building into request buffer
304/// impl Default for Request {
305///   fn default() -> Self {
306///     Request::That(0)
307///   }
308/// }
309///
310/// rq.with_request_mut(|r| *r = Request::This(1,2)).unwrap() ;
311/// assert!(rq.send_request().is_ok());
312/// let request = rp.take_request().unwrap();
313/// assert_eq!(request, Request::This(1, 2));
314/// println!("rp got request: {:?}", request);
315///
316/// // building into response buffer
317/// impl Default for Response {
318///   fn default() -> Self {
319///     Response::There(1)
320///   }
321/// }
322///
323/// rp.with_response_mut(|r| *r = Response::Here(3,2,1)).unwrap();
324/// assert!(rp.send_response().is_ok());
325/// let response = rq.take_response().unwrap();
326/// assert_eq!(response, Response::Here(3,2,1));
327///
328/// ```
329pub struct Channel<Rq, Rp> {
330    data: UnsafeCell<Message<Rq, Rp>>,
331    state: AtomicU8,
332    requester_claimed: AtomicBool,
333    responder_claimed: AtomicBool,
334}
335
336impl<Rq, Rp> Channel<Rq, Rp> {
337    // Loom's atomics are not const :/
338    #[cfg(not(loom))]
339    pub const fn new() -> Self {
340        Self {
341            data: UnsafeCell::new(Message::None),
342            state: AtomicU8::new(0),
343            requester_claimed: AtomicBool::new(false),
344            responder_claimed: AtomicBool::new(false),
345        }
346    }
347
348    #[cfg(loom)]
349    pub fn new() -> Self {
350        Self {
351            data: UnsafeCell::new(Message::None),
352            state: AtomicU8::new(0),
353            requester_claimed: AtomicBool::new(false),
354            responder_claimed: AtomicBool::new(false),
355        }
356    }
357
358    /// Obtain the requester end of the channel if it hasn't been taken yet.
359    ///
360    /// Can be called again if the previously obtained [`Requester`]() has been dropped
361    pub fn requester(&self) -> Option<Requester<'_, Rq, Rp>> {
362        if self
363            .requester_claimed
364            .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
365            .is_ok()
366        {
367            Some(Requester {
368                channel: self,
369                callback: || {},
370            })
371        } else {
372            None
373        }
374    }
375
376    /// Obtain the responder end of the channel if it hasn't been taken yet.
377    ///
378    /// Can be called again if the previously obtained [`Responder`]() has been dropped
379    pub fn responder(&self) -> Option<Responder<'_, Rq, Rp>> {
380        if self
381            .responder_claimed
382            .compare_exchange(false, true, Ordering::Relaxed, Ordering::Relaxed)
383            .is_ok()
384        {
385            Some(Responder {
386                channel: self,
387                callback: || {},
388            })
389        } else {
390            None
391        }
392    }
393
394    /// Obtain both the requester and responder ends of the channel.
395    ///
396    /// Can be called again if the previously obtained [`Responder`]() and [`Requester`]() have been dropped
397    pub fn split(&self) -> Option<(Requester<'_, Rq, Rp>, Responder<'_, Rq, Rp>)> {
398        Some((self.requester()?, self.responder()?))
399    }
400
401    fn transition(&self, from: State, to: State) -> bool {
402        self.state
403            .compare_exchange(from as u8, to as u8, Ordering::AcqRel, Ordering::Relaxed)
404            .is_ok()
405    }
406}
407
408impl<Rq, Rp> Default for Channel<Rq, Rp> {
409    fn default() -> Self {
410        Self::new()
411    }
412}
413
414/// Requester end of a channel
415///
416/// For a `static` [`Channel`]() or [`Interchange`](),
417/// the requester uses a `'static` lifetime parameter
418pub struct Requester<'i, Rq, Rp> {
419    channel: &'i Channel<Rq, Rp>,
420    callback: Callback,
421}
422
423impl<Rq, Rp> Drop for Requester<'_, Rq, Rp> {
424    fn drop(&mut self) {
425        self.channel
426            .requester_claimed
427            .store(false, Ordering::Release);
428    }
429}
430
431impl<'i, Rq, Rp> Requester<'i, Rq, Rp> {
432    /// Allows to set a callback that is called when a request has been sent and when a request
433    /// has been cancelled before it was taken by the responder.
434    ///
435    /// The callback is called by [`Requester::request`][], [`Requester::send_request`][] and
436    /// [`Requester::cancel`][].
437    pub fn callback_mut(&mut self) -> &mut Callback {
438        &mut self.callback
439    }
440
441    pub fn channel(&self) -> &'i Channel<Rq, Rp> {
442        self.channel
443    }
444
445    #[cfg(not(loom))]
446    unsafe fn data(&self) -> &Message<Rq, Rp> {
447        &mut *self.channel.data.get()
448    }
449
450    #[cfg(not(loom))]
451    unsafe fn data_mut(&mut self) -> &mut Message<Rq, Rp> {
452        &mut *self.channel.data.get()
453    }
454
455    #[cfg(not(loom))]
456    unsafe fn with_data<R>(&self, f: impl FnOnce(&Message<Rq, Rp>) -> R) -> R {
457        f(&*self.channel.data.get())
458    }
459
460    #[cfg(not(loom))]
461    unsafe fn with_data_mut<R>(&mut self, f: impl FnOnce(&mut Message<Rq, Rp>) -> R) -> R {
462        f(&mut *self.channel.data.get())
463    }
464
465    #[cfg(loom)]
466    unsafe fn with_data<R>(&self, f: impl FnOnce(&Message<Rq, Rp>) -> R) -> R {
467        self.channel.data.with(|i| f(&*i))
468    }
469
470    #[cfg(loom)]
471    unsafe fn with_data_mut<R>(&mut self, f: impl FnOnce(&mut Message<Rq, Rp>) -> R) -> R {
472        self.channel.data.with_mut(|i| f(&mut *i))
473    }
474
475    #[inline]
476    /// Current state of the channel.
477    ///
478    /// Informational only!
479    ///
480    /// The responder may change this state between calls,
481    /// internally atomics ensure correctness.
482    pub fn state(&self) -> State {
483        State::from(self.channel.state.load(Ordering::Acquire))
484    }
485
486    /// Send a request to the responder.
487    ///
488    /// If efficiency is a concern, or requests need multiple steps to
489    /// construct, use `request_mut` and `send_request`.
490    ///
491    /// If the RPC state is `Idle`, this always succeeds, else calling
492    /// is a logic error and the request is returned.
493    ///
494    /// If the request has been sent succesfully, this functions calls the callback set with
495    /// [`Requester::callback_mut`][].
496    pub fn request(&mut self, request: Rq) -> Result<(), Error> {
497        if State::Idle == self.channel.state.load(Ordering::Acquire) {
498            unsafe {
499                self.with_data_mut(|i| *i = Message::from_rq(request));
500            }
501            self.channel
502                .state
503                .store(State::Requested as u8, Ordering::Release);
504            (self.callback)();
505            Ok(())
506        } else {
507            Err(Error)
508        }
509    }
510
511    /// Attempt to cancel a request.
512    ///
513    /// If the responder has not taken the request yet, this succeeds and returns
514    /// the request.
515    ///
516    /// If the responder has taken the request (is processing), we succeed and return None.
517    ///
518    /// In other cases (`Idle` or `Reponsed`) there is nothing to cancel and we fail.
519    ///
520    /// If the responder has not taken the request yet, this functions calls the callback set
521    /// with [`Requester::callback_mut`][].
522    pub fn cancel(&mut self) -> Result<Option<Rq>, Error> {
523        if self
524            .channel
525            .transition(State::BuildingResponse, State::Canceled)
526        {
527            // we canceled after the responder took the request, but before they answered.
528            return Ok(None);
529        }
530
531        if self.channel.transition(State::Requested, State::Idle) {
532            (self.callback)();
533            // we canceled before the responder was even aware of the request.
534            return Ok(Some(unsafe { self.with_data_mut(|i| i.take_rq()) }));
535        }
536
537        Err(Error)
538    }
539
540    /// If there is a response waiting, obtain a reference to it
541    ///
542    /// This may be called multiple times.
543    // Safety: We cannot test this with loom efficiently, but given that `with_response` is tested,
544    // this is likely correct
545    #[cfg(not(loom))]
546    pub fn response(&self) -> Result<&Rp, Error> {
547        if self.channel.transition(State::Responded, State::Responded) {
548            Ok(unsafe { self.data().rp_ref() })
549        } else {
550            Err(Error)
551        }
552    }
553
554    /// If there is a request waiting, perform an operation with a reference to it
555    ///
556    /// This may be called multiple times.
557    pub fn with_response<R>(&self, f: impl FnOnce(&Rp) -> R) -> Result<R, Error> {
558        if self.channel.transition(State::Responded, State::Responded) {
559            Ok(unsafe { self.with_data(|i| f(i.rp_ref())) })
560        } else {
561            Err(Error)
562        }
563    }
564
565    /// Look for a response.
566    /// If the responder has sent a response, we return it.
567    ///
568    /// This may be called only once as it move the state to Idle.
569    /// If you need copies, clone the request.
570    // It is a logic error to call this method if we're Idle or Canceled, but
571    // it seems unnecessary to model this.
572    pub fn take_response(&mut self) -> Option<Rp> {
573        if self.channel.transition(State::Responded, State::Idle) {
574            Some(unsafe { self.with_data_mut(|i| i.take_rp()) })
575        } else {
576            None
577        }
578    }
579}
580
581impl<Rq, Rp> Requester<'_, Rq, Rp>
582where
583    Rq: Default,
584{
585    /// Initialize a request with its default values and mutates it with `f`
586    ///
587    /// This is usefull to build large structures in-place
588    pub fn with_request_mut<R>(&mut self, f: impl FnOnce(&mut Rq) -> R) -> Result<R, Error> {
589        if self.channel.transition(State::Idle, State::BuildingRequest)
590            || self
591                .channel
592                .transition(State::BuildingRequest, State::BuildingRequest)
593        {
594            let res = unsafe {
595                self.with_data_mut(|i| {
596                    if !i.is_request_state() {
597                        *i = Message::from_rq(Rq::default());
598                    }
599                    f(i.rq_mut())
600                })
601            };
602            Ok(res)
603        } else {
604            Err(Error)
605        }
606    }
607
608    /// Initialize a request with its default values and and return a mutable reference to it
609    ///
610    /// This is usefull to build large structures in-place
611    // Safety: We cannot test this with loom efficiently, but given that `with_request_mut` is tested,
612    // this is likely correct
613    #[cfg(not(loom))]
614    pub fn request_mut(&mut self) -> Result<&mut Rq, Error> {
615        if self.channel.transition(State::Idle, State::BuildingRequest)
616            || self
617                .channel
618                .transition(State::BuildingRequest, State::BuildingRequest)
619        {
620            unsafe {
621                self.with_data_mut(|i| {
622                    if !i.is_request_state() {
623                        *i = Message::from_rq(Rq::default());
624                    }
625                })
626            }
627            Ok(unsafe { self.data_mut().rq_mut() })
628        } else {
629            Err(Error)
630        }
631    }
632
633    /// Send a request that was already placed in the channel using `request_mut` or
634    /// `with_request_mut`.
635    ///
636    /// If the request has been sent succesfully, this functions calls the callback set with
637    /// [`Requester::callback_mut`][].
638    pub fn send_request(&mut self) -> Result<(), Error> {
639        if State::BuildingRequest == self.channel.state.load(Ordering::Acquire)
640            && self
641                .channel
642                .transition(State::BuildingRequest, State::Requested)
643        {
644            (self.callback)();
645            Ok(())
646        } else {
647            // logic error
648            Err(Error)
649        }
650    }
651}
652
653/// Responder end of a channel
654///
655/// For a `static` [`Channel`]() or [`Interchange`](),
656/// the responder uses a `'static` lifetime parameter
657pub struct Responder<'i, Rq, Rp> {
658    channel: &'i Channel<Rq, Rp>,
659    callback: Callback,
660}
661
662impl<Rq, Rp> Drop for Responder<'_, Rq, Rp> {
663    fn drop(&mut self) {
664        self.channel
665            .responder_claimed
666            .store(false, Ordering::Release);
667    }
668}
669
670impl<'i, Rq, Rp> Responder<'i, Rq, Rp> {
671    /// Allows to set a callback that is called when a response has been sent.
672    ///
673    /// The callback is called by [`Responder::respond`][] and [`Responder::send_response`][].
674    pub fn callback_mut(&mut self) -> &mut Callback {
675        &mut self.callback
676    }
677
678    pub fn channel(&self) -> &'i Channel<Rq, Rp> {
679        self.channel
680    }
681
682    #[cfg(not(loom))]
683    unsafe fn data(&self) -> &Message<Rq, Rp> {
684        &mut *self.channel.data.get()
685    }
686
687    #[cfg(not(loom))]
688    unsafe fn data_mut(&mut self) -> &mut Message<Rq, Rp> {
689        &mut *self.channel.data.get()
690    }
691
692    #[cfg(not(loom))]
693    unsafe fn with_data<R>(&self, f: impl FnOnce(&Message<Rq, Rp>) -> R) -> R {
694        f(&*self.channel.data.get())
695    }
696
697    #[cfg(not(loom))]
698    unsafe fn with_data_mut<R>(&mut self, f: impl FnOnce(&mut Message<Rq, Rp>) -> R) -> R {
699        f(&mut *self.channel.data.get())
700    }
701
702    #[cfg(loom)]
703    unsafe fn with_data<R>(&self, f: impl FnOnce(&Message<Rq, Rp>) -> R) -> R {
704        self.channel.data.with(|i| f(&*i))
705    }
706
707    #[cfg(loom)]
708    unsafe fn with_data_mut<R>(&mut self, f: impl FnOnce(&mut Message<Rq, Rp>) -> R) -> R {
709        self.channel.data.with_mut(|i| f(&mut *i))
710    }
711
712    #[inline]
713    /// Current state of the channel.
714    ///
715    /// Informational only!
716    ///
717    /// The responder may change this state between calls,
718    /// internally atomics ensure correctness.
719    pub fn state(&self) -> State {
720        State::from(self.channel.state.load(Ordering::Acquire))
721    }
722
723    /// If there is a request waiting, perform an operation with a reference to it
724    ///
725    /// This may be called only once as it move the state to BuildingResponse.
726    /// If you need copies, use `take_request`
727    pub fn with_request<R>(&self, f: impl FnOnce(&Rq) -> R) -> Result<R, Error> {
728        if self
729            .channel
730            .transition(State::Requested, State::BuildingResponse)
731        {
732            Ok(unsafe { self.with_data(|i| f(i.rq_ref())) })
733        } else {
734            Err(Error)
735        }
736    }
737
738    /// If there is a request waiting, obtain a reference to it
739    ///
740    /// This may be called multiple times.
741    // Safety: We cannot test this with loom efficiently, but given that `with_request` is tested,
742    // this is likely correct
743    #[cfg(not(loom))]
744    pub fn request(&self) -> Result<&Rq, Error> {
745        if self
746            .channel
747            .transition(State::Requested, State::BuildingResponse)
748        {
749            Ok(unsafe { self.data().rq_ref() })
750        } else {
751            Err(Error)
752        }
753    }
754
755    /// If there is a request waiting, take a reference to it out
756    ///
757    /// This may be called only once as it move the state to BuildingResponse.
758    /// If you need copies, clone the request.
759    pub fn take_request(&mut self) -> Option<Rq> {
760        if self
761            .channel
762            .transition(State::Requested, State::BuildingResponse)
763        {
764            Some(unsafe { self.with_data_mut(|i| i.take_rq()) })
765        } else {
766            None
767        }
768    }
769
770    // Check if requester attempted to cancel
771    pub fn is_canceled(&self) -> bool {
772        self.channel.state.load(Ordering::SeqCst) == State::Canceled as u8
773    }
774
775    // Acknowledge a cancel, thereby setting Channel to Idle state again.
776    //
777    // It is a logic error to call this method if there is no pending cancellation.
778    pub fn acknowledge_cancel(&self) -> Result<(), Error> {
779        if self.channel.transition(State::Canceled, State::Idle) {
780            Ok(())
781        } else {
782            Err(Error)
783        }
784    }
785
786    /// Respond to a request.
787    ///
788    /// If efficiency is a concern, or responses need multiple steps to
789    /// construct, use `with_response_mut` or `response_mut` and `send_response`.
790    ///
791    /// If the response has been sent succesfully, this functions calls the callback set with
792    /// [`Responder::callback_mut`][].
793    pub fn respond(&mut self, response: Rp) -> Result<(), Error> {
794        if State::BuildingResponse == self.channel.state.load(Ordering::Acquire) {
795            unsafe {
796                self.with_data_mut(|i| *i = Message::from_rp(response));
797            }
798            if self
799                .channel
800                .transition(State::BuildingResponse, State::Responded)
801            {
802                (self.callback)();
803                Ok(())
804            } else {
805                Err(Error)
806            }
807        } else {
808            Err(Error)
809        }
810    }
811}
812
813impl<Rq, Rp> Responder<'_, Rq, Rp>
814where
815    Rp: Default,
816{
817    /// Initialize a response with its default values and mutates it with `f`
818    ///
819    /// This is usefull to build large structures in-place
820    pub fn with_response_mut<R>(&mut self, f: impl FnOnce(&mut Rp) -> R) -> Result<R, Error> {
821        if self
822            .channel
823            .transition(State::Requested, State::BuildingResponse)
824            || self
825                .channel
826                .transition(State::BuildingResponse, State::BuildingResponse)
827        {
828            let res = unsafe {
829                self.with_data_mut(|i| {
830                    if !i.is_response_state() {
831                        *i = Message::from_rp(Rp::default());
832                    }
833                    f(i.rp_mut())
834                })
835            };
836            Ok(res)
837        } else {
838            Err(Error)
839        }
840    }
841
842    /// Initialize a response with its default values and and return a mutable reference to it
843    ///
844    /// This is usefull to build large structures in-place
845    // Safety: We cannot test this with loom efficiently, but given that `with_response_mut` is tested,
846    // this is likely correct
847    #[cfg(not(loom))]
848    pub fn response_mut(&mut self) -> Result<&mut Rp, Error> {
849        if self
850            .channel
851            .transition(State::Requested, State::BuildingResponse)
852            || self
853                .channel
854                .transition(State::BuildingResponse, State::BuildingResponse)
855        {
856            unsafe {
857                self.with_data_mut(|i| {
858                    if !i.is_response_state() {
859                        *i = Message::from_rp(Rp::default());
860                    }
861                })
862            }
863            Ok(unsafe { self.data_mut().rp_mut() })
864        } else {
865            Err(Error)
866        }
867    }
868
869    /// Send a response that was already placed in the channel using `response_mut` or
870    /// `with_response_mut`.
871    ///
872    /// If the response has been sent succesfully, this functions calls the callback set with
873    /// [`Responder::callback_mut`][].
874    pub fn send_response(&mut self) -> Result<(), Error> {
875        if State::BuildingResponse == self.channel.state.load(Ordering::Acquire)
876            && self
877                .channel
878                .transition(State::BuildingResponse, State::Responded)
879        {
880            (self.callback)();
881            Ok(())
882        } else {
883            // logic error
884            Err(Error)
885        }
886    }
887}
888
889// Safety: The channel can be split, which then allows getting sending the Rq and Rp types across threads
890// TODO: is the Sync bound really necessary?
891unsafe impl<Rq, Rp> Sync for Channel<Rq, Rp>
892where
893    Rq: Send + Sync,
894    Rp: Send + Sync,
895{
896}
897
898/// Set of `N` channels
899///
900/// Channels can be claimed with [`claim()`](Self::claim)
901///
902/// ```
903/// # #![cfg(not(loom))]
904/// # use interchange::*;
905/// # #[derive(Clone, Debug, PartialEq)]
906/// # pub enum Request {
907/// #     This(u8, u32),
908/// #     That(i64),
909/// # }
910/// #
911/// # #[derive(Clone, Debug, PartialEq)]
912/// # pub enum Response {
913/// #     Here(u8, u8, u8),
914/// #     There(i16),
915/// # }
916/// #
917/// static interchange: Interchange<Request, Response,10> = Interchange::new();
918///
919/// for i in 0..10 {
920///     let rq: Requester<'_, Request, Response>;
921///     let rp: Responder<'_, Request, Response>;
922///     (rq, rp) = interchange.claim().unwrap() ;
923/// }
924/// ```
925pub struct Interchange<Rq, Rp, const N: usize> {
926    channels: [Channel<Rq, Rp>; N],
927    last_claimed: AtomicUsize,
928}
929
930impl<Rq, Rp, const N: usize> Interchange<Rq, Rp, N> {
931    /// Create a new Interchange
932    #[cfg(not(loom))]
933    pub const fn new() -> Self {
934        Self {
935            channels: [const { Channel::new() }; N],
936            last_claimed: AtomicUsize::new(0),
937        }
938    }
939
940    /// Create a new Interchange
941    #[cfg(loom)]
942    pub fn new() -> Self {
943        Self {
944            channels: core::array::from_fn(|_| Channel::new()),
945            last_claimed: AtomicUsize::new(0),
946        }
947    }
948
949    /// Claim one of the channels of the interchange. Returns None if called more than `N` times.
950    pub fn claim(&'_ self) -> Option<(Requester<'_, Rq, Rp>, Responder<'_, Rq, Rp>)> {
951        self.as_interchange_ref().claim()
952    }
953
954    /// Returns a reference to the interchange with the `N` const-generic removed.
955    /// This can avoid the requirement to have `const N: usize` everywhere
956    /// ```
957    /// # #![cfg(not(loom))]
958    /// # use interchange::{State, Interchange, InterchangeRef};
959    /// # #[derive(Clone, Debug, PartialEq)]
960    /// # pub enum Request {
961    /// #     This(u8, u32),
962    /// #     That(i64),
963    /// # }
964    /// # #[derive(Clone, Debug, PartialEq)]
965    /// # pub enum Response {
966    /// #     Here(u8, u8, u8),
967    /// #     There(i16),
968    /// # }
969    /// static INTERCHANGE_INNER: Interchange<Request, Response, 1> = Interchange::new();
970    ///
971    /// // The size of the interchange is absent from the type
972    /// static INTERCHANGE: InterchangeRef<'static, Request, Response> = INTERCHANGE_INNER.as_interchange_ref();
973    ///
974    /// let (mut rq, mut rp) = INTERCHANGE.claim().unwrap();
975    /// ```
976    pub const fn as_interchange_ref(&self) -> InterchangeRef<'_, Rq, Rp> {
977        InterchangeRef {
978            channels: &self.channels,
979            last_claimed: &self.last_claimed,
980        }
981    }
982}
983
984/// Interchange witout the `const N: usize` generic parameter
985/// Obtained using [`Interchange::as_interchange_ref`](Interchange::as_interchange_ref)
986pub struct InterchangeRef<'alloc, Rq, Rp> {
987    channels: &'alloc [Channel<Rq, Rp>],
988    last_claimed: &'alloc AtomicUsize,
989}
990
991impl<'alloc, Rq, Rp> InterchangeRef<'alloc, Rq, Rp> {
992    /// Claim one of the channels of the interchange. Returns None if called more than `N` times.
993    pub fn claim(&self) -> Option<(Requester<'alloc, Rq, Rp>, Responder<'alloc, Rq, Rp>)> {
994        let index = self.last_claimed.fetch_add(1, Ordering::Relaxed);
995        let n = self.channels.len();
996
997        for i in (index % n)..n {
998            let tmp = self.channels[i].split();
999            if tmp.is_some() {
1000                return tmp;
1001            }
1002        }
1003
1004        for i in 0..(index % n) {
1005            let tmp = self.channels[i].split();
1006            if tmp.is_some() {
1007                return tmp;
1008            }
1009        }
1010        None
1011    }
1012}
1013
1014impl<Rq, Rp> Clone for InterchangeRef<'_, Rq, Rp> {
1015    fn clone(&self) -> Self {
1016        *self
1017    }
1018}
1019
1020impl<Rq, Rp> Copy for InterchangeRef<'_, Rq, Rp> {}
1021
1022impl<Rq, Rp, const N: usize> Default for Interchange<Rq, Rp, N> {
1023    fn default() -> Self {
1024        Self::new()
1025    }
1026}
1027
1028/// ```compile_fail
1029/// use std::rc::Rc;
1030/// use interchange::*;
1031/// #[allow(unconditional_recursion, unused)]
1032/// fn assert_send<T: Send>() {
1033///     assert_send::<Channel<Rc<String>, u32>>();
1034/// }
1035/// ```
1036/// ```compile_fail
1037/// use std::rc::Rc;
1038/// use interchange::*;
1039/// #[allow(unconditional_recursion, unused)]
1040/// fn assert_send<T: Send>() {
1041///     assert_send::<Requester<Rc<String>, u32>>();
1042/// }
1043/// ```
1044/// ```compile_fail
1045/// use std::rc::Rc;
1046/// use interchange::*;
1047/// #[allow(unconditional_recursion, unused)]
1048/// fn assert_send<T: Send>() {
1049///     assert_send::<Responder<Rc<String>, u32>>();
1050/// }
1051/// ```
1052/// ```compile_fail
1053/// use std::rc::Rc;
1054/// use interchange::*;
1055/// #[allow(unconditional_recursion, unused)]
1056/// fn assert_sync<T: Sync>() {
1057///     assert_sync::<Channel<Rc<String>, u32>>();
1058/// }
1059/// ```
1060/// ```compile_fail
1061/// use std::rc::Rc;
1062/// use interchange::*;
1063/// #[allow(unconditional_recursion, unused)]
1064/// fn assert_sync<T: Sync>() {
1065///     assert_sync::<Requester<Rc<String>, u32>>();
1066/// }
1067/// ```
1068/// ```compile_fail
1069/// use std::rc::Rc;
1070/// use interchange::*;
1071/// #[allow(unconditional_recursion, unused)]
1072/// fn assert_sync<T: Sync>() {
1073///     assert_sync::<Responder<Rc<String>, u32>>();
1074/// }
1075/// ```
1076const _ASSERT_COMPILE_FAILS: () = {};
1077
1078#[cfg(all(not(loom), test))]
1079mod tests {
1080    use super::*;
1081    #[derive(Clone, Debug, PartialEq)]
1082    pub enum Request {
1083        This(u8, u32),
1084    }
1085    #[derive(Clone, Debug, PartialEq)]
1086    pub enum Response {
1087        Here(u8, u8, u8),
1088        There(i16),
1089    }
1090    impl Default for Response {
1091        fn default() -> Self {
1092            Response::There(1)
1093        }
1094    }
1095    impl Default for Request {
1096        fn default() -> Self {
1097            Request::This(0, 0)
1098        }
1099    }
1100
1101    #[test]
1102    fn interchange() {
1103        static INTERCHANGE: Interchange<Request, Response, 1> = Interchange::new();
1104        let (mut rq, mut rp) = INTERCHANGE.claim().unwrap();
1105        assert_eq!(rq.state(), State::Idle);
1106        // happy path: no cancelation
1107        let request = Request::This(1, 2);
1108        assert!(rq.request(request).is_ok());
1109        let request = rp.take_request().unwrap();
1110        println!("rp got request: {request:?}");
1111        let response = Response::There(-1);
1112        assert!(!rp.is_canceled());
1113        assert!(rp.respond(response).is_ok());
1114        let response = rq.take_response().unwrap();
1115        println!("rq got response: {response:?}");
1116        // early cancelation path
1117        assert!(rq.request(request).is_ok());
1118        let request = rq.cancel().unwrap().unwrap();
1119        println!("responder could cancel: {request:?}");
1120        assert!(rp.take_request().is_none());
1121        assert_eq!(State::Idle, rq.state());
1122        // late cancelation
1123        assert!(rq.request(request).is_ok());
1124        let request = rp.take_request().unwrap();
1125        println!(
1126            "responder could cancel: {:?}",
1127            rq.cancel().unwrap().is_none()
1128        );
1129        assert_eq!(request, Request::This(1, 2));
1130        assert!(rp.is_canceled());
1131        assert!(rp.respond(response).is_err());
1132        assert!(rp.acknowledge_cancel().is_ok());
1133        assert_eq!(State::Idle, rq.state());
1134        // building into request buffer
1135        rq.with_request_mut(|r| *r = Request::This(1, 2)).unwrap();
1136        assert!(rq.send_request().is_ok());
1137        let request = rp.take_request().unwrap();
1138        assert_eq!(request, Request::This(1, 2));
1139        println!("rp got request: {request:?}");
1140        // building into response buffer
1141        rp.with_response_mut(|r| *r = Response::Here(3, 2, 1))
1142            .unwrap();
1143        assert!(rp.send_response().is_ok());
1144        let response = rq.take_response().unwrap();
1145        assert_eq!(response, Response::Here(3, 2, 1));
1146    }
1147
1148    #[test]
1149    fn interchange_ref() {
1150        static INTERCHANGE_INNER: Interchange<Request, Response, 1> = Interchange::new();
1151        static INTERCHANGE: InterchangeRef<'static, Request, Response> =
1152            INTERCHANGE_INNER.as_interchange_ref();
1153        let (mut rq, mut rp) = INTERCHANGE.claim().unwrap();
1154        assert_eq!(rq.state(), State::Idle);
1155        // happy path: no cancelation
1156        let request = Request::This(1, 2);
1157        assert!(rq.request(request).is_ok());
1158        let request = rp.take_request().unwrap();
1159        println!("rp got request: {request:?}");
1160        let response = Response::There(-1);
1161        assert!(!rp.is_canceled());
1162        assert!(rp.respond(response).is_ok());
1163        let response = rq.take_response().unwrap();
1164        println!("rq got response: {response:?}");
1165        // early cancelation path
1166        assert!(rq.request(request).is_ok());
1167        let request = rq.cancel().unwrap().unwrap();
1168        println!("responder could cancel: {request:?}");
1169        assert!(rp.take_request().is_none());
1170        assert_eq!(State::Idle, rq.state());
1171        // late cancelation
1172        assert!(rq.request(request).is_ok());
1173        let request = rp.take_request().unwrap();
1174        println!(
1175            "responder could cancel: {:?}",
1176            rq.cancel().unwrap().is_none()
1177        );
1178        assert_eq!(request, Request::This(1, 2));
1179        assert!(rp.is_canceled());
1180        assert!(rp.respond(response).is_err());
1181        assert!(rp.acknowledge_cancel().is_ok());
1182        assert_eq!(State::Idle, rq.state());
1183        // building into request buffer
1184        rq.with_request_mut(|r| *r = Request::This(1, 2)).unwrap();
1185        assert!(rq.send_request().is_ok());
1186        let request = rp.take_request().unwrap();
1187        assert_eq!(request, Request::This(1, 2));
1188        println!("rp got request: {request:?}");
1189        // building into response buffer
1190        rp.with_response_mut(|r| *r = Response::Here(3, 2, 1))
1191            .unwrap();
1192        assert!(rp.send_response().is_ok());
1193        let response = rq.take_response().unwrap();
1194        assert_eq!(response, Response::Here(3, 2, 1));
1195    }
1196
1197    #[allow(unconditional_recursion, clippy::extra_unused_type_parameters, unused)]
1198    fn assert_send<T: Send>() {
1199        assert_send::<Channel<String, u32>>();
1200        assert_send::<Responder<'static, String, u32>>();
1201        assert_send::<Requester<'static, String, u32>>();
1202        assert_send::<Channel<&'static mut String, u32>>();
1203        assert_send::<Responder<'static, &'static mut String, u32>>();
1204        assert_send::<Requester<'static, &'static mut String, u32>>();
1205    }
1206    #[allow(unconditional_recursion, clippy::extra_unused_type_parameters, unused)]
1207    fn assert_sync<T: Sync>() {
1208        assert_sync::<Channel<String, u32>>();
1209        assert_sync::<Channel<String, u32>>();
1210        assert_sync::<Responder<'static, String, u32>>();
1211        assert_sync::<Requester<'static, String, u32>>();
1212
1213        assert_sync::<Channel<&'static mut String, u32>>();
1214        assert_sync::<Responder<'static, &'static mut String, u32>>();
1215        assert_sync::<Requester<'static, &'static mut String, u32>>();
1216    }
1217}