Send a message to a Rendezvous. Blocking or non-blocking If a `Box ` is provided then it is suspended until the message is received i.e. blocking. Causes state transition: 1. Empty -> Sending, return (None, None) 3. Sending -> Sending, return (sending thread, None) Error returned to thread 2. Receiving -> Empty, return (receiving thread, sending thread) 3. SendReceiving -> SendReceiving,
(&mut self, thread: Option<Box<Thread>>, message: Message)
| 36 | /// 3. SendReceiving -> SendReceiving, return (sending thread, None) |
| 37 | /// Error returned to thread |
| 38 | pub fn send(&mut self, thread: Option<Box<Thread>>, message: Message) |
| 39 | -> (Option<Box<Thread>>, Option<Box<Thread>>) { |
| 40 | match &*self { |
| 41 | Rendezvous::Empty => { |
| 42 | *self = Rendezvous::Sending(thread, message); |
| 43 | (None, None) |
| 44 | } |
| 45 | Rendezvous::Sending(_, _) => { |
| 46 | // Signal error to thread: Can't have two sending threads |
| 47 | if let Some(t) = &thread { |
| 48 | // Return message, so that any handles are not lost |
| 49 | t.return_error_message(syscalls::SYSCALL_ERROR_SEND_BLOCKING, message); |
| 50 | } |
| 51 | (thread, None) |
| 52 | } |
| 53 | Rendezvous::Receiving(_, some_tid) => { |
| 54 | if let Some(tid) = some_tid { |
| 55 | // Restricted to a single thread |
| 56 | if let Some(t) = &thread { |
| 57 | if t.tid() != *tid { |
| 58 | // Wrong thread ID |
| 59 | t.return_error_message(syscalls::SYSCALL_ERROR_RECV_BLOCKING, message); |
| 60 | return (thread, None); |
| 61 | } |
| 62 | // else keep going |
| 63 | } else { |
| 64 | // No sender thread => error |
| 65 | return (thread, None); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | // Complete the message transfer |
| 70 | // core::mem::replace https://doc.rust-lang.org/beta/core/mem/fn.replace.html |
| 71 | if let Rendezvous::Receiving(rec_thread, _) = mem::replace(self, Rendezvous::Empty) { |
| 72 | rec_thread.return_message(message); |
| 73 | if let Some(ref t) = thread { |
| 74 | t.return_error(0); // Success |
| 75 | } |
| 76 | return (Some(rec_thread), thread); |
| 77 | } |
| 78 | (None, None) // This should never be reached |
| 79 | } |
| 80 | Rendezvous::SendReceiving(_, _) => { |
| 81 | // Signal error to thread: Can't have two sending threads |
| 82 | if let Some(t) = &thread { |
| 83 | t.return_error_message(syscalls::SYSCALL_ERROR_SEND_BLOCKING, message); |
| 84 | } |
| 85 | (thread, None) |
| 86 | } |
| 87 | } |
| 88 | } |
| 89 | |
| 90 | /// Blocking receive a message |
| 91 | /// |
no test coverage detected