1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
use std::sync::Arc; use sigq::Queue as NotifyQueue; use crate::rctx::{InnerReplyContext, ReplyContext}; pub(crate) struct ServerQueueNode<S, R> { /// Raw message being sent from the client to the server. pub(crate) msg: S, /// Keep track of data needed to share reply data. pub(crate) reply: InnerReplyContext<R> } /// Representation of a server object. /// /// Each instantiation of a `Client` object is itself an isolated client with /// regards to the server context. By cloning a client a new independent /// client is created. (Independent here meaning that it is still tied to the /// same server object, but it the new client can be passed to a separate /// thread and can independently make calls to the server). pub struct Server<S, R> { pub(crate) srvq: Arc<NotifyQueue<ServerQueueNode<S, R>>> } impl<S, R> Server<S, R> where S: 'static + Send, R: 'static + Send { /// Block and wait for an incoming message from a /// [`Client`](struct.Client.html). /// /// Returns the message sent by the client and a reply context. The server /// must call `reply()` on the reply context to pass a return value to the /// client. pub fn wait(&self) -> (S, ReplyContext<R>) { let node = self.srvq.pop(); // Extract the data from the node let msg = node.msg; // Create an application reply context from the reply context in the queue // Implicitly changes state of the reply context from Queued to Waiting let rctx = ReplyContext::from(node.reply); (msg, rctx) } /// Same as [`wait()`](#method.wait), but for use in an `async` context. pub async fn async_wait(&self) -> (S, ReplyContext<R>) { let node = self.srvq.apop().await; // Extract the data from the node let msg = node.msg; // Create an application reply context from the reply context in the queue // Implicitly changes state of the reply context from Queued to Waiting let rctx = ReplyContext::from(node.reply); (msg, rctx) } /// Returns a boolean indicating whether the queue is/was empty. This isn't /// really useful unless used in very specific situations. It mostly exists /// for test cases. pub fn was_empty(&self) -> bool { self.srvq.was_empty() } } // vim: set ft=rust et sw=2 ts=2 sts=2 cinoptions=2 tw=79 :