diff --git a/help.html b/help.html index cc4f51c..47fd1e9 100644 --- a/help.html +++ b/help.html @@ -1 +1 @@ -
#[repr(u8)]
+State in interchange - Rust Enum interchange::State
source · #[repr(u8)]
pub enum State {
Idle,
BuildingRequest,
@@ -7,7 +7,7 @@
Responded,
Canceled,
// some variants omitted
-}
Expand description
State of the RPC interchange
+}Expand description
State of the RPC interchange
Variants§
§Idle
The requester may send a new request.
§BuildingRequest
The requester is building a request, using the pre-allocated static data as &mut Request
§Requested
The request is pending either processing by responder or cancelation by requester.
@@ -16,12 +16,18 @@
§Responded
The responder sent a response.
§Canceled
The requester canceled the request. Responder needs to acknowledge to return to Idle
state.
-Trait Implementations§
source§impl PartialEq<State> for State
source§impl PartialEq<u8> for State
source§impl Copy for State
source§impl Eq for State
source§impl StructuralEq for State
source§impl StructuralPartialEq for State
Auto Trait Implementations§
§impl RefUnwindSafe for State
§impl Send for State
§impl Sync for State
§impl Unpin for State
§impl UnwindSafe for State
Blanket Implementations§
source§impl<T, U> Into<U> for Twhere
U: From<T>,
Trait Implementations§
source§impl PartialEq<State> for State
source§impl PartialEq<u8> for State
source§impl Copy for State
source§impl Eq for State
source§impl StructuralEq for State
source§impl StructuralPartialEq for State
Auto Trait Implementations§
§impl RefUnwindSafe for State
§impl Send for State
§impl Sync for State
§impl Unpin for State
§impl UnwindSafe for State
Blanket Implementations§
\ No newline at end of file
+From<T> for U
chooses to do.
+
Implement a somewhat convenient and somewhat efficient way to perform RPC +
Implement a somewhat convenient and somewhat efficient way to perform RPC in an embedded context.
The approach is inspired by Go’s channels, with the restriction that there is a clear separation into a requester and a responder.
@@ -16,7 +16,7 @@It is assumed that all requests fit in a single Request
enum, and that
-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
+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
Both structures have const
constructors, allowing them to be statically allocated.
An alternative approach would be to use two heapless Queues of length one each for response and requests. The advantage of our construction is to @@ -98,5 +98,5 @@
N
channelsconst N: usize
generic parameter
-Obtained using Interchange::as_interchange_ref
N
channelsconst N: usize
generic parameter
+Obtained using Interchange::as_interchange_ref
pub struct Channel<Rq, Rp> { /* private fields */ }
Channel used for Request/Response mechanism.
+pub struct Channel<Rq, Rp> { /* private fields */ }
Channel used for Request/Response mechanism.
#[derive(Clone, Debug, PartialEq)]
pub enum Request {
@@ -76,14 +76,28 @@
let response = rq.take_response().unwrap();
assert_eq!(response, Response::Here(3,2,1));
Obtain the requester end of the channel if it hasn’t been taken yet.
-Can be called again if the previously obtained Requester
has been dropped
Obtain the requester end of the channel if it hasn’t been taken yet.
+Can be called again if the previously obtained Requester
has been dropped
From<T> for U
chooses to do.
+pub struct Error;
Calls U::from(self)
.
pub struct Error;
From<T> for U
chooses to do.
+pub struct Interchange<Rq, Rp, const N: usize> { /* private fields */ }
Set of N
channels
Channels can be claimed with claim()
pub struct Interchange<Rq, Rp, const N: usize> { /* private fields */ }
Set of N
channels
Channels can be claimed with claim()
static interchange: Interchange<Request, Response,10> = Interchange::new();
@@ -8,9 +8,9 @@
let rp: Responder<'_, Request, Response>;
(rq, rp) = interchange.claim().unwrap() ;
}
Claim one of the channels of the interchange. Returns None if called more than N
times.
Returns a reference to the interchange with the N
const-generic removed.
+
Claim one of the channels of the interchange. Returns None if called more than N
times.
Returns a reference to the interchange with the N
const-generic removed.
This can avoid the requirement to have const N: usize
everywhere
static INTERCHANGE_INNER: Interchange<Request, Response, 1> = Interchange::new();
@@ -19,8 +19,22 @@
static INTERCHANGE: InterchangeRef<'static, Request, Response> = INTERCHANGE_INNER.as_interchange_ref();
let (mut rq, mut rp) = INTERCHANGE.claim().unwrap();
From<T> for U
chooses to do.
+pub struct InterchangeRef<'alloc, Rq, Rp> { /* private fields */ }
Interchange witout the const N: usize
generic parameter
-Obtained using Interchange::as_interchange_ref
Calls U::from(self)
.
pub struct InterchangeRef<'alloc, Rq, Rp> { /* private fields */ }
Interchange witout the const N: usize
generic parameter
+Obtained using Interchange::as_interchange_ref
From<T> for U
chooses to do.
+pub struct Requester<'i, Rq, Rp> { /* private fields */ }
Requester end of a channel
-For a static
Channel
or Interchange
,
+
pub struct Requester<'i, Rq, Rp> { /* private fields */ }
Requester end of a channel
+For a static
Channel
or Interchange
,
the requester uses a 'static
lifetime parameter
Current state of the channel.
Informational only!
The responder may change this state between calls, internally atomics ensure correctness.
-Send a request to the responder.
If efficiency is a concern, or requests need multiple steps to
construct, use request_mut
and `send_request.
If the RPC state is Idle
, this always succeeds, else calling
is a logic error and the request is returned.
Attempt to cancel a request.
If the responder has not taken the request yet, this succeeds and returns the request.
If the responder has taken the request (is processing), we succeed and return None.
In other cases (Idle
or Reponsed
) there is nothing to cancel and we fail.
If there is a response waiting, obtain a reference to it
+If there is a response waiting, obtain a reference to it
This may be called multiple times.
-If there is a request waiting, perform an operation with a reference to it
+If there is a request waiting, perform an operation with a reference to it
This may be called multiple times.
-Look for a response. +
Look for a response. If the responder has sent a response, we return it.
This may be called only once as it move the state to Idle. If you need copies, clone the request.
-Initialize a request with its default values and mutates it with f
This is usefull to build large structures in-place
-Initialize a request with its default values and and return a mutable reference to it
+Initialize a request with its default values and and return a mutable reference to it
This is usefull to build large structures in-place
-Send a request that was already placed in the channel using request_mut
or
+
Send a request that was already placed in the channel using request_mut
or
with_request_mut
.
From<T> for U
chooses to do.
+pub struct Responder<'i, Rq, Rp> { /* private fields */ }
Responder end of a channel
-For a static
Channel
or Interchange
,
+
pub struct Responder<'i, Rq, Rp> { /* private fields */ }
Responder end of a channel
+For a static
Channel
or Interchange
,
the responder uses a 'static
lifetime parameter
Current state of the channel.
Informational only!
The responder may change this state between calls, internally atomics ensure correctness.
-If there is a request waiting, perform an operation with a reference to it
+If there is a request waiting, perform an operation with a reference to it
This may be called only once as it move the state to BuildingResponse.
If you need copies, use take_request
If there is a request waiting, obtain a reference to it
+If there is a request waiting, obtain a reference to it
This may be called multiple times.
-If there is a request waiting, take a reference to it out
+If there is a request waiting, take a reference to it out
This may be called only once as it move the state to BuildingResponse. If you need copies, clone the request.
-Initialize a response with its default values and mutates it with f
This is usefull to build large structures in-place
-Initialize a response with its default values and and return a mutable reference to it
+Initialize a response with its default values and and return a mutable reference to it
This is usefull to build large structures in-place
-Send a response that was already placed in the channel using response_mut
or
+
Send a response that was already placed in the channel using response_mut
or
with_response_mut
.
From<T> for U
chooses to do.
+N
channels","Interchange witout the const N: usize
generic parameter …","The request is pending either processing by responder or …","Requester end of a channel","The responder sent a response.","Responder end of a channel","State of the RPC interchange","","Returns a reference to the interchange with the N
…","","","","","","","","","","","","","","","Attempt to cancel a request.","Claim one of the channels of the interchange. Returns None …","Claim one of the channels of the interchange. Returns None …","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","","","Create a new Interchange","Send a request to the responder.","If there is a request waiting, obtain a reference to it","Initialize a request with its default values and and …","Obtain the requester end of the channel if it hasn’t …","Respond to a request.","Obtain the responder end of the channel if it hasn’t …","If there is a response waiting, obtain a reference to it","Initialize a response with its default values and and …","Send a request that was already placed in the channel …","Send a response that was already placed in the channel …","Obtain both the requester and responder ends of the …","Current state of the channel.","Current state of the channel.","If there is a request waiting, take a reference to it out","Look for a response. If the responder has sent a response, …","","","","","","","","","","","","","","","","","","","","","","If there is a request waiting, perform an operation with a …","Initialize a request with its default values and mutates …","If there is a request waiting, perform an operation with a …","Initialize a response with its default values and mutates …"],"i":[8,8,8,0,0,8,0,0,8,0,8,0,0,1,4,9,6,1,4,5,2,8,9,6,1,4,5,2,8,6,4,5,2,8,9,4,6,1,8,8,2,8,9,6,1,4,5,2,8,8,9,6,1,4,5,2,8,1,9,4,6,1,6,9,1,9,6,1,6,1,9,6,1,1,6,9,6,1,4,5,2,8,9,6,1,4,5,2,8,9,6,1,4,5,2,8,1,6,6,1],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,[1,[[3,[2]]]],[4,5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[6,[[3,[7,2]]]],[4,7],[5,7],[2,2],[8,8],[[],9],[[],4],[6],[1],[[8,8],10],[[8,11],10],[[2,12],13],[[8,12],13],[[]],[[]],[[]],[[]],[[]],[[]],[11,8],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[1,10],[[],9],[[],4],[6,[[3,[2]]]],[1,[[3,[2]]]],[6,[[3,[2]]]],[9,[[7,[6]]]],[1,[[3,[2]]]],[9,[[7,[1]]]],[6,[[3,[2]]]],[1,[[3,[2]]]],[6,[[3,[2]]]],[1,[[3,[2]]]],[9,7],[6,8],[1,8],[1,7],[6,7],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],14],[[],14],[[],14],[[],14],[[],14],[[],14],[[],14],[[1,15],[[3,[2]]]],[[6,15],[[3,[2]]]],[[6,15],[[3,[2]]]],[[1,15],[[3,[2]]]]],"p":[[3,"Responder"],[3,"Error"],[4,"Result"],[3,"Interchange"],[3,"InterchangeRef"],[3,"Requester"],[4,"Option"],[4,"State"],[3,"Channel"],[15,"bool"],[15,"u8"],[3,"Formatter"],[6,"Result"],[3,"TypeId"],[8,"FnOnce"]]}\
+"interchange":{"doc":"Implement a somewhat convenient and somewhat efficient way …","t":"NNNDDNDDNDNDELLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL","n":["BuildingRequest","BuildingResponse","Canceled","Channel","Error","Idle","Interchange","InterchangeRef","Requested","Requester","Responded","Responder","State","acknowledge_cancel","as_interchange_ref","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","cancel","claim","claim","clone","clone","default","default","drop","drop","eq","eq","fmt","fmt","from","from","from","from","from","from","from","from","into","into","into","into","into","into","into","is_canceled","new","new","request","request","request_mut","requester","respond","responder","response","response_mut","send_request","send_response","split","state","state","take_request","take_response","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","with_request","with_request_mut","with_response","with_response_mut"],"q":[[0,"interchange"]],"d":["The requester is building a request, using the …","The responder is building a response, using the …","The requester canceled the request. Responder needs to …","Channel used for Request/Response mechanism.","","The requester may send a new request.","Set of N
channels","Interchange witout the const N: usize
generic parameter …","The request is pending either processing by responder or …","Requester end of a channel","The responder sent a response.","Responder end of a channel","State of the RPC interchange","","Returns a reference to the interchange with the N
…","","","","","","","","","","","","","","","Attempt to cancel a request.","Claim one of the channels of the interchange. Returns None …","Claim one of the channels of the interchange. Returns None …","","","","","","","","","","","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","Returns the argument unchanged.","","Returns the argument unchanged.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","Calls U::from(self)
.","","","Create a new Interchange","Send a request to the responder.","If there is a request waiting, obtain a reference to it","Initialize a request with its default values and and …","Obtain the requester end of the channel if it hasn’t …","Respond to a request.","Obtain the responder end of the channel if it hasn’t …","If there is a response waiting, obtain a reference to it","Initialize a response with its default values and and …","Send a request that was already placed in the channel …","Send a response that was already placed in the channel …","Obtain both the requester and responder ends of the …","Current state of the channel.","Current state of the channel.","If there is a request waiting, take a reference to it out","Look for a response. If the responder has sent a response, …","","","","","","","","","","","","","","","","","","","","","","If there is a request waiting, perform an operation with a …","Initialize a request with its default values and mutates …","If there is a request waiting, perform an operation with a …","Initialize a response with its default values and mutates …"],"i":[8,8,8,0,0,8,0,0,8,0,8,0,0,1,4,9,6,1,4,5,2,8,9,6,1,4,5,2,8,6,4,5,2,8,9,4,6,1,8,8,2,8,9,6,1,4,5,2,8,8,9,6,1,4,5,2,8,1,9,4,6,1,6,9,1,9,6,1,6,1,9,6,1,1,6,9,6,1,4,5,2,8,9,6,1,4,5,2,8,9,6,1,4,5,2,8,1,6,6,1],"f":[0,0,0,0,0,0,0,0,0,0,0,0,0,[1,[[3,[2]]]],[4,5],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[6,[[3,[7,2]]]],[4,7],[5,7],[2,2],[8,8],[[],9],[[],4],[6],[1],[[8,10],11],[[8,8],11],[[2,12],13],[[8,12],13],[[]],[[]],[[]],[[]],[[]],[[]],[10,8],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[1,11],[[],9],[[],4],[6,[[3,[2]]]],[1,[[3,[2]]]],[[[6,[14]]],[[3,[14,2]]]],[9,[[7,[6]]]],[1,[[3,[2]]]],[9,[[7,[1]]]],[6,[[3,[2]]]],[[[1,[14]]],[[3,[14,2]]]],[[[6,[14]]],[[3,[2]]]],[[[1,[14]]],[[3,[2]]]],[9,7],[6,8],[1,8],[1,7],[6,7],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],3],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[],15],[[1,16],[[3,[2]]]],[[[6,[14]],16],[[3,[2]]]],[[6,16],[[3,[2]]]],[[[1,[14]],16],[[3,[2]]]]],"c":[],"p":[[3,"Responder"],[3,"Error"],[4,"Result"],[3,"Interchange"],[3,"InterchangeRef"],[3,"Requester"],[4,"Option"],[4,"State"],[3,"Channel"],[15,"u8"],[15,"bool"],[3,"Formatter"],[6,"Result"],[8,"Default"],[3,"TypeId"],[8,"FnOnce"]]}\
}');
if (typeof window !== 'undefined' && window.initSearch) {window.initSearch(searchIndex)};
if (typeof exports !== 'undefined') {exports.searchIndex = searchIndex};
diff --git a/settings.html b/settings.html
index 4875295..5fc9d25 100644
--- a/settings.html
+++ b/settings.html
@@ -1 +1 @@
-1 +lib.rs - source \ No newline at end of file + -1 2 3 4 @@ -1079,7 +1079,82 @@ 1079 1080 1081 -#![cfg_attr(not(test), no_std)] +1082 +1083 +1084 +1085 +1086 +1087 +1088 +1089 +1090 +1091 +1092 +1093 +1094 +1095 +1096 +1097 +1098 +1099 +1100 +1101 +1102 +1103 +1104 +1105 +1106 +1107 +1108 +1109 +1110 +1111 +1112 +1113 +1114 +1115 +1116 +1117 +1118 +1119 +1120 +1121 +1122 +1123 +1124 +1125 +1126 +1127 +1128 +1129 +1130 +1131 +1132 +1133 +1134 +1135 +1136 +1137 +1138 +1139 +1140 +1141 +1142 +1143 +1144 +1145 +1146 +1147 +1148 +1149 +1150 +1151 +1152 +1153 +1154 +1155 +1156 +
#![cfg_attr(not(test), no_std)] //! Implement a somewhat convenient and somewhat efficient way to perform RPC //! in an embedded context. //! @@ -1923,10 +1998,14 @@ } } -unsafe impl<'i, Rq, Rp> Send for Responder<'i, Rq, Rp> {} -unsafe impl<'i, Rq, Rp> Send for Requester<'i, Rq, Rp> {} -unsafe impl<Rq, Rp> Send for Channel<Rq, Rp> {} -unsafe impl<Rq, Rp> Sync for Channel<Rq, Rp> {} +// Safety: The channel can be split, which then allows getting sending the Rq and Rp types across threads +// TODO: is the Sync bound really necessary? +unsafe impl<Rq, Rp> Sync for Channel<Rq, Rp> +where + Rq: Send + Sync, + Rp: Send + Sync, +{ +} /// Set of `N` channels /// @@ -2041,6 +2120,56 @@ } } +/// ```compile_fail +/// use std::rc::Rc; +/// use interchange::*; +/// #[allow(unconditional_recursion, unused)] +/// fn assert_send<T: Send>() { +/// assert_send::<Channel<Rc<String>, u32>>(); +/// } +/// ``` +/// ```compile_fail +/// use std::rc::Rc; +/// use interchange::*; +/// #[allow(unconditional_recursion, unused)] +/// fn assert_send<T: Send>() { +/// assert_send::<Requester<Rc<String>, u32>>(); +/// } +/// ``` +/// ```compile_fail +/// use std::rc::Rc; +/// use interchange::*; +/// #[allow(unconditional_recursion, unused)] +/// fn assert_send<T: Send>() { +/// assert_send::<Responder<Rc<String>, u32>>(); +/// } +/// ``` +/// ```compile_fail +/// use std::rc::Rc; +/// use interchange::*; +/// #[allow(unconditional_recursion, unused)] +/// fn assert_sync<T: Sync>() { +/// assert_sync::<Channel<Rc<String>, u32>>(); +/// } +/// ``` +/// ```compile_fail +/// use std::rc::Rc; +/// use interchange::*; +/// #[allow(unconditional_recursion, unused)] +/// fn assert_sync<T: Sync>() { +/// assert_sync::<Requester<Rc<String>, u32>>(); +/// } +/// ``` +/// ```compile_fail +/// use std::rc::Rc; +/// use interchange::*; +/// #[allow(unconditional_recursion, unused)] +/// fn assert_sync<T: Sync>() { +/// assert_sync::<Responder<Rc<String>, u32>>(); +/// } +/// ``` +const _ASSERT_COMPILE_FAILS: () = {}; + #[cfg(all(not(loom), test))] mod tests { use super::*; @@ -2159,6 +2288,26 @@ let response = rq.take_response().unwrap(); assert_eq!(response, Response::Here(3, 2, 1)); } + + #[allow(unconditional_recursion, clippy::extra_unused_type_parameters, unused)] + fn assert_send<T: Send>() { + assert_send::<Channel<String, u32>>(); + assert_send::<Responder<'static, String, u32>>(); + assert_send::<Requester<'static, String, u32>>(); + assert_send::<Channel<&'static mut String, u32>>(); + assert_send::<Responder<'static, &'static mut String, u32>>(); + assert_send::<Requester<'static, &'static mut String, u32>>(); + } + #[allow(unconditional_recursion, clippy::extra_unused_type_parameters, unused)] + fn assert_sync<T: Sync>() { + assert_sync::<Channel<String, u32>>(); + assert_sync::<Channel<String, u32>>(); + assert_sync::<Responder<'static, String, u32>>(); + assert_sync::<Requester<'static, String, u32>>(); + + assert_sync::<Channel<&'static mut String, u32>>(); + assert_sync::<Responder<'static, &'static mut String, u32>>(); + assert_sync::<Requester<'static, &'static mut String, u32>>(); + } } -
fn:
) to \
- restrict the search to a given item kind.","Accepted kinds are: fn
, mod
, struct
, \
- enum
, trait
, type
, macro
, \
- and const
.","Search functions by type signature (e.g., vec -> usize
or \
- -> vec
)","Search multiple things at once by splitting your query with comma (e.g., \
- str,u8
or String,struct:Vec,test
)","You can look for items with an exact name by putting double quotes around \
- your request: \"string\"
","Look for items inside another one by searching for a path: vec::Vec
",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="fn:
) to \
+ restrict the search to a given item kind.","Accepted kinds are: fn
, mod
, struct
, \
+ enum
, trait
, type
, macro
, \
+ and const
.","Search functions by type signature (e.g., vec -> usize
or \
+ -> vec
or String, enum:Cow -> bool
)","You can look for items with an exact name by putting double quotes around \
+ your request: \"string\"
","Look for items inside another one by searching for a path: vec::Vec
",].map(x=>""+x+"
").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="${value}
`}else{error[index]=value}});output+=`