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
use fltk_sys::fl;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
use std::{any, marker, mem, os::raw};
pub unsafe fn awake_msg<T>(msg: T) {
fl::Fl_awake_msg(Box::into_raw(Box::from(msg)) as *mut raw::c_void);
}
#[allow(clippy::missing_safety_doc)]
pub unsafe fn thread_msg<T>() -> Option<T> {
let msg = fl::Fl_thread_msg();
if msg.is_null() {
None
} else {
let msg = Box::from_raw(msg as *const _ as *mut T);
Some(*msg)
}
}
#[repr(C)]
struct Message<T: Send + Sync> {
hash: u64,
sz: usize,
msg: T,
}
#[derive(Debug, Clone, Copy)]
pub struct Sender<T: Send + Sync> {
data: marker::PhantomData<T>,
hash: u64,
sz: usize,
}
impl<T: Send + Sync> Sender<T> {
pub fn send(&self, val: T) {
let msg = Message {
hash: self.hash,
sz: self.sz,
msg: val,
};
unsafe { awake_msg(msg) }
}
}
#[derive(Debug, Clone, Copy)]
pub struct Receiver<T: Send + Sync> {
data: marker::PhantomData<T>,
hash: u64,
sz: usize,
}
impl<T: Send + Sync> Receiver<T> {
pub fn recv(&self) -> Option<T> {
let data: Option<Message<T>> = unsafe { thread_msg() };
data.and_then(|data| {
if data.sz == self.sz && data.hash == self.hash {
Some(data.msg)
} else {
None
}
})
}
}
pub fn channel<T: Send + Sync>() -> (Sender<T>, Receiver<T>) {
let msg_sz = mem::size_of::<T>();
let type_name = any::type_name::<T>();
let mut hasher = DefaultHasher::new();
type_name.hash(&mut hasher);
let type_hash = hasher.finish();
let s = Sender {
data: marker::PhantomData,
hash: type_hash,
sz: msg_sz,
};
let r = Receiver {
data: marker::PhantomData,
hash: type_hash,
sz: msg_sz,
};
(s, r)
}