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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// SRCE - Self-referential cell environments
// Copyright (C) 2022-2023 Soni L.
// This software is made with love by a queer trans person.
//
// SPDX-License-Identifier: MIT OR Apache-2.0
#![cfg_attr(not(test), no_std)]
//! SRCE is a way to open and close an `LCellOwner`, thus allowing the use of
//! `LCell` with tokio.
//!
//! It is based on `qcell` and `selfref`.
//!
//! This crate has not been audited for soundness at this time.
use qcell::LCellOwner;
use selfref::{Builder, Holder, Opaque, OperateIn};
use core::pin::Pin;
/// A self-referential environment of `LCell`s, with zero runtime cost.
pub struct LCellEnvironment<'k, T: Opaque + 'k> {
inner: Holder<'k, T>,
}
impl<'k, T> LCellEnvironment<'k, T> where T: Opaque {
/// Creates a new `LCellEnvironment`.
///
/// Works exactly like [`Holder::new_with`].
pub fn new_with<F>(f: F) -> Self
where
F: for<'a> FnOnce(&mut Builder<'a, T>),
T::Kind<'k>: Sized,
{
Self {
inner: Holder::new_with(f)
}
}
}
impl<'k, T> LCellEnvironment<'k, T> where T: Opaque {
/// Opens this LCellEnvironment for reading and writing (mutable).
pub fn open_rw<'i, F, R>(self: Pin<&'i mut Self>, f: F) -> R
where
F: for<'a, 'id> FnOnce(&'a mut LCellOwner<'id>, OperateIn<'id, T>) -> R,
{
unsafe {
self.map_unchecked_mut(|this| &mut this.inner)
}.into_ref().operate_in(|env| {
// SAFETY? we're actually unsure if this is sound!
// the LCellOwner is owned by us, and the borrow given to the
// closure is mutable if we're mutable, and shared if we're shared.
let guard = unsafe {
generativity::Guard::new(generativity::Id::new())
};
f(&mut LCellOwner::new(guard), env)
})
}
/// Opens this LCellEnvironment for reading only (shared).
pub fn open_ro<'i, F, R>(self: Pin<&'i Self>, f: F) -> R
where
F: for<'a, 'id> FnOnce(&'a LCellOwner<'id>, OperateIn<'id, T>) -> R,
{
unsafe {
self.map_unchecked(|this| &this.inner)
}.operate_in(|env| {
// SAFETY? we're actually unsure if this is sound!
// the LCellOwner is owned by us, and the borrow given to the
// closure is mutable if we're mutable, and shared if we're shared.
let guard = unsafe {
generativity::Guard::new(generativity::Id::new())
};
f(&LCellOwner::new(guard), env)
})
}
}
#[test]
fn test() {
use core::cell::Cell;
use core::marker::PhantomData;
use qcell::LCell;
trait Foo {
fn update(&mut self);
}
trait Bar {
fn get(&self) -> String;
}
struct MyThing;
impl Foo for MyThing {
fn update(&mut self) {
println!("hello world!");
}
}
impl Bar for MyThing {
fn get(&self) -> String {
return String::from("hello");
}
}
struct IntrusiveLCell<'a, T: ?Sized> {
y: Cell<Option<&'a LCell<'a, dyn Bar>>>,
x: LCell<'a, T>,
}
struct IntrusiveLCellKey<T: ?Sized>(PhantomData<T>);
selfref::opaque! {
impl[T: ?Sized] Opaque for IntrusiveLCellKey<T> {
type Kind<'this> = IntrusiveLCell<'this, T>;
}
}
let mut holder = Box::pin(
LCellEnvironment::<IntrusiveLCellKey<MyThing>>::new_with(|b| b.build(
IntrusiveLCell {
x: LCell::new(MyThing),
y: Cell::new(None),
}
))
);
holder.as_mut().open_rw(|owner, x| {
x.y.set(Some(&x.get_ref().x));
owner.rw(&x.x).update();
println!("{}", owner.ro(x.y.get().unwrap()).get());
});
let mut holder_dyn: Pin<Box<LCellEnvironment<IntrusiveLCellKey<dyn Foo>>>> = holder;
}
|