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
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#![cfg_attr(feature="experimental-auto-traits", feature(optin_builtin_traits))]
#![cfg_attr(not(feature="std"), no_std)]
//! The interprocess-traits crate provides type traits to annotate types which have certain
//! properties when used in a multiprocess environment.


#[cfg(feature="std")]
use std as core;

use core::sync::atomic::*;
use core::num::*;

#[cfg(feature="experimental-auto-traits")]
macro_rules! maybe_auto_trait {
    ($doctext:literal pub unsafe trait $traitname:ident: $deps:ident {}) => {
        // NB: no supertrait, built-in traits cannot have them!
        #[doc=$doctext]
        pub unsafe auto trait $traitname {}
    }
}

#[cfg(not(feature="experimental-auto-traits"))]
macro_rules! maybe_auto_trait {
    ($doctext:literal pub unsafe trait $traitname:ident: $deps:ident {}) => {
        #[doc=$doctext]
        pub unsafe trait $traitname: $deps {}
    }
}

maybe_auto_trait! {
"Types which can be transferred across process boundary.

An example of non-`ProcSend` type would be any type that contains pointers to values in \
a process’ address space. Instead a `ProcSend` type would use indices which the \
processes would know how to convert into their own address space.

In general, for any type to implement `ProcSend`, it must be [`Send`], as threads \
conceptually are the same as processes which share the same address space.

Unlike [`Send`], `ProcSend` is not an auto-trait by default, because auto-traits are not stable. \
Unless the `auto_traits` feature is enabled, it will be necessary to implement this \
trait manually.

Finally, currently `ProcSend` is only implemented for the built-in types which have \
specified type layout and are ffi-safe. This is a conservative default as there is \
no guarantee that the two interacting processes will be compiled with a same version \
of Rust or are Rust at all."
pub unsafe trait ProcSend: Send {}
}

maybe_auto_trait! {
"Types for which it is safe to share references between processes.

Much like [`ProcSend`] is a cross-process [`Send`], [`ProcSync`] is a cross-process [`Sync`].

In general, for any type to implement `ProcSync`, it must be [`Sync`], as threads conceptually \
are the same as processes which sahre the same address space.

Unlike [`Sync`], `ProcSync` is not an auto-trait by default, because auto-traits are not stable. \
Unless the `auto_traits` feature is enabled, it will be necessary to implement this \
trait manually."
pub unsafe trait ProcSync: Sync {}
}

macro_rules! implement_marker_for {
    (unsafe impl $trait:ident for $($t:ty),*) => {
        $(unsafe impl $trait for $t {})*
    };
    (unsafe impl !$trait:ident for $($t:ty),*) => {
        $(unsafe impl !$trait for $t {})*
    };
}

macro_rules! implement_marker_for_tuples {
    (unsafe impl $trait:ident for) => { };
    (unsafe impl $trait:ident for $hd:ident, $($tl:ident,)*) => {
        unsafe impl<$hd: $trait, $($tl: $trait),*> $trait for ($hd, $($tl),*) {}
        implement_marker_for_tuples! {
            unsafe impl $trait for $($tl,)*
        }
    };
}

implement_marker_for! {
    unsafe impl ProcSend for
    u8, u16, u32, u64, u128, usize,
    i8, i16, i32, i64, i128, isize,
    f32, f64,
    bool, char, str,
    AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
    AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize,
    AtomicBool,
    NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
    core::ffi::c_void
}

implement_marker_for_tuples! {
    unsafe impl ProcSend for
    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
}

unsafe impl<T: ProcSend> ProcSend for core::cell::RefCell<T> {}
unsafe impl<T: ProcSend> ProcSend for core::cell::Cell<T> {}
unsafe impl<T: ProcSend> ProcSend for core::cell::UnsafeCell<T> {}
unsafe impl<T: ProcSend> ProcSend for core::mem::ManuallyDrop<T> {}

#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSend for *const T {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSend for *mut T {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSend for AtomicPtr<T> {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSend for &T {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSend for &mut T {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::net::TcpListener {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::net::TcpStream {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::net::UdpSocket {}
#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
impl !ProcSend for std::os::unix::net::UnixDatagram {}
#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
impl !ProcSend for std::os::unix::net::UnixListener {}
#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
impl !ProcSend for std::os::unix::net::UnixStream {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::fs::File {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::process::Child {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::process::ChildStderr {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::process::ChildStdin {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::process::ChildStdout {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::process::Stdio {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSend for std::thread::ThreadId {}


implement_marker_for! {
    unsafe impl ProcSync for
    u8, u16, u32, u64, u128, usize,
    i8, i16, i32, i64, i128, isize,
    f32, f64,
    bool, char, str,
    AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
    AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize,
    AtomicBool,
    NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
    core::ffi::c_void
}

implement_marker_for_tuples! {
    unsafe impl ProcSync for
    T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
}

unsafe impl<T: ProcSync> ProcSync for core::mem::ManuallyDrop<T> {}

#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for core::cell::Cell<T> {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for core::cell::UnsafeCell<T> {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for *const T {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for *mut T {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for AtomicPtr<T> {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for core::ptr::NonNull<T> {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for &T {}
#[cfg(feature="experimental-auto-traits")]
impl<T> !ProcSync for &mut T {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::net::TcpListener {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::net::TcpStream {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::net::UdpSocket {}
#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
impl !ProcSync for std::os::unix::net::UnixDatagram {}
#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
impl !ProcSync for std::os::unix::net::UnixListener {}
#[cfg(all(feature="experimental-auto-traits", feature="std", unix))]
impl !ProcSync for std::os::unix::net::UnixStream {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::fs::File {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::process::Child {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::process::ChildStderr {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::process::ChildStdin {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::process::ChildStdout {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::process::Stdio {}
#[cfg(all(feature="experimental-auto-traits", feature="std"))]
impl !ProcSync for std::thread::ThreadId {}