1use platform;
2
3use std::{io};
4use std::ops::{Range, RangeFull, RangeTo, RangeFrom};
5use std::collections::Bound;
6use std::sync::Arc;
7
8use uuid::Uuid;
9
10#[cfg(test)]
12pub mod queue;
13#[cfg(test)]
14pub use self::queue::Queue;
15
16#[derive(Serialize, Deserialize, Clone, Debug)]
17pub struct SharedMem(Arc<_SharedMem>);
18
19#[derive(Debug)]
20#[derive(Serialize, Deserialize)]
21struct _SharedMem {
22 pub(crate) inner: platform::SharedMem,
23 pub(crate) token: Uuid,
24}
25
26#[derive(Clone, Debug)]
27pub struct SharedMemMap(Arc<_SharedMemMap>);
28
29#[derive(Debug)]
30struct _SharedMemMap {
31 object: SharedMem,
32 inner: platform::SharedMemMap,
33}
34
35#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
36pub enum Access {
37 Read,
38 ReadWrite,
39}
40
41impl SharedMem {
42 pub fn new(size: usize) -> io::Result<SharedMem> {
43 let inner = platform::SharedMem::new(size)?;
44 let token = Uuid::new_v4();
45 Ok(SharedMem(Arc::new(_SharedMem { inner, token })))
46 }
47
48 pub fn size(&self) -> usize { self.0.inner.size() }
49
50 pub fn clone_with_access(&self, access: Access) -> io::Result<SharedMem> {
51 let inner = self.0.inner.clone(access)?;
52 Ok(SharedMem(Arc::new(_SharedMem { inner, token: self.0.token })))
53 }
54
55 pub fn map<R: RangeArgument<usize>>(&self, range: R, access: Access) -> io::Result<SharedMemMap> where {
56 let inner = self.0.inner.map(range, access)?;
57 Ok(SharedMemMap(Arc::new(_SharedMemMap {
58 object: self.clone(),
59 inner,
60 })))
61 }
62}
63
64impl SharedMemMap {
65 pub unsafe fn pointer(&self) -> *mut u8 { self.0.inner.pointer() }
66 pub fn len(&self) -> usize { self.0.inner.len() }
67 pub fn access(&self) -> Access { self.0.inner.access() }
68 pub fn offset(&self) -> usize { self.0.inner.offset() }
69
70 pub(crate) fn token(&self) -> Uuid { self.0.object.0.token }
71}
72
73pub trait RangeArgument<T> {
74 fn start(&self) -> Bound<&T>;
75 fn end(&self) -> Bound<&T>;
76}
77
78impl<T> RangeArgument<T> for RangeFull {
79 fn start(&self) -> Bound<&T> { Bound::Unbounded }
80 fn end(&self) -> Bound<&T> { Bound::Unbounded }
81}
82
83impl<T> RangeArgument<T> for RangeFrom<T> {
84 fn start(&self) -> Bound<&T> { Bound::Included(&self.start) }
85 fn end(&self) -> Bound<&T> { Bound::Unbounded }
86}
87
88impl<T> RangeArgument<T> for RangeTo<T> {
89 fn start(&self) -> Bound<&T> { Bound::Unbounded }
90 fn end(&self) -> Bound<&T> { Bound::Excluded(&self.end) }
91}
92
93impl<T> RangeArgument<T> for Range<T> {
94 fn start(&self) -> Bound<&T> { Bound::Included(&self.start) }
95 fn end(&self) -> Bound<&T> { Bound::Excluded(&self.end) }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use ::{MessageChannel, check_send};
102
103 use tokio::runtime::Runtime;
104 use futures::{Sink, Stream};
105
106 #[test]
107 fn shared_mem_map_is_send() {
108 let memory = SharedMem::new(4096).unwrap();
109 let memory = memory.map(.., Access::ReadWrite).unwrap();
110 check_send(&memory);
111 }
112
113 #[test]
114 fn shared_mem_is_send() {
115 let memory = SharedMem::new(4096).unwrap();
116 check_send(&memory);
117 }
118
119 #[test]
120 fn send_mem_same_process() {
121 let mut runtime = Runtime::new().unwrap();
122 let (a, b) = MessageChannel::pair(runtime.reactor(), 8192).unwrap();
123
124 let test_bytes: &[u8] = b"hello";
125
126 let memory = SharedMem::new(0x1000).unwrap();
127 unsafe {
128 let mapping = memory.map(.., Access::ReadWrite).unwrap();
129 let slice = ::std::slice::from_raw_parts_mut(mapping.pointer(), mapping.len());
130
131 slice[0..test_bytes.len()].copy_from_slice(test_bytes);
132 }
133
134 let _a = runtime.block_on(a.send(memory)).unwrap();
135 let (message, _b) = runtime.block_on(b.into_future()).map_err(|(err, _)| err).unwrap();
136 let memory: SharedMem = message.unwrap();
137
138 unsafe {
139 let mapping = memory.map(.., Access::Read).unwrap();
140 let slice = ::std::slice::from_raw_parts_mut(mapping.pointer(), mapping.len());
141
142 assert_eq!(&slice[0..test_bytes.len()], test_bytes);
143 }
144 }
145
146 #[test]
147 fn big_shm() {
148 let memory = SharedMem::new(64 * 1024 * 1024).unwrap();
149 let _mapping = memory.map(.., Access::ReadWrite).unwrap();
150 }
151}