Skip to content

Commit

Permalink
[context] Once again support singleton and thread-unsafe collectors
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Techcable committed Dec 20, 2020
1 parent 85efecf commit 1d3f95c
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 59 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "zerogc"
version = "0.1.0"
version = "0.1.2"
authors = ["Techcable <[email protected]>"]
description = "Zero overhead tracing garbage collection for rust"
repository = "https://github.com/DuckLogic/zerogc"
Expand All @@ -15,7 +15,7 @@ readme = "README.md"
indexmap = { version = "1.4", optional = true }

[workspace]
members = ["libs/simple", "libs/derive"]
members = ["libs/simple", "libs/derive", "libs/context"]

[profile.dev]
opt-level = 1
Expand Down
4 changes: 2 additions & 2 deletions libs/context/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
[package]
name = "zerogc-context"
description = "Handles the context of a zerogc collector."
version = "0.1.1"
version = "0.1.2"
authors = ["Techcable <[email protected]>"]
repository = "https://github.com/DuckLogic/zerogc"
readme = "../../README.md"
license = "MIT"
edition = "2018"

[dependencies]
zerogc = { path = "../..", version = "0.1.0" }
zerogc = { path = "../..", version = "0.1.2" }
once_cell = { version = "1.4.0", optional = true }
# Concurrency
parking_lot = { version = "0.11", features = ["nightly"], optional = true }
Expand Down
51 changes: 36 additions & 15 deletions libs/context/src/collector.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
//! The interface to a collector

use std::ptr::NonNull;
use std::sync::Arc;
use std::fmt::{self, Debug, Formatter};
#[cfg(feature = "multiple-collectors")]
use std::sync::Arc;
#[cfg(feature = "multiple-collectors")]
use std::ptr::NonNull;

use slog::{Logger, o};

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

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

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

/// Id of global collector, for when we aren't configured
/// to allow multiple collectors.
#[cfg(not(feature = "multiple-collectors"))]
const GLOBAL_ID: &'static CollectorId<Self> = &CollectorId { _marker: PhantomData };

/// When the collector is a singleton,
/// return the global implementation
#[cfg(not(feature = "multiple-collectors"))]
fn global_ptr() -> *const Self;

#[cfg(not(feature = "multiple-collectors"))]
fn init_global(logger: Logger);

#[cfg(feature = "multiple-collectors")]
fn init(logger: Logger) -> NonNull<Self>;

/// The id of this collector
#[inline]
fn id(&self) -> CollectorId<Self> {
#[cfg(not(feature = "multiple-collectors"))] {
CollectorId {}
CollectorId { _marker: PhantomData }
}
#[cfg(feature = "multiple-collectors")] {
CollectorId { rc: NonNull::from(self) }
Expand Down Expand Up @@ -63,6 +75,7 @@ impl<C: RawCollectorImpl> PartialEq for CollectorId<C> {
self.rc.as_ptr() == other.rc.as_ptr()
}
#[cfg(not(feature = "multiple-collectors"))] {
let CollectorId { _marker: PhantomData } = *other;
true // Singleton
}
}
Expand Down Expand Up @@ -103,6 +116,11 @@ pub struct CollectorId<C: RawCollectorImpl> {
///
/// We don't know whether the underlying memory will be valid.
rc: NonNull<C>,
/// Phantom reference to `&'static C`
///
/// This represents the fact we (statically) refer to the global instance
#[cfg(not(feature = "multiple-collectors"))]
_marker: PhantomData<&'static C>
}
impl<C: RawCollectorImpl> CollectorId<C> {
#[cfg(feature = "multiple-collectors")]
Expand All @@ -118,7 +136,7 @@ impl<C: RawCollectorImpl> CollectorId<C> {
#[cfg(not(feature = "multiple-collectors"))]
#[inline]
pub unsafe fn as_ref(&self) -> &C {
&*GLOBAL_COLLECTOR.load(Ordering::Acquire)
&*C::global_ptr()
}
#[cfg(feature = "multiple-collectors")]
pub unsafe fn weak_ref(&self) -> WeakCollectorRef<C> {
Expand All @@ -129,7 +147,7 @@ impl<C: RawCollectorImpl> CollectorId<C> {
}
#[cfg(not(feature = "multiple-collectors"))]
pub unsafe fn weak_ref(&self) -> WeakCollectorRef<C> {
WeakCollectorRef { }
WeakCollectorRef { _marker: PhantomData }
}
}
unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
Expand All @@ -155,16 +173,16 @@ unsafe impl<C: RawCollectorImpl> ::zerogc::CollectorId for CollectorId<C> {
&*(self as *const CollectorId<C> as *const CollectorRef<C>)
}
#[cfg(not(feature = "multiple-collectors"))] {
// NOTE: We live forever
const COLLECTOR: CollectorRef = CollectorRef { };
&COLLECTOR
&*(C::GLOBAL_ID as *const CollectorId<C> as *const CollectorRef<C>)
}
}
}

