jvm_rs/
weak.rs

1use std::sync::atomic::{AtomicUsize, Ordering};
2use std::{marker, mem};
3use std::ffi::CString;
4use std::os::raw::{c_char, c_void};
5
6pub struct Weak<F> {
7	name: &'static str,
8	addr: AtomicUsize,
9	_marker: marker::PhantomData<F>,
10}
11
12impl<F> Weak<F> {
13	pub const fn new(name: &'static str) -> Weak<F> {
14		Weak {
15			name,
16			addr: AtomicUsize::new(1),
17			_marker: marker::PhantomData,
18		}
19	}
20	
21	pub fn get(&self) -> Option<&F> {
22		assert_eq!(mem::size_of::<F>(), mem::size_of::<usize>());
23		unsafe {
24			if self.addr.load(Ordering::SeqCst) == 1 {
25				self.addr.store(fetch(self.name), Ordering::SeqCst);
26			}
27			if self.addr.load(Ordering::SeqCst) == 0 {
28				None
29			} else {
30				mem::transmute::<&AtomicUsize, Option<&F>>(&self.addr)
31			}
32		}
33	}
34}
35
36unsafe fn fetch(name: &str) -> usize {
37	let name = match CString::new(name) {
38		Ok(cstr) => cstr,
39		Err(..) => return 0,
40	};
41	find_symbol(name.as_ptr())
42}
43
44#[cfg(unix)]
45unsafe fn find_symbol(name: *const c_char) -> usize {
46	extern "C" {
47		pub fn dlsym(
48			handle: *mut c_void,
49			symbol: *const c_char,
50		) -> *mut c_void;
51	}
52	pub const RTLD_DEFAULT: *mut c_void = 0i64 as *mut c_void;
53	
54	dlsym(RTLD_DEFAULT, name) as usize
55}
56
57#[cfg(windows)]
58unsafe fn find_symbol(name: *const c_char) -> usize {
59	use std::ptr::null;
60	use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress};
61	GetProcAddress(GetModuleHandleA(null()), name) as usize
62}