1 | use std::fmt::{self, Debug}; |
2 | use std::thread::{self, ThreadId}; |
3 | |
4 | /// ThreadBound is a Sync-maker and Send-maker that allows accessing a value |
5 | /// of type T only from the original thread on which the ThreadBound was |
6 | /// constructed. |
7 | pub struct ThreadBound<T> { |
8 | value: T, |
9 | thread_id: ThreadId, |
10 | } |
11 | |
12 | unsafe impl<T> Sync for ThreadBound<T> {} |
13 | |
14 | // Send bound requires Copy, as otherwise Drop could run in the wrong place. |
15 | unsafe impl<T: Copy> Send for ThreadBound<T> {} |
16 | |
17 | impl<T> ThreadBound<T> { |
18 | pub fn new(value: T) -> Self { |
19 | ThreadBound { |
20 | value, |
21 | thread_id: thread::current().id(), |
22 | } |
23 | } |
24 | |
25 | pub fn get(&self) -> Option<&T> { |
26 | if thread::current().id() == self.thread_id { |
27 | Some(&self.value) |
28 | } else { |
29 | None |
30 | } |
31 | } |
32 | } |
33 | |
34 | impl<T: Debug> Debug for ThreadBound<T> { |
35 | fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { |
36 | match self.get() { |
37 | Some(value: &T) => Debug::fmt(self:value, f:formatter), |
38 | None => formatter.write_str(data:"unknown" ), |
39 | } |
40 | } |
41 | } |
42 | |