maybe_sync/lib.rs
1//! This crates helps creating flexible libraries that may work in either
2//! multithreaded and singlethreaded environments.
3//!
4//! [](https://crates.io/crates/maybe-sync)
5//! [](https://docs.rs/maybe-sync)
6//! [](LICENSE-MIT)
7//! [](LICENSE-APACHE)
8//!
9//! # Why it exists?
10//!
11//! Creating library that works in either desktop/server or web-browser environment
12//! could be tough.
13//!
14//! In desktop/server environments crates tend to be usable with multiple threads
15//! and add [`Send`] and [`Sync`] trait bounds where needed.
16//! In the same time [`web-sys`] - a de facto standard crate to use browser API -
17//! provides programmer with `!Send + !Sync` types that cannot be used when [`Send`]
18//! or [`Sync`] bounds are placed on the API calls.
19//!
20//! For example asset loading crate [`goods`] uses generic executors to drive
21//! loading process.
22//! Some executors work with sendable futures only: [`tokio`],
23//! some requre sendable future to run them on multiple threads:
24//! [`async-std`], [`actix-rt`],
25//! Others work with any futures in single thread: [`wasm_bindgen_futures::spawn_local`]
26//!
27//! In [`goods`] one of the basic data sources for web - [`FetchSource`] - uses
28//! browser's Fetch API to retreive data from web and produces non-sendable future.
29//!
30//! That's why [`goods::Spawn::spawn`] takes [`maybe_sync::BoxFuture`] that is
31//! a sendable boxed future when "sync" feature is enabled,
32//! allowing using multithreaded future executors.
33//! And without "sync" feature [`maybe_sync::BoxFuture`] is
34//! a non-sendable boxed future and only then [`FetchSource`] exists.
35//!
36//! Similar story with ECS crates.
37//! Most of them require that components are [`Send`] + [`Sync`]
38//! so systems can access them from any thread.
39//! This makes it impossible to have types from [`web-sys`] in components.
40//!
41//! Some small application may desire to turn off "sync" feature in their
42//! dependencies as they are singlethreaded and would rather not pay for what
43//! they don't use.
44//!
45//! # [`MaybeSend`] and [`MaybeSync`]
46//!
47//! Marker traits [`MaybeSend`] and [`MaybeSync`] can be used in place of
48//! [`Send`] and [`Sync`] traits in where clauses and bounds.
49//!
50//! When "sync" feature is enabled then [`MaybeSend`] is actually reexported [`Send`]
51//! and [`MaybeSync`] is reexported [`Sync`] trait.
52//! Thus allowing types with those bounds to be sent or shared across threads.
53//!
54//! When "sync" feature is not enabled then [`MaybeSend`] and [`MaybeSync`] are empty
55//! traits implemented for all types and when used as bounds permit types that
56//! does not satisfy [`Send`] or [`Sync`] bounds.
57//!
58//! This makes it impossible to forget enable "sync" feature and accidentally send
59//! `!Send` value to another thread.
60//! Function that uncodintionally send value to another thread
61//! should not use [`MaybeSend`] bound, but an actual [`Send`].
62//!
63//! # BoxFuture
64//!
65//! Type alias for boxed future. Sendable if "sync" feature is enabled.
66//! It is designed to be used as return type from trait functions
67//! where trait implementations that produce non-sendable futures
68//! exist only when "sync" feature is not enabled.
69//! It can be used as function argument type when [`MaybeSend`] bound is placed.
70//!
71//! # Rc
72//!
73//! Type alias to [`alloc::rc::Rc`] when "sync" feature is not enabled, or
74//! [`alloc::sync::Arc`] when "sync" feature is enabled. Serves for optimization
75//! purposes for crates that already use [`maybe-sync`] crate.
76//!
77//! # Mutex
78//!
79//! Type alias to [`parking_lot::Mutex`] when "sync" feature is enabled, or
80//! thin wrapper arond [`core::cell::RefCell`] otherwise. Serves for optimization
81//! purposes for crates that already use [`maybe-sync`] crate.
82//!
83//! [`Send`]: https://doc.rust-lang.org/std/marker/trait.Send.html
84//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
85//! [`web-sys`]: https://docs.rs/web-sys
86//! [`goods`]: https://docs.rs/goods
87//! [`tokio`]: https://docs.rs/tokio
88//! [`async-std`]: https://docs.rs/async-std
89//! [`actix-rt`]: https://docs.rs/actix-rt
90//! [`FetchSource`]: https://docs.rs/goods/0.5/wasm32-unknown-unknown/goods/struct.FetchSource.html
91//! [`wasm_bindgen_futures::spawn_local`]: https://docs.rs/wasm-bindgen-futures/0.4/wasm_bindgen_futures/fn.spawn_local.html
92//! [`goods::Spawn::spawn`]: https://docs.rs/goods/0.5/goods/trait.Spawn.html#tymethod.spawn
93//! [`maybe_sync::BoxFuture`]: ./type.BoxFuture.html
94//! [`MaybeSend`]: ./trait.MaybeSend.html
95//! [`MaybeSync`]: ./trait.MaybeSync.html
96//! [`alloc::rc::Rc`]: https://doc.rust-lang.org/alloc/rc/struct.Rc.html
97//! [`alloc::sync::Arc`]: https://doc.rust-lang.org/alloc/sync/struct.Arc.html
98//! [`maybe-sync`]: ./index.html
99//! [`parking_lot::Mutex`]: https://docs.rs/parking_lot/0.10/parking_lot/type.Mutex.html
100//! [`core::cell::RefCell`]: https://doc.rust-lang.org/core/cell/struct.RefCell.html
101
102#![no_std]
103#![cfg_attr(all(doc, feature = "unstable-doc"), feature(doc_cfg))]
104
105#[cfg(feature = "alloc")]
106extern crate alloc;
107
108#[cfg(feature = "sync")]
109mod sync {
110 #[cfg(feature = "alloc")]
111 use core::{future::Future, pin::Pin};
112
113 /// Reexports of the actual marker traits from core.
114 pub use core::marker::{Send as MaybeSend, Sync as MaybeSync};
115
116 /// An owned dynamically typed [`Future`] for use at return position in cases
117 /// when type is opaque and existential type cannot be used,
118 /// or when multiple types can be returned.
119 ///
120 /// A type alias equal to `futures::future::BoxFuture`
121 /// when "sync" feature is enabled.\
122 /// A type alias equal to `futures::future::LocalBoxFuture`
123 /// when "sync" feature is not enabled.
124 #[cfg(feature = "alloc")]
125 #[cfg_attr(all(doc, feature = "unstable-doc"), doc(cfg(feature = "alloc")))]
126 pub type BoxFuture<'a, T> = Pin<alloc::boxed::Box<dyn Future<Output = T> + Send + 'a>>;
127
128 /// A pointer type which can be safely shared between threads
129 /// when "sync" feature is enabled.\
130 /// A pointer type which can be shared, but only within single thread
131 /// where it was created when "sync" feature is not enabled.
132 ///
133 /// # Example
134 ///
135 /// ```
136 /// # use {maybe_sync::{MaybeSend, Rc}, std::fmt::Debug};
137 ///
138 /// fn maybe_sends<T: MaybeSend + Debug + 'static>(val: T) {
139 /// #[cfg(feature = "sync")]
140 /// {
141 /// // If this code is compiled then `MaybeSend` is alias to `std::marker::Send`.
142 /// std::thread::spawn(move || { println!("{:?}", val) });
143 /// }
144 /// }
145 ///
146 /// // Unlike `std::rc::Rc` this `maybe_sync::Rc` always satisfies `MaybeSend` bound.
147 /// maybe_sends(Rc::new(42));
148 /// ```
149 #[cfg(feature = "alloc")]
150 #[cfg_attr(all(doc, feature = "unstable-doc"), doc(cfg(feature = "alloc")))]
151 pub type Rc<T> = alloc::sync::Arc<T>;
152
153 /// Mutex implementation to use in conjunction with `MaybeSync` bound.
154 ///
155 /// A type alias to `parking_lot::Mutex` when "sync" feature is enabled.\
156 /// A wrapper type around `std::cell::RefCell` when "sync" feature is not enabled.
157 ///
158 /// # Example
159 ///
160 /// ```
161 /// # use {maybe_sync::{MaybeSend, Mutex}, std::{fmt::Debug, sync::Arc}};
162 ///
163 /// fn maybe_sends<T: MaybeSend + Debug + 'static>(val: Arc<Mutex<T>>) {
164 /// #[cfg(feature = "sync")]
165 /// {
166 /// // If this code is compiled then `MaybeSend` is alias to `std::marker::Send`,
167 /// // and `Mutex` is `parking_lot::Mutex`.
168 /// std::thread::spawn(move || { println!("{:?}", *val.lock()) });
169 /// }
170 /// }
171 ///
172 /// // `maybe_sync::Mutex<T>` would always satisfy `MaybeSync` and `MaybeSend`
173 /// // bounds when `T: MaybeSend`,
174 /// // even if feature "sync" is enabeld.
175 /// maybe_sends(Arc::new(Mutex::new(42)));
176 /// ```
177 pub type Mutex<T> = parking_lot::Mutex<T>;
178
179 /// A boolean type which can be safely shared between threads
180 /// when "sync" feature is enabled.\
181 /// A boolean type with non-threadsafe interior mutability
182 /// when "sync" feature is not enabled.
183 ///
184 /// This type has the same in-memory representation as a bool.
185 pub type AtomicBool = core::sync::atomic::AtomicBool;
186
187 /// A integer type which can be safely shared between threads
188 /// when "sync" feature is enabled.\
189 /// A integer type with non-threadsafe interior mutability
190 /// when "sync" feature is not enabled.
191 ///
192 /// This type has the same in-memory representation as a i8.
193 pub type AtomicI8 = core::sync::atomic::AtomicI8;
194
195 /// A integer type which can be safely shared between threads
196 /// when "sync" feature is enabled.\
197 /// A integer type with non-threadsafe interior mutability
198 /// when "sync" feature is not enabled.
199 ///
200 /// This type has the same in-memory representation as a i16.
201 pub type AtomicI16 = core::sync::atomic::AtomicI16;
202
203 /// A integer type which can be safely shared between threads
204 /// when "sync" feature is enabled.\
205 /// A integer type with non-threadsafe interior mutability
206 /// when "sync" feature is not enabled.
207 ///
208 /// This type has the same in-memory representation as a i32.
209 pub type AtomicI32 = core::sync::atomic::AtomicI32;
210
211 /// A integer type which can be safely shared between threads
212 /// when "sync" feature is enabled.\
213 /// A integer type with non-threadsafe interior mutability
214 /// when "sync" feature is not enabled.
215 ///
216 /// This type has the same in-memory representation as a isize.
217 pub type AtomicIsize = core::sync::atomic::AtomicIsize;
218
219 /// A integer type which can be safely shared between threads
220 /// when "sync" feature is enabled.\
221 /// A integer type with non-threadsafe interior mutability
222 /// when "sync" feature is not enabled.
223 ///
224 /// This type has the same in-memory representation as a i8.
225 pub type AtomicU8 = core::sync::atomic::AtomicU8;
226
227 /// A integer type which can be safely shared between threads
228 /// when "sync" feature is enabled.\
229 /// A integer type with non-threadsafe interior mutability
230 /// when "sync" feature is not enabled.
231 ///
232 /// This type has the same in-memory representation as a i16.
233 pub type AtomicU16 = core::sync::atomic::AtomicU16;
234
235 /// A integer type which can be safely shared between threads
236 /// when "sync" feature is enabled.\
237 /// A integer type with non-threadsafe interior mutability
238 /// when "sync" feature is not enabled.
239 ///
240 /// This type has the same in-memory representation as a i32.
241 pub type AtomicU32 = core::sync::atomic::AtomicU32;
242
243 /// A integer type which can be safely shared between threads
244 /// when "sync" feature is enabled.\
245 /// A integer type with non-threadsafe interior mutability
246 /// when "sync" feature is not enabled.
247 ///
248 /// This type has the same in-memory representation as a isize.
249 pub type AtomicUsize = core::sync::atomic::AtomicUsize;
250
251 /// A raw pointer type which can be safely shared between threads
252 /// when "sync" feature is enabled.\
253 /// A raw pointer type with non-threadsafe interior mutability
254 /// when "sync" feature is not enabled.
255 ///
256 /// This type has the same in-memory representation as a isize.
257 pub type AtomicPtr<T> = core::sync::atomic::AtomicPtr<T>;
258}
259
260#[cfg(not(feature = "sync"))]
261mod unsync {
262 use core::cell::{RefCell, RefMut};
263
264 #[cfg(feature = "alloc")]
265 use core::{future::Future, pin::Pin};
266
267 /// Marker trait that can represent nothing if feature "sync" is not enabled.
268 /// Or be reexport of `std::marker::Send` if "sync" feature is enabled.
269 ///
270 /// It is intended to be used as trait bound where `std::marker::Send` bound
271 /// is required only when application is compiled for multithreaded environment.\
272 /// If "sync" feature is not enabled then this trait bound will *NOT* allow
273 /// value to cross thread boundary or be used where sendable value is expected.
274 ///
275 /// # Examples
276 ///
277 /// ```
278 /// # use {maybe_sync::MaybeSend, std::{fmt::Debug, rc::Rc}};
279 ///
280 /// fn maybe_sends<T: MaybeSend + Debug + 'static>(val: T) {
281 /// #[cfg(feature = "sync")]
282 /// {
283 /// // If this code is compiled then `MaybeSend` is alias to `std::marker::Send`.
284 /// std::thread::spawn(move || { println!("{:?}", val) });
285 /// }
286 /// }
287 ///
288 /// #[cfg(not(feature = "sync"))]
289 /// {
290 /// // If this code is compiled then `MaybeSend` dummy markerd implemented for all types.
291 /// maybe_sends(Rc::new(42));
292 /// }
293 /// ```
294 pub trait MaybeSend {}
295
296 /// All values are maybe sendable.
297 impl<T> MaybeSend for T where T: ?Sized {}
298
299 /// Marker trait that can represent nothing if feature "sync" is not enabled.
300 /// Or be reexport of `std::marker::Sync` if "sync" feature is enabled.
301 ///
302 /// It is intended to be used as trait bound where `std::marker::Sync` bound
303 /// is required only when application is compiled for multithreaded environment.\
304 /// If "sync" feature is not enabled then this trait bound will *NOT* allow
305 /// reference to the value to cross thread boundary or be used where sync
306 /// value is expected.
307 ///
308 /// # Examples
309 ///
310 /// ```
311 /// # use {maybe_sync::MaybeSync, std::{sync::Arc, fmt::Debug, cell::Cell}};
312 ///
313 /// fn maybe_shares<T: MaybeSync + Debug + 'static>(val: Arc<T>) {
314 /// #[cfg(feature = "sync")]
315 /// {
316 /// // If this code is compiled then `MaybeSync` is alias to `std::marker::Sync`.
317 /// std::thread::spawn(move || { println!("{:?}", val) });
318 /// }
319 /// }
320 ///
321 /// #[cfg(not(feature = "sync"))]
322 /// {
323 /// // If this code is compiled then `MaybeSync` dummy markerd implemented for all types.
324 /// maybe_shares(Arc::new(Cell::new(42)));
325 /// }
326 /// ```
327 pub trait MaybeSync {}
328
329 /// All values are maybe sync.
330 impl<T> MaybeSync for T where T: ?Sized {}
331
332 /// An owned dynamically typed [`Future`] for use at return position in cases
333 /// when type is opaque and existential type cannot be used,
334 /// or when multiple types can be returned.
335 ///
336 /// A type alias equal to `futures::future::BoxFuture`
337 /// when "sync" feature is enabled.\
338 /// A type alias equal to `futures::future::LocalBoxFuture`
339 /// when "sync" feature is not enabled.
340 #[cfg(feature = "alloc")]
341 #[cfg_attr(all(doc, feature = "unstable-doc"), doc(cfg(feature = "alloc")))]
342 pub type BoxFuture<'a, T> = Pin<alloc::boxed::Box<dyn Future<Output = T> + 'a>>;
343
344 /// A pointer type which can be safely shared between threads
345 /// when "sync" feature is enabled.\
346 /// A pointer type which can be shared, but only within single thread
347 /// where it was created when "sync" feature is not enabled.
348 ///
349 /// # Example
350 ///
351 /// ```
352 /// # use {maybe_sync::{MaybeSend, Rc}, std::fmt::Debug};
353 ///
354 /// fn maybe_sends<T: MaybeSend + Debug + 'static>(val: T) {
355 /// #[cfg(feature = "sync")]
356 /// {
357 /// // If this code is compiled then `MaybeSend` is alias to `std::marker::Send`.
358 /// std::thread::spawn(move || { println!("{:?}", val) });
359 /// }
360 /// }
361 ///
362 /// // Unlike `std::rc::Rc` this `maybe_sync::Rc<T>` would always
363 /// // satisfy `MaybeSend` bound when `T: MaybeSend + MaybeSync`,
364 /// // even if feature "sync" is enabeld.
365 /// maybe_sends(Rc::new(42));
366 /// ```
367 #[cfg(feature = "alloc")]
368 #[cfg_attr(all(doc, feature = "unstable-doc"), doc(cfg(feature = "alloc")))]
369 pub type Rc<T> = alloc::rc::Rc<T>;
370
371 /// Mutex implementation to use in conjunction with `MaybeSync` bound.
372 ///
373 /// A type alias to `parking_lot::Mutex` when "sync" feature is enabled.\
374 /// A wrapper type around `std::cell::RefCell` when "sync" feature is not enabled.
375 ///
376 /// # Example
377 ///
378 /// ```
379 /// # use {maybe_sync::{MaybeSend, Mutex}, std::{fmt::Debug, sync::Arc}};
380 ///
381 /// fn maybe_sends<T: MaybeSend + Debug + 'static>(val: Arc<Mutex<T>>) {
382 /// #[cfg(feature = "sync")]
383 /// {
384 /// // If this code is compiled then `MaybeSend` is alias to `std::marker::Send`,
385 /// // and `Mutex` is `parking_lot::Mutex`.
386 /// std::thread::spawn(move || { println!("{:?}", *val.lock()) });
387 /// }
388 /// }
389 ///
390 /// // `maybe_sync::Mutex<T>` would always satisfy `MaybeSync` and `MaybeSend`
391 /// // bounds when `T: MaybeSend`,
392 /// // even if feature "sync" is enabeld.
393 /// maybe_sends(Arc::new(Mutex::new(42)));
394 /// ```
395 #[repr(transparent)]
396 #[derive(Debug, Default)]
397 pub struct Mutex<T: ?Sized> {
398 cell: RefCell<T>,
399 }
400
401 impl<T> Mutex<T> {
402 /// Creates a new mutex in an unlocked state ready for use.
403 pub fn new(value: T) -> Self {
404 Mutex {
405 cell: RefCell::new(value),
406 }
407 }
408 }
409
410 impl<T> Mutex<T>
411 where
412 T: ?Sized,
413 {
414 /// Acquires a mutex, blocking the current thread until it is able to do so.\
415 /// This function will block the local thread until it is available to acquire the mutex.\
416 /// Upon returning, the thread is the only thread with the mutex held.\
417 /// An RAII guard is returned to allow scoped unlock of the lock.\
418 /// When the guard goes out of scope, the mutex will be unlocked.\
419 /// Attempts to lock a mutex in the thread which already holds the lock will result in a deadlock.
420 pub fn lock(&self) -> RefMut<T> {
421 self.cell.borrow_mut()
422 }
423
424 /// Attempts to acquire this lock.\
425 /// If the lock could not be acquired at this time, then `None` is returned.\
426 /// Otherwise, an RAII guard is returned.\
427 /// The lock will be unlocked when the guard is dropped.\
428 /// This function does not block.
429 pub fn try_lock(&self) -> Option<RefMut<T>> {
430 self.cell.try_borrow_mut().ok()
431 }
432
433 /// Returns a mutable reference to the underlying data.\
434 /// Since this call borrows the `Mutex` mutably,\
435 /// no actual locking needs to take place -
436 /// the mutable borrow statically guarantees no locks exist.
437 pub fn get_mut(&mut self) -> &mut T {
438 self.cell.get_mut()
439 }
440 }
441
442 /// A boolean type which can be safely shared between threads
443 /// when "sync" feature is enabled.\
444 /// A boolean type with non-threadsafe interior mutability
445 /// when "sync" feature is not enabled.
446 ///
447 /// This type has the same in-memory representation as a bool.
448 pub type AtomicBool = core::cell::Cell<bool>;
449
450 /// A integer type which can be safely shared between threads
451 /// when "sync" feature is enabled.\
452 /// A integer type with non-threadsafe interior mutability
453 /// when "sync" feature is not enabled.
454 ///
455 /// This type has the same in-memory representation as a i8.
456 pub type AtomicI8 = core::cell::Cell<i8>;
457
458 /// A integer type which can be safely shared between threads
459 /// when "sync" feature is enabled.\
460 /// A integer type with non-threadsafe interior mutability
461 /// when "sync" feature is not enabled.
462 ///
463 /// This type has the same in-memory representation as a i16.
464 pub type AtomicI16 = core::cell::Cell<i16>;
465
466 /// A integer type which can be safely shared between threads
467 /// when "sync" feature is enabled.\
468 /// A integer type with non-threadsafe interior mutability
469 /// when "sync" feature is not enabled.
470 ///
471 /// This type has the same in-memory representation as a i32.
472 pub type AtomicI32 = core::cell::Cell<i32>;
473
474 /// A integer type which can be safely shared between threads
475 /// when "sync" feature is enabled.\
476 /// A integer type with non-threadsafe interior mutability
477 /// when "sync" feature is not enabled.
478 ///
479 /// This type has the same in-memory representation as a isize.
480 pub type AtomicIsize = core::cell::Cell<isize>;
481
482 /// A integer type which can be safely shared between threads
483 /// when "sync" feature is enabled.\
484 /// A integer type with non-threadsafe interior mutability
485 /// when "sync" feature is not enabled.
486 ///
487 /// This type has the same in-memory representation as a i8.
488 pub type AtomicU8 = core::cell::Cell<u8>;
489
490 /// A integer type which can be safely shared between threads
491 /// when "sync" feature is enabled.\
492 /// A integer type with non-threadsafe interior mutability
493 /// when "sync" feature is not enabled.
494 ///
495 /// This type has the same in-memory representation as a i16.
496 pub type AtomicU16 = core::cell::Cell<u16>;
497
498 /// A integer type which can be safely shared between threads
499 /// when "sync" feature is enabled.\
500 /// A integer type with non-threadsafe interior mutability
501 /// when "sync" feature is not enabled.
502 ///
503 /// This type has the same in-memory representation as a i32.
504 pub type AtomicU32 = core::cell::Cell<u32>;
505
506 /// A integer type which can be safely shared between threads
507 /// when "sync" feature is enabled.\
508 /// A integer type with non-threadsafe interior mutability
509 /// when "sync" feature is not enabled.
510 ///
511 /// This type has the same in-memory representation as a isize.
512 pub type AtomicUsize = core::cell::Cell<usize>;
513
514 /// A raw pointer type which can be safely shared between threads
515 /// when "sync" feature is enabled.\
516 /// A raw pointer type with non-threadsafe interior mutability
517 /// when "sync" feature is not enabled.
518 ///
519 /// This type has the same in-memory representation as a isize.
520 pub type AtomicPtr<T> = core::cell::Cell<*mut T>;
521}
522
523#[cfg(feature = "sync")]
524pub use sync::*;
525
526#[cfg(not(feature = "sync"))]
527pub use unsync::*;
528
529/// Expands to `dyn $traits` with `Send` marker trait
530/// added when "sync" feature is enabled.
531///
532/// Expands to `dyn $traits` without `Send` marker trait
533/// added "sync" feature is not enabled.
534///
535/// # Example
536/// ```
537/// # use maybe_sync::{MaybeSend, dyn_maybe_send};
538/// fn foo<T: MaybeSend>(_: T) {}
539/// // `x` will implement `MaybeSend` whether "sync" feature is enabled or not.
540/// let x: Box<dyn_maybe_send!(std::future::Future<Output = u32>)> = Box::new(async move { 42 });
541/// foo(x);
542/// ```
543#[cfg(feature = "sync")]
544#[macro_export]
545macro_rules! dyn_maybe_send {
546 ($($traits:tt)+) => {
547 dyn $($traits)+ + Send
548 };
549}
550
551/// Expands to `dyn $traits` with `Send` marker trait
552/// added when "sync" feature is enabled.
553///
554/// Expands to `dyn $traits` without `Send` marker trait
555/// added "sync" feature is not enabled.
556///
557/// # Example
558/// ```
559/// # use maybe_sync::{MaybeSend, dyn_maybe_send};
560/// fn foo<T: MaybeSend>(_: T) {}
561/// // `x` will implement `MaybeSend` whether "sync" feature is enabled or not.
562/// let x: Box<dyn_maybe_send!(std::future::Future<Output = u32>)> = Box::new(async move { 42 });
563/// foo(x);
564/// ```
565#[cfg(not(feature = "sync"))]
566#[macro_export]
567macro_rules! dyn_maybe_send {
568 ($($traits:tt)+) => {
569 dyn $($traits)+
570 };
571}
572
573/// Expands to `dyn $traits` with `Sync` marker trait
574/// added when "sync" feature is enabled.
575///
576/// Expands to `dyn $traits` without `Sync` marker trait
577/// added "sync" feature is not enabled.
578///
579/// # Example
580/// ```
581/// # use maybe_sync::{MaybeSync, dyn_maybe_sync};
582/// fn foo<T: MaybeSync + ?Sized>(_: &T) {}
583///
584/// let x: &dyn_maybe_sync!(AsRef<str>) = &"qwerty";
585/// // `x` will implement `MaybeSync` whether "sync" feature is enabled or not.
586/// foo(x);
587/// ```
588#[cfg(feature = "sync")]
589#[macro_export]
590macro_rules! dyn_maybe_sync {
591 ($($traits:tt)+) => {
592 dyn $($traits)+ + Sync
593 };
594}
595
596/// Expands to `dyn $traits` with `Sync` marker trait
597/// added when "sync" feature is enabled.
598///
599/// Expands to `dyn $traits` without `Sync` marker trait
600/// added "sync" feature is not enabled.
601///
602/// # Example
603/// ```
604/// # use maybe_sync::{MaybeSync, dyn_maybe_sync};
605/// fn foo<T: MaybeSync + ?Sized>(_: &T) {}
606/// // `x` will implement `MaybeSync` whether "sync" feature is enabled or not.
607/// let x: &dyn_maybe_sync!(AsRef<str>) = &"qwerty";
608/// foo(x);
609/// ```
610#[cfg(not(feature = "sync"))]
611#[macro_export]
612macro_rules! dyn_maybe_sync {
613 ($($traits:tt)+) => {
614 dyn $($traits)+
615 };
616}
617
618/// Expands to `dyn $traits` with `Send` and `Sync` marker trait
619/// added when "sync" feature is enabled.
620///
621/// Expands to `dyn $traits` without `Send` and `Sync` marker trait
622/// added "sync" feature is not enabled.
623///
624/// # Example
625/// ```
626/// # use maybe_sync::{MaybeSend, MaybeSync, dyn_maybe_send_sync};
627/// fn foo<T: MaybeSend + MaybeSync + ?Sized>(_: &T) {}
628/// // `x` will implement `MaybeSend` and `MaybeSync` whether "sync" feature is enabled or not.
629/// let x: &dyn_maybe_send_sync!(AsRef<str>) = &"qwerty";
630/// foo(x);
631/// ```
632#[cfg(feature = "sync")]
633#[macro_export]
634macro_rules! dyn_maybe_send_sync {
635 ($($traits:tt)+) => {
636 dyn $($traits)+ + Send + Sync
637 };
638}
639
640/// Expands to `dyn $traits` with `Sync` marker trait
641/// added when "sync" feature is enabled.
642///
643/// Expands to `dyn $traits` without `Sync` marker trait
644/// added "sync" feature is not enabled.
645///
646/// # Example
647/// ```
648/// # use maybe_sync::{MaybeSend, MaybeSync, dyn_maybe_send_sync};
649/// fn foo<T: MaybeSend + MaybeSync + ?Sized>(_: &T) {}
650/// // `x` will implement `MaybeSend` and `MaybeSync` whether "sync" feature is enabled or not.
651/// let x: &dyn_maybe_send_sync!(AsRef<str>) = &"qwerty";
652/// foo(x);
653/// ```
654#[cfg(not(feature = "sync"))]
655#[macro_export]
656macro_rules! dyn_maybe_send_sync {
657 ($($traits:tt)+) => {
658 dyn $($traits)+
659 };
660}