aboutsummaryrefslogtreecommitdiff
path: root/src/sync.rs
blob: cd626faee9ad26bb3969b6e9b9018ce3de97d658 (plain)
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
//! # Synchronization module
//!
//! Provides synchronization objects for thread-safe memory sharing.
use core::cell::UnsafeCell;

/// # Synchronization interfaces
///
/// Provides Synchronization traits.
pub mod interface {
	/// # Mutex Trait
	///
	/// Basic Locking primitive to allow single-process access to data
	pub trait Mutex {
		/// # The data
		///
		/// Each mutex protects some internal data from modification across
		/// processes when it is in use. This is important if the process
		/// is preempted while the function is using it.
		type Data;
		/// # Locking mechanism
		///
		/// Locks the mutex to access the data in a closure.
		/// The data can be read and modified in this closure without worry
		/// of poisoning the data across processes.
		fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut Self::Data) -> R) -> R;
	}
}

/// # Basic Lock Structure
pub struct NullLock<T> where T: ?Sized {
	/// The internal data to safely share
	data: UnsafeCell<T>,
}

/// # Allow thread sharing
unsafe impl<T> Send for NullLock<T> where T: ?Sized + Send {}
/// # Allow thread sharing
unsafe impl<T> Sync for NullLock<T> where T: ?Sized + Send {}

impl<T> NullLock<T> {
	/// # Create a new instance of the lock
	pub const fn new(data: T) -> Self {
		Self {
			data: UnsafeCell::new(data),
		}
	}
}

impl<T> interface::Mutex for NullLock<T> {
	/// # Underlying data of the lock
	type Data = T;

	/// # Locking mechanism
	///
	/// Locks the Mutex, and passes a mutable reference
	/// to the encapsulated data to a closure.
	fn lock<'a, R>(&'a self, f: impl FnOnce(&'a mut T) -> R) -> R {
		let data = unsafe { &mut *self.data.get() };

		f(data)
	}
}