Skip to content

Commit 1d3f95c

Browse files
committed
[context] Once again support singleton and thread-unsafe collectors
Before this was a compilation error (because I was focusing on default features). Now the features "sync" and "multiple-collectors" are truly optional once again. Bump version
1 parent 85efecf commit 1d3f95c

File tree

8 files changed

+86
-59
lines changed

8 files changed

+86
-59
lines changed

Diff for: Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "zerogc"
3-
version = "0.1.0"
3+
version = "0.1.2"
44
authors = ["Techcable <[email protected]>"]
55
description = "Zero overhead tracing garbage collection for rust"
66
repository = "https://github.com/DuckLogic/zerogc"
@@ -15,7 +15,7 @@ readme = "README.md"
1515
indexmap = { version = "1.4", optional = true }
1616

1717
[workspace]
18-
members = ["libs/simple", "libs/derive"]
18+
members = ["libs/simple", "libs/derive", "libs/context"]
1919

2020
[profile.dev]
2121
opt-level = 1

Diff for: libs/context/Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
[package]
22
name = "zerogc-context"
33
description = "Handles the context of a zerogc collector."
4-
version = "0.1.1"
4+
version = "0.1.2"
55
authors = ["Techcable <[email protected]>"]
66
repository = "https://github.com/DuckLogic/zerogc"
77
readme = "../../README.md"
88
license = "MIT"
99
edition = "2018"
1010

1111
[dependencies]
12-
zerogc = { path = "../..", version = "0.1.0" }
12+
zerogc = { path = "../..", version = "0.1.2" }
1313
once_cell = { version = "1.4.0", optional = true }
1414
# Concurrency
1515
parking_lot = { version = "0.11", features = ["nightly"], optional = true }

Diff for: libs/context/src/collector.rs

+36-15
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
//! The interface to a collector
22
3-
use std::ptr::NonNull;
4-
use std::sync::Arc;
53
use std::fmt::{self, Debug, Formatter};
4+
#[cfg(feature = "multiple-collectors")]
5+
use std::sync::Arc;
6+
#[cfg(feature = "multiple-collectors")]
7+
use std::ptr::NonNull;
68

79
use slog::{Logger, o};
810

911
use zerogc::{Gc, GcSafe, GcSystem, Trace, GcSimpleAlloc};
1012

1113
use crate::{CollectorContext, CollectionManager};
14+
#[cfg(not(feature = "multiple-collectors"))]
15+
use std::marker::PhantomData;
1216

1317
/// A specific implementation of a collector
1418
pub unsafe trait RawCollectorImpl: 'static + Sized {
@@ -21,19 +25,27 @@ pub unsafe trait RawCollectorImpl: 'static + Sized {
2125
/// Convert the specified value into a dyn pointer
2226
unsafe fn create_dyn_pointer<T: Trace>(t: *mut T) -> Self::GcDynPointer;
2327

