process_owned/lib.rs
1#![warn(missing_docs)]
2
3//! This crate provides the `ProcessOwned` type, a value
4//! that shares its lifetime with the process *unless* it
5//! can be optimally freed earlier than that.
6//!
7//! Internally, `ProcessOwned` uses the `Rc` type to
8//! ensure that the value is only dropped when the last
9//! owner is dropped. The specific implementation is
10//! subject to change for performance reasons.
11
12use std::{
13 rc::Rc,
14 cell::RefCell,
15 ops::Deref,
16 alloc::{alloc, Layout}
17};
18
19/// A value that is owned by the process itself.
20///
21/// The lifetime of a value is tied to its owner. When the
22/// owner is dropped, the value is dropped as well. This
23/// object uses the `Rc` type internally to ensure that
24/// the value is only dropped when the last owner is dropped.
25/// The specific implementation is subject to change for
26/// performance reasons.
27///
28/// When a `ProcessOwned` is initialized as a global static
29/// variable with the `lazy_static` crate, it will never be
30/// dropped. This allows values to easily and clearly share
31/// the scope of the entire process.
32#[derive(Clone, Debug)]
33pub struct ProcessOwned<T> {
34 value: Rc<T>
35}
36
37impl<T> ProcessOwned<T> {
38 /// Create a new `ProcessOwned` value.
39 ///
40 /// # Examples
41 ///
42 /// ```
43 /// use process_owned::ProcessOwned;
44 ///
45 /// let value = ProcessOwned::new(5);
46 /// assert_eq!(*value, 5);
47 /// ```
48 pub fn new(value: T) -> Self {
49 ProcessOwned {
50 value: Rc::new(value)
51 }
52 }
53}
54
55impl<T> Deref for ProcessOwned<T> {
56 type Target = T;
57
58 fn deref(&self) -> &Self::Target {
59 &self.value
60 }
61}
62
63/// A mutable version of `ProcessOwned`.
64///
65/// This type is identical to `ProcessOwned` except that
66/// it provides mutability. This is done by using a
67/// `RefCell` internally.
68#[derive(Clone, Debug)]
69pub struct ProcessOwnedMut<T> {
70 value: Rc<RefCell<T>>
71}
72
73impl<T> ProcessOwnedMut<T> {
74 /// Create a new `ProcessOwnedMut` value.
75 ///
76 /// # Examples
77 ///
78 /// ```
79 /// use process_owned::ProcessOwnedMut;
80 ///
81 /// let mut value = ProcessOwnedMut::new(5);
82 /// *value.borrow_mut() = 10;
83 /// assert_eq!(*value.borrow(), 10);
84 /// ```
85 pub fn new(value: T) -> Self {
86 ProcessOwnedMut {
87 value: Rc::new(RefCell::new(value))
88 }
89 }
90}
91
92impl<T> Deref for ProcessOwnedMut<T> {
93 type Target = RefCell<T>;
94
95 fn deref(&self) -> &Self::Target {
96 &self.value
97 }
98}
99
100/// A value that is truly owned by the process itself.
101///
102/// Using this type is similar to using a `ProcessOwned`
103/// with `lazy_static`, except the value can only be dropped
104/// when the process terminates. This can lead to memory
105/// leaks, but it can also be useful for values that are
106/// used throughout the entire process.
107#[derive(Clone, Debug)]
108pub struct Immortal<T> {
109 value: *const T
110}
111
112impl<T> Immortal<T> {
113 /// Creates a new `Immortal` value.
114 ///
115 /// # Safety
116 ///
117 /// This function is unsafe because it allocates memory
118 /// and stores a raw pointer to it. The memory is never
119 /// freed, so it is up to the caller to ensure that the
120 /// memory is not leaked.
121 ///
122 /// # Examples
123 ///
124 /// ```
125 /// use process_owned::Immortal;
126 ///
127 /// unsafe {
128 /// let immortal = Immortal::new(5);
129 /// assert_eq!(*immortal, 5);
130 /// }
131 /// ```
132 pub unsafe fn new(value: T) -> Self {
133 let layout = Layout::new::<T>();
134 let ptr = alloc(layout) as *mut T;
135 *ptr = value;
136
137 Immortal {
138 value: ptr
139 }
140 }
141}
142
143impl<T> From<Immortal<T>> for *const T {
144 fn from(immortal: Immortal<T>) -> Self {
145 immortal.value
146 }
147}
148
149impl<T> Deref for Immortal<T> {
150 type Target = T;
151
152 fn deref(&self) -> &Self::Target {
153 unsafe { &*self.value }
154 }
155}