pub struct WeakCollectorRef<C: RawCollectorImpl> {
#[cfg(feature = "multiple-collectors")]
weak: std::sync::Weak<C>,
#[cfg(not(feature = "multiple-collectors"))]
_marker: PhantomData<&'static C>
}
impl<C: RawCollectorImpl> WeakCollectorRef<C> {
#[cfg(feature = "multiple-collectors")]
Expand All @@ -179,7 +197,7 @@ impl<C: RawCollectorImpl> WeakCollectorRef<C> {
}
#[cfg(not(feature = "multiple-collectors"))]
pub unsafe fn assume_valid(&self) -> CollectorId<C> {
CollectorId {}
CollectorId { _marker: PhantomData }
}
pub fn ensure_valid<R>(&self, func: impl FnOnce(CollectorId<C>) -> R) -> R {
self.try_ensure_valid(|id| match id{
Expand All @@ -200,7 +218,7 @@ impl<C: RawCollectorImpl> WeakCollectorRef<C> {
#[cfg(not(feature = "multiple-collectors"))]
pub fn try_ensure_valid<R>(&self, func: impl FnOnce(Option<CollectorId<C>>) -> R) -> R {
// global collector is always valid
func(Some(CollectorId {}))
func(Some(CollectorId { _marker: PhantomData }))
}
}

Expand All @@ -224,7 +242,10 @@ pub struct CollectorRef<C: RawCollectorImpl> {
///
/// It is implemented as a raw pointer around [Arc::into_raw]
#[cfg(feature = "multiple-collectors")]
rc: NonNull<C>
rc: NonNull<C>,
/// Phantom reference to the global collector instance
#[cfg(not(feature = "multiple-collectors"))]
_marker: PhantomData<&'static C>
}
/// We actually are thread safe ;)
#[cfg(feature = "sync")]
Expand All @@ -241,9 +262,9 @@ impl<C: RawCollectorImpl> CollectorRef<C> {
}
#[cfg(not(feature = "multiple-collectors"))]
pub fn with_logger(logger: Logger) -> Self {
unsafe { C::init_global(logger) }
C::init_global(logger); // TODO: Is this safe?
// NOTE: The raw pointer is implicit (now that we're leaked)
CollectorRef {}
CollectorRef { _marker: PhantomData }
}

#[cfg(feature = "multiple-collectors")]
Expand All @@ -262,7 +283,7 @@ impl<C: RawCollectorImpl> CollectorRef<C> {
}
#[cfg(not(feature = "multiple-collectors"))]
pub(crate) fn clone_internal(&self) -> CollectorRef<C> {
CollectorRef {}
CollectorRef { _marker: PhantomData }
}
#[cfg(feature = "multiple-collectors")]
#[inline]
Expand All @@ -272,7 +293,7 @@ impl<C: RawCollectorImpl> CollectorRef<C> {
#[cfg(not(feature = "multiple-collectors"))]
#[inline]
pub fn as_raw(&self) -> &C {
let ptr = GLOBAL_COLLECTOR.load(Ordering::Acquire);
let ptr = C::global_ptr();
assert!(!ptr.is_null());
unsafe { &*ptr }
}
Expand Down
7 changes: 2 additions & 5 deletions libs/context/src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};

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

const INITIAL_HANDLE_CAPACITY: usize = 64;
Expand Down Expand Up @@ -391,7 +387,8 @@ unsafe impl<T: GcSafe, C: RawHandleImpl> ::zerogc::GcHandle<T> for GcHandle<T, C
#[cfg(feature = "sync")]
fn use_critical<R>(&self, func: impl FnOnce(&T) -> R) -> R {
self.collector.ensure_valid(|collector| unsafe {

// Used for 'prevent_collection' method
use crate::SyncCollectorImpl;
/*
* This should be sufficient to ensure
* the value won't be collected or relocated.
Expand Down
4 changes: 4 additions & 0 deletions libs/context/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![feature(
negative_impls, // !Send is much cleaner than `PhantomData<Rc>`
untagged_unions, // I want to avoid ManuallyDrop in unions
const_fn, // Apparently this feature is unstable???
)]
//! The implementation of [::zerogc::CollectorContext] that is
//! shared among both thread-safe and thread-unsafe code.
Expand All @@ -23,7 +24,10 @@ pub mod collector;
pub mod handle;

use crate::collector::{RawCollectorImpl};
#[cfg(feature = "sync")]
use crate::sync::SyncCollectorImpl;
#[cfg(not(feature = "sync"))]
use crate::nosync::NoSyncCollectorImpl;

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

Expand Down
Loading

0 comments on commit 1d3f95c

Please sign in to comment.