28+
/// Id of global collector, for when we aren't configured
29+
/// to allow multiple collectors.
2430
#[cfg(not(feature = "multiple-collectors"))]
31+
const GLOBAL_ID: &'static CollectorId<Self> = &CollectorId { _marker: PhantomData };
32+
2533
/// When the collector is a singleton,
2634
/// return the global implementation
35+
#[cfg(not(feature = "multiple-collectors"))]
2736
fn global_ptr() -> *const Self;
37+
2838
#[cfg(not(feature = "multiple-collectors"))]
2939
fn init_global(logger: Logger);
40+
3041
#[cfg(feature = "multiple-collectors")]
3142
fn init(logger: Logger) -> NonNull<Self>;
43+
3244
/// The id of this collector
3345
#[inline]
3446
fn id(&self) -> CollectorId<Self> {
3547
#[cfg(not(feature = "multiple-collectors"))] {
36-
CollectorId {}
48+
CollectorId { _marker: PhantomData }
3749
}
3850
#[cfg(feature = "multiple-collectors")] {
3951
CollectorId { rc: NonNull::from(self) }
@@ -63,6 +75,7 @@ impl<C: RawCollectorImpl> PartialEq for CollectorId<C> {
6375
self.rc.as_ptr() == other.rc.as_ptr()
6476
}
6577
#[cfg(not(feature = "multiple-collectors"))] {
78+
let CollectorId { _marker: PhantomData } = *other;
6679
true // Singleton
6780
}
6881
}
@@ -103,6 +116,11 @@ pub struct CollectorId<C: RawCollectorImpl> {
103116
///
104117
/// We don't know whether the underlying memory will be valid.
105118
rc: NonNull<C>,
119+
/// Phantom reference to `&'static C`
120+
///
121+
/// This represents the fact we (statically) refer to the global instance
122+
#[cfg(not(feature = "multiple-collectors"))]
123+
_marker: PhantomData<&'static C>
106124
}
107125
impl<C: RawCollectorImpl> CollectorId<C> {
108126
#[cfg(feature = "multiple-collectors")]
@@ -118,7 +136,7 @@ impl<C: RawCollectorImpl> CollectorId<C> {
118136
#[cfg(not(feature = "multiple-collectors"))]
119137
#[inline]
120138
pub unsafe fn as_ref(&self) -> &C {
121-
&*GLOBAL_COLLECTOR.load(Ordering::Acquire)
139+
&*C::global_ptr()
122140
}
123141
#[cfg(feature = "multiple-collectors")]
124142
pub unsafe fn weak_ref(&self) -> WeakCollectorRef<C> {
@@ -129,7 +147,7 @@ impl<C: RawCollectorImpl> CollectorId<C> {
129147
}
130148
#[cfg(not(feature = "multiple-collectors"))]
131149
pub unsafe fn weak_ref(&self) -> WeakCollectorRef<C> {
132-
WeakCollectorRef { }
150+
WeakCollectorRef { _marker: PhantomData }
133151
}
134152
}
135153
unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
@@ -155,16 +173,16 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
155173
&*(self as *const CollectorId<C> as *const CollectorRef<C>)
156174
}
157175
#[cfg(not(feature = "multiple-collectors"))] {
158-
// NOTE: We live forever
159-
const COLLECTOR: CollectorRef = CollectorRef { };
160-
&COLLECTOR
176+
&*(C::GLOBAL_ID as *const CollectorId<C> as *const CollectorRef<C>)
161177
}
162178
}
163179
}
164180

