Index: Cargo.toml ================================================================== --- Cargo.toml +++ Cargo.toml @@ -1,8 +1,8 @@ [package] name = "ump" -version = "0.10.1" +version = "0.10.2" authors = ["Jan Danielsson "] edition = "2018" license = "0BSD" categories = [ "concurrency", "asynchronous" ] keywords = [ "channel", "threads", "sync", "message-passing" ] @@ -19,10 +19,13 @@ "rustfmt.toml", "tests", "www" ] +[features] +dev-docs = [] + [dependencies] parking_lot = { version = "0.12.1" } sigq = { version = "0.13.3" } [dev-dependencies] Index: benches/add_server.rs ================================================================== --- benches/add_server.rs +++ benches/add_server.rs @@ -9,11 +9,11 @@ Add(i32, i32), AddThreaded(i32, i32) } pub fn criterion_benchmark(c: &mut Criterion) { - let mut group = c.benchmark_group("send operation"); + let mut group = c.benchmark_group("req operation"); let (server, client) = channel::(); let server_thread = thread::spawn(move || { let mut croak = false; @@ -39,11 +39,11 @@ group.bench_function("add", |b| { b.iter(|| { p += 2; q -= 3; - let result = client.send(Ops::Add(p, q)).unwrap(); + let result = client.req(Ops::Add(p, q)).unwrap(); assert_eq!(result, q + p); }) }); p = 0; @@ -50,11 +50,11 @@ q = 0; group.bench_function("add (threaded)", |b| { b.iter(|| { p += 2; q -= 3; - let result = client.send(Ops::AddThreaded(p, q)).unwrap(); + let result = client.req(Ops::AddThreaded(p, q)).unwrap(); assert_eq!(result, q + p); }) }); @@ -62,11 +62,11 @@ group.bench_function("add (async)", |b| { b.to_async(&rt).iter(|| async { let p = 1; let q = 2; - let result = client.asend(Ops::Add(p, q)).await.unwrap(); + let result = client.areq(Ops::Add(p, q)).await.unwrap(); assert_eq!(result, q + p); }) }); @@ -74,17 +74,17 @@ group.bench_function("add (async, threaded)", |b| { b.to_async(&rt).iter(|| async { let p = 1; let q = 2; - let result = client.asend(Ops::AddThreaded(p, q)).await.unwrap(); + let result = client.areq(Ops::AddThreaded(p, q)).await.unwrap(); assert_eq!(result, q + p); }) }); - let result = client.send(Ops::Die).unwrap(); + let result = client.req(Ops::Die).unwrap(); assert_eq!(result, 0); server_thread.join().unwrap(); } Index: examples/cloneclientserver.rs ================================================================== --- examples/cloneclientserver.rs +++ examples/cloneclientserver.rs @@ -37,23 +37,22 @@ } } }); if let Reply::ClientClone(cloned_client) = - client.send(Request::CloneClient).unwrap() + client.req(Request::CloneClient).unwrap() { - if let Reply::Sum(x) = cloned_client.send(Request::Add(5, 7)).unwrap() { + if let Reply::Sum(x) = cloned_client.req(Request::Add(5, 7)).unwrap() { assert_eq!(x, 12); } else { panic!("Unexpected result"); } } else { panic!("Unexpected result"); } - let _ = client.send(Request::Croak); + let _ = client.req(Request::Croak); server_thread.join().unwrap(); } - // vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 : Index: examples/many_once.rs ================================================================== --- examples/many_once.rs +++ examples/many_once.rs @@ -53,11 +53,11 @@ let client_clone = client.clone(); let client_thread = thread::spawn(move || { let name = format!("Client {}", i + 1); let msg = String::from(&name); println!("{} sending '{}'", name, msg); - let reply = client_clone.send(msg).unwrap(); + let reply = client_clone.req(msg).unwrap(); println!("{} received reply '{}' -- done", name, reply); }); join_handles.push(client_thread); } Index: examples/simple.rs ================================================================== --- examples/simple.rs +++ examples/simple.rs @@ -22,11 +22,11 @@ println!("Server done"); }); let msg = String::from("Client"); println!("Client sending '{}'", msg); - let reply = client.send(msg).unwrap(); + let reply = client.req(msg).unwrap(); println!("Client received reply '{}'", reply); println!("Client done"); server_thread.join().unwrap(); } Index: examples/threaded_handler.rs ================================================================== --- examples/threaded_handler.rs +++ examples/threaded_handler.rs @@ -50,11 +50,11 @@ let client_clone = client.clone(); let client_thread = thread::spawn(move || { let name = format!("Client {}", i + 1); let msg = String::from(&name); println!("{} sending '{}'", name, msg); - let reply = client_clone.send(msg).unwrap(); + let reply = client_clone.req(msg).unwrap(); println!("{} received reply '{}' -- done", name, reply); }); join_handles.push(client_thread); } Index: src/client.rs ================================================================== --- src/client.rs +++ src/client.rs @@ -43,11 +43,11 @@ /// dropped `Err(Error::NoReply)` will be returned. /// /// If an application specific error occurs it will be returned as a /// `Err(Error::App(E))`, where `E` is the error type used when creating the /// [`channel`](crate::channel). - pub fn send(&self, out: S) -> Result> { + pub fn req(&self, out: S) -> Result> { // Create a per-call reply context. // This context could be created when the Client object is being created // and stored in the context, and thus be reused for reach client call. // One side-effect is that some of the state semantics becomes more // complicated. @@ -66,12 +66,17 @@ let reply = rctx.get()?; Ok(reply) } - /// Same as [`Client::send()`] but for use in `async` contexts. - pub async fn asend(&self, out: S) -> Result> { + #[deprecated(since = "0.10.2", note = "Use req() instead.")] + pub fn send(&self, out: S) -> Result> { + self.req(out) + } + + /// Same as [`Client::req()`] but for use in `async` contexts. + pub async fn areq(&self, out: S) -> Result> { let rctx = InnerReplyContext::new(); self .qpusher .push(ServerQueueNode { @@ -82,10 +87,15 @@ let result = rctx.aget().await?; Ok(result) } + + #[deprecated(since = "0.10.2", note = "Use areq() instead.")] + pub async fn asend(&self, out: S) -> Result> { + self.areq(out).await + } } impl Clone for Client { /// Clone a client. Index: src/err.rs ================================================================== --- src/err.rs +++ src/err.rs @@ -1,25 +1,31 @@ use std::fmt; /// Module-specific error codes. #[derive(Debug)] pub enum Error { - /// The server object has shut down. This happens when clients: - /// - attempt to send messages to a server that has been deallocated. + /// The server object has shut down. + /// + /// This happens when clients: + /// - attempt to transmit messages to a server that has been deallocated. /// - have their requests dropped from the serrver's queue because the /// server itself was deallocated. ServerDisappeared, + /// No more client end-points remain. + /// /// There are no more nodes to pick up in the queue and all client - /// end-points have been dropped. + /// end-points have been dropped (implied: no new nodes will ever be added + /// to the queue). ClientsDisappeared, /// The message was delivered to the server, but the reply context was - /// released before sending back a reply. + /// dropped before transmitting a reply. NoReply, /// Application-specific error. + /// /// The `E` type is typically declared as the third generic parameter to /// [`channel`](crate::channel()). App(E) } Index: src/lib.rs ================================================================== --- src/lib.rs +++ src/lib.rs @@ -13,11 +13,11 @@ //! //! The server calls [`Server::wait()`]/[`Server::async_wait()`], which //! blocks and waits for an incoming message from a client. //! //! A client, in a separate thread or task, calls -//! [`Client::send()`]/[`Client::asend()`] to send a message to the server. +//! [`Client::req()`]/[`Client::areq()`] to send a message to the server. //! //! The server's wait call returns two objects: The message sent by the //! client, and a [`ReplyContext`]. //! //! After processing its application-defined message, the server *must* call @@ -54,17 +54,17 @@ //! println!("Server done"); //! }); //! //! let msg = String::from("Client"); //! println!("Client sending '{}'", msg); -//! let reply = client.send(String::from(msg)).unwrap(); +//! let reply = client.req(msg).unwrap(); //! println!("Client received reply '{}'", reply); //! println!("Client done"); //! //! server_thread.join().unwrap(); //! ``` -//! In practice the send/reply types will probably be `enum`s used to +//! In practice the req/reply types will probably be `enum`s used to //! indicate command/return type with associated data. The third type argument //! to [`channel`] is an error type that can be used to explicitly pass errors //! back to the sender. //! //! # Semantics @@ -115,20 +115,20 @@ /// clients. Once a message arrives it must reply to it using a /// [`ReplyContext`] that's returned to it in the same call that returned the /// message. /// /// The [`Client`] object can be used to send messages to the [`Server`]. The -/// [`Client::send()`] call will not return until the server has replied. +/// [`Client::req()`] call will not return until the server has replied. /// /// Clients can be [cloned](Client::clone()); each clone will create a /// new client object that is connected to the same server object, but is /// completely independent of the original client. /// -/// The `S` type parameter is the "send" data type that clients will transfer -/// to the server. The `R` type parameter is the "receive" data type that -/// clients will receive from the server. The `E` type parameter can be used -/// to return application specific errors from the server to the client. +/// The `S` type parameter is the "request" data type that clients will +/// transfer to the server. The `R` type parameter is the "receive" data type +/// that clients will receive from the server. The `E` type parameter can be +/// used to return application specific errors from the server to the client. pub fn channel() -> (Server, Client) { let (qpusher, qpuller) = sigq::new(); let server = Server { qpuller }; Index: src/rctx/public.rs ================================================================== --- src/rctx/public.rs +++ src/rctx/public.rs @@ -1,12 +1,19 @@ use crate::rctx::{err::Error, inner::State, InnerReplyContext}; -/// Public-facing sender part of the `ReplyContext` object. -/// -/// This is safe to pass to applications which are meant to only be able to put -/// a value through the `ReplyContext` channel, but not extract the value from -/// it. +/// Context used to transmit a reply back to the originating requester. +#[cfg_attr( + feature = "dev-docs", + doc = r#" +# Internals +Public-facing sender part of the `ReplyContext` object. + +This, as opposed to `InnerReplyContext`, is safe to pass to applications that +are meant to only be able to put a value through the `ReplyContext` channel, +but not extract the value from it. +"# +)] pub struct ReplyContext { inner: InnerReplyContext, did_handover: bool } @@ -23,11 +30,11 @@ /// let (data, rctx) = server.wait().unwrap(); /// let reply = format!("Hello, {}!", data); /// rctx.reply(reply).unwrap(); /// }); /// let msg = String::from("Client"); - /// let reply = client.send(String::from(msg)).unwrap(); + /// let reply = client.req(msg).unwrap(); /// assert_eq!(reply, "Hello, Client!"); /// server_thread.join().unwrap(); /// ``` /// /// # Semantics @@ -59,11 +66,11 @@ /// let server_thread = thread::spawn(move || { /// let (_, rctx) = server.wait().unwrap(); /// rctx.fail(MyError::SomeError("failed".to_string())).unwrap(); /// }); /// let msg = String::from("Client"); - /// let reply = client.send(String::from(msg)); + /// let reply = client.req(msg); /// match reply { /// Err(Error::App(MyError::SomeError(s))) => { /// assert_eq!(s, "failed"); /// } /// _ => { Index: tests/async_client.rs ================================================================== --- tests/async_client.rs +++ tests/async_client.rs @@ -36,18 +36,18 @@ let mut b: i32 = 0; for _ in 0..niterations { a += 2; b -= 3; - let result = client.asend(Request::Add(a, b)).await.unwrap(); + let result = client.areq(Request::Add(a, b)).await.unwrap(); if let Reply::Sum(sum) = result { assert_eq!(sum, a + b); } else { panic!("Didn't get sum"); } } - let result = client.asend(Request::Croak).await.unwrap(); + let result = client.areq(Request::Croak).await.unwrap(); if let Reply::OkICroaked = result { } else { panic!("Didn't get a croak"); } }); Index: tests/fail.rs ================================================================== --- tests/fail.rs +++ tests/fail.rs @@ -18,11 +18,11 @@ rctx.fail(MyError::SomeError("failed".to_string())).unwrap(); }); let msg = String::from("Client"); - let reply = client.send(msg); + let reply = client.req(msg); match reply { Err(Error::App(MyError::SomeError(s))) => { assert_eq!(s, "failed"); } _ => { @@ -47,11 +47,11 @@ rctx.fail(MyError::SomeError("failed".to_string())).unwrap(); }); tokrt.block_on(async { let msg = String::from("Client"); - let reply = client.asend(msg).await; + let reply = client.areq(msg).await; match reply { Err(Error::App(MyError::SomeError(s))) => { assert_eq!(s, "failed"); } _ => { Index: tests/noreply.rs ================================================================== --- tests/noreply.rs +++ tests/noreply.rs @@ -14,11 +14,11 @@ // Don't do this. drop(rctx); }); let msg = String::from("Client"); - let reply = client.send(msg); + let reply = client.req(msg); match reply { Err(Error::NoReply) => { // This is the expected error } _ => { @@ -44,11 +44,11 @@ drop(rctx); }); tokrt.block_on(async { let msg = String::from("Client"); - let reply = client.asend(msg).await; + let reply = client.areq(msg).await; match reply { Err(Error::NoReply) => { // This is the expected error } _ => { Index: tests/queue_cleanup.rs ================================================================== --- tests/queue_cleanup.rs +++ tests/queue_cleanup.rs @@ -14,11 +14,11 @@ thread::sleep(one_second); drop(server); }); let msg = String::from("Client"); - let reply = client.send(msg); + let reply = client.req(msg); match reply { Err(Error::ServerDisappeared) => { // This is the expected error } _ => { @@ -43,12 +43,12 @@ drop(server); }); tokrt.block_on(async { let msg = String::from("Client"); - let reply = client.asend(msg).await; - //let reply = client.send(msg); + let reply = client.areq(msg).await; + //let reply = client.req(msg); match reply { Err(Error::ServerDisappeared) => { // This is the expected error } _ => { Index: tests/stress.rs ================================================================== --- tests/stress.rs +++ tests/stress.rs @@ -36,14 +36,14 @@ let mut b: i32 = 0; for _ in 0..65535 { a += 2; b -= 3; - let result = client.send(Ops::Add(a, b)).unwrap(); + let result = client.req(Ops::Add(a, b)).unwrap(); assert_eq!(result, a + b); } - let result = client.send(Ops::Die).unwrap(); + let result = client.req(Ops::Die).unwrap(); assert_eq!(result, 0); server_thread.join().unwrap(); } @@ -82,15 +82,15 @@ let mut b: i32 = 0; for _ in 0..niterations { a += 2; b -= 3; - let result = client.send(Ops::Sub(a, b)).unwrap(); + let result = client.req(Ops::Sub(a, b)).unwrap(); assert_eq!(result, a - b); } - let result = client.send(Ops::Die).unwrap(); + let result = client.req(Ops::Die).unwrap(); assert_eq!(result, 0); server_thread.join().unwrap(); } // vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 : Index: www/changelog.md ================================================================== --- www/changelog.md +++ www/changelog.md @@ -6,10 +6,24 @@ ### Changed ### Removed + +## [0.10.2] - 2023-07-28 + +### Added + +- Add `send()`/`asend()` wrappers around the new `req()`/`areq()` methods with + a deprecation notice. +- Add a `dev-docs` feature to allow internal documentation notes to be + included in generated documentation. + +### Changed + +- Rename `send()`/`asend()` to `req()/`areq()`. + ## [0.10.1] - 2023-07-27 ### Changed