concurrency_traits/
lib.rs1#![cfg_attr(not(any(feature = "std", test)), no_std)]
4#![warn(missing_docs, missing_debug_implementations, unused_import_braces)]
5#![cfg_attr(feature = "nightly", feature(option_result_unwrap_unchecked))]
6
7#[cfg(feature = "alloc")]
8extern crate alloc;
9
10pub mod mutex;
11pub mod queue;
12pub mod rw_lock;
13pub mod semaphore;
14pub mod stack;
15
16use core::convert::Infallible;
17use core::fmt::Debug;
18use core::ops::{Add, AddAssign, Sub, SubAssign};
19use core::time::Duration;
20
21trait EnsureSend: Send {}
22trait EnsureSync: Sync {}
23
24pub trait TimeFunctions {
26 type InstantType: Add<Duration, Output = Self::InstantType>
28 + AddAssign<Duration>
29 + Sub<Duration, Output = Self::InstantType>
30 + SubAssign<Duration>
31 + Sub<Self::InstantType, Output = Duration>
32 + Ord
33 + Copy;
34
35 fn current_time() -> Self::InstantType;
37}
38pub trait ThreadFunctions {
40 fn sleep(duration: Duration);
42 fn yield_now();
44}
45pub trait TryThreadSpawner<O>
47where
48 O: Send + 'static,
49{
50 type ThreadHandle: ThreadHandle;
52 type SpawnError;
54
55 fn try_spawn(
57 func: impl FnOnce() -> O + 'static + Send,
58 ) -> Result<Self::ThreadHandle, Self::SpawnError>;
59}
60pub trait ThreadSpawner<O>: TryThreadSpawner<O, SpawnError = Infallible>
62where
63 O: Send + 'static,
64{
65 fn spawn(func: impl FnOnce() -> O + 'static + Send) -> Self::ThreadHandle {
67 #[cfg(not(feature = "nightly"))]
68 {
69 Self::try_spawn(func).unwrap()
70 }
71 #[cfg(feature = "nightly")]
72 unsafe {
73 Self::try_spawn(func).unwrap_unchecked()
74 }
75 }
76}
77impl<T, O> ThreadSpawner<O> for T
78where
79 T: TryThreadSpawner<O, SpawnError = Infallible>,
80 O: Send + 'static,
81{
82}
83pub trait TryResultThreadSpawner<O>: TryThreadSpawner<O>
85where
86 Self::ThreadHandle: TryJoinableHandle<Output = O>,
87 O: Send + 'static,
88{
89}
90impl<T, O> TryResultThreadSpawner<O> for T
91where
92 T: TryThreadSpawner<O>,
93 T::ThreadHandle: TryJoinableHandle<Output = O>,
94 O: Send + 'static,
95{
96}
97pub trait ResultThreadSpawner<O>: ThreadSpawner<O>
99where
100 Self::ThreadHandle: TryJoinableHandle<Output = O>,
101 O: Send + 'static,
102{
103}
104impl<T, O> ResultThreadSpawner<O> for T
105where
106 T: ThreadSpawner<O>,
107 T::ThreadHandle: TryJoinableHandle<Output = O>,
108 O: Send + 'static,
109{
110}
111pub trait ThreadParker {
113 type ThreadId: Debug;
115
116 fn park();
118 fn unpark(thread: Self::ThreadId);
120 fn current_thread() -> Self::ThreadId;
122}
123pub trait ThreadTimeoutParker: ThreadParker {
125 fn park_timeout(timeout: Duration);
127}
128pub trait ThreadHandle {
130 type ThreadId;
132
133 fn thread_id(&self) -> &Self::ThreadId;
135}
136pub trait TryJoinableHandle: Sized + ThreadHandle {
138 type Output;
140 type ThreadError;
142
143 fn try_join(self) -> Result<Self::Output, Self::ThreadError>;
145}
146pub trait JoinableHandle: Sized + TryJoinableHandle<ThreadError = Infallible> {
148 #[inline]
150 fn join(self) -> Self::Output {
151 #[cfg(not(feature = "nightly"))]
152 {
153 self.try_join().unwrap()
154 }
155 #[cfg(feature = "nightly")]
156 unsafe {
157 self.try_join().unwrap_unchecked()
158 }
159 }
160}
161impl<T> JoinableHandle for T where T: TryJoinableHandle<ThreadError = Infallible> {}
162
163pub trait ConcurrentSystem<O>: 'static
165where
166 Self: TimeFunctions
167 + ThreadFunctions
168 + TryThreadSpawner<O>
169 + ThreadParker<
170 ThreadId = <<Self as TryThreadSpawner<O>>::ThreadHandle as ThreadHandle>::ThreadId,
171 >,
172 O: Send + 'static,
173{
174}
175
176#[cfg(feature = "std")]
178#[derive(Copy, Clone, Debug)]
179pub struct StdThreadFunctions;
180#[cfg(feature = "std")]
181mod std_thread_impls {
182 use super::*;
183 impl TimeFunctions for StdThreadFunctions {
184 type InstantType = std::time::Instant;
185
186 #[inline]
187 fn current_time() -> Self::InstantType {
188 std::time::Instant::now()
189 }
190 }
191 impl ThreadFunctions for StdThreadFunctions {
192 #[inline]
193 fn sleep(duration: Duration) {
194 std::thread::sleep(duration)
195 }
196
197 fn yield_now() {
198 std::thread::yield_now()
199 }
200 }
201 impl<O> TryThreadSpawner<O> for StdThreadFunctions
202 where
203 O: Send + 'static,
204 {
205 type ThreadHandle = std::thread::JoinHandle<O>;
206 type SpawnError = Infallible;
207
208 fn try_spawn(
209 func: impl FnOnce() -> O + 'static + Send,
210 ) -> Result<Self::ThreadHandle, Self::SpawnError> {
211 Ok(std::thread::spawn(func))
212 }
213 }
214 impl ThreadParker for StdThreadFunctions {
215 type ThreadId = std::thread::Thread;
216
217 #[inline]
218 fn park() {
219 std::thread::park()
220 }
221
222 #[inline]
223 fn unpark(thread: Self::ThreadId) {
224 thread.unpark()
225 }
226
227 #[inline]
228 fn current_thread() -> Self::ThreadId {
229 std::thread::current()
230 }
231 }
232 impl ThreadTimeoutParker for StdThreadFunctions {
233 fn park_timeout(timeout: Duration) {
234 std::thread::park_timeout(timeout)
235 }
236 }
237 impl<O> ThreadHandle for std::thread::JoinHandle<O> {
238 type ThreadId = std::thread::Thread;
239
240 #[inline]
241 fn thread_id(&self) -> &Self::ThreadId {
242 self.thread()
243 }
244 }
245 impl<O> TryJoinableHandle for std::thread::JoinHandle<O> {
246 type Output = O;
247 type ThreadError = Box<dyn std::any::Any + Send + 'static>;
248
249 #[inline]
250 fn try_join(self) -> Result<Self::Output, Self::ThreadError> {
251 self.join()
252 }
253 }
254 impl<O> ConcurrentSystem<O> for StdThreadFunctions where O: Send + 'static {}
255}
256
257