165181
pub struct WeakCollectorRef<C: RawCollectorImpl> {
166182
#[cfg(feature = "multiple-collectors")]
167183
weak: std::sync::Weak<C>,
184+
#[cfg(not(feature = "multiple-collectors"))]
185+
_marker: PhantomData<&'static C>
168186
}
169187
impl<C: RawCollectorImpl> WeakCollectorRef<C> {
170188
#[cfg(feature = "multiple-collectors")]
@@ -179,7 +197,7 @@ impl<C: RawCollectorImpl> WeakCollectorRef<C> {
179197
}
180198
#[cfg(not(feature = "multiple-collectors"))]
181199
pub unsafe fn assume_valid(&self) -> CollectorId<C> {
182-
CollectorId {}
200+
CollectorId { _marker: PhantomData }
183201
}
184202
pub fn ensure_valid<R>(&self, func: impl FnOnce(CollectorId<C>) -> R) -> R {
185203
self.try_ensure_valid(|id| match id{
@@ -200,7 +218,7 @@ impl<C: RawCollectorImpl> WeakCollectorRef<C> {
200218
#[cfg(not(feature = "multiple-collectors"))]
201219
pub fn try_ensure_valid<R>(&self, func: impl FnOnce(Option<CollectorId<C>>) -> R) -> R {
202220
// global collector is always valid
203-
func(Some(CollectorId {}))
221+
func(Some(CollectorId { _marker: PhantomData }))
204222
}
205223
}
206224

@@ -224,7 +242,10 @@ pub struct CollectorRef<C: RawCollectorImpl> {
224242
///
225243
/// It is implemented as a raw pointer around [Arc::into_raw]
226244
#[cfg(feature = "multiple-collectors")]
227-
rc: NonNull<C>
245+
rc: NonNull<C>,
246+
/// Phantom reference to the global collector instance
247+
#[cfg(not(feature = "multiple-collectors"))]
248+
_marker: PhantomData<&'static C>
228249
}
229250
/// We actually are thread safe ;)
230251
#[cfg(feature = "sync")]
@@ -241,9 +262,9 @@ impl<C: RawCollectorImpl> CollectorRef<C> {
241262
}
242263
#[cfg(not(feature = "multiple-collectors"))]
243264
pub fn with_logger(logger: Logger) -> Self {
244-
unsafe { C::init_global(logger) }
265+
C::init_global(logger); // TODO: Is this safe?
245266
// NOTE: The raw pointer is implicit (now that we're leaked)
246-
CollectorRef {}
267+
CollectorRef { _marker: PhantomData }
247268
}
248269

249270
#[cfg(feature = "multiple-collectors")]
@@ -262,7 +283,7 @@ impl<C: RawCollectorImpl> CollectorRef<C> {
262283
}
263284
#[cfg(not(feature = "multiple-collectors"))]
264285
pub(crate) fn clone_internal(&self) -> CollectorRef<C> {
265-
CollectorRef {}
286+
CollectorRef { _marker: PhantomData }
266287
}
267288
#[cfg(feature = "multiple-collectors")]
268289
#[inline]
@@ -272,7 +293,7 @@ impl<C: RawCollectorImpl> CollectorRef<C> {
272293
#[cfg(not(feature = "multiple-collectors"))]
273294
#[inline]
274295
pub fn as_raw(&self) -> &C {
275-
let ptr = GLOBAL_COLLECTOR.load(Ordering::Acquire);
296+
let ptr = C::global_ptr();
276297
assert!(!ptr.is_null());
277298
unsafe { &*ptr }
278299
}

Diff for: libs/context/src/handle.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
77

88
use zerogc::{Trace, GcSafe, GcBrand, GcVisitor, NullTrace, TraceImmutable, GcHandleSystem, GcBindHandle};
99
use crate::{Gc, WeakCollectorRef, CollectorId, CollectorContext, CollectorRef};
10-
#[cfg(feature = "sync")]
11-
use crate::SyncCollectorImpl;
12-
#[cfg(not(feature = "sync"))]
13-
use crate::NoSyncCollectorImpl; // TODO
1410
use crate::collector::RawCollectorImpl;
1511

1612
const INITIAL_HANDLE_CAPACITY: usize = 64;
@@ -391,7 +387,8 @@ unsafe impl<T: GcSafe, C: RawHandleImpl> ::zerogc::GcHandle<T> for GcHandle<T, C
391387
#[cfg(feature = "sync")]
392388
fn use_critical<R>(&self, func: impl FnOnce(&T) -> R) -> R {
393389
self.collector.ensure_valid(|collector| unsafe {
394-
390+
// Used for 'prevent_collection' method
391+
use crate::SyncCollectorImpl;
395392
/*
396393
* This should be sufficient to ensure
397394
* the value won't be collected or relocated.

Diff for: libs/context/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![feature(
22
negative_impls, // !Send is much cleaner than `PhantomData<Rc>`
33
untagged_unions, // I want to avoid ManuallyDrop in unions
4+
const_fn, // Apparently this feature is unstable???
45
)]
56
//! The implementation of [::zerogc::CollectorContext] that is
67
//! shared among both thread-safe and thread-unsafe code.
@@ -23,7 +24,10 @@ pub mod collector;
2324
pub mod handle;
2425

2526
use crate::collector::{RawCollectorImpl};
27+
#[cfg(feature = "sync")]
2628
use crate::sync::SyncCollectorImpl;
29+
#[cfg(not(feature = "sync"))]
30+
use crate::nosync::NoSyncCollectorImpl;
2731

2832
pub use crate::collector::{WeakCollectorRef, CollectorRef, CollectorId};
2933

0 commit comments

Comments
 (0)