Skip to content

Commit d6b410e

Browse files
committed
Make ::zerogc::Gc a struct replacing GcRef trait
This more-specific struct simplifies things. Now, collector-specific data is associated behind a '::zerogc::CollectorId' For collectors with multiple instances, this should be a pointer. However for singleton collectors it can simply be a ZST. See issue #5
1 parent b72b708 commit d6b410e

File tree

11 files changed

+525
-351
lines changed

11 files changed

+525
-351
lines changed

libs/derive/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,9 @@ fn impl_extras(target: &DeriveInput) -> Result<TokenStream, Error> {
224224
let barrier = quote_spanned!(field.span() => ::zerogc::GcDirectBarrier::write_barrier(&value, &self, offset));
225225
extra_items.push(quote! {
226226
#[inline] // TODO: Implement `GcDirectBarrier` ourselves
227-
#mutator_vis fn #mutator_name<OwningRef>(self: OwningRef, value: #value_ref_type)
228-
where OwningRef: ::zerogc::GcRef<'gc, Self>,
229-
#value_ref_type: ::zerogc::GcDirectBarrier<'gc, OwningRef> {
227+
#mutator_vis fn #mutator_name<Id>(self: ::zerogc::Gc<'gc, Self, Id>, value: #value_ref_type)
228+
where Id: ::zerogc::CollectorId,
229+
#value_ref_type: ::zerogc::GcDirectBarrier<'gc, ::zerogc::Gc<'gc, Self, Id>> {
230230
unsafe {
231231
let target_ptr = #field_as_ptr;
232232
let offset = target_ptr as usize - self.as_raw_ptr() as usize;
@@ -306,7 +306,7 @@ fn impl_brand(target: &DeriveInput) -> Result<TokenStream, Error> {
306306
}
307307
let mut impl_generics = generics.clone();
308308
impl_generics.params.push(GenericParam::Lifetime(parse_quote!('new_gc)));
309-
impl_generics.params.push(GenericParam::Type(parse_quote!(S: ::zerogc::GcSystem)));
309+
impl_generics.params.push(GenericParam::Type(parse_quote!(S: ::zerogc::CollectorId)));
310310
let (_, ty_generics, where_clause) = generics.split_for_impl();
311311
let (impl_generics, _, _) = impl_generics.split_for_impl();
312312
Ok(quote! {

libs/simple/src/context/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use zerogc::prelude::*;
1414
use super::{SimpleCollector, RawSimpleCollector, DynTrace};
1515
use std::mem::ManuallyDrop;
1616
use std::ptr::NonNull;
17+
use crate::CollectorId;
1718

1819

1920
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -156,6 +157,7 @@ impl Drop for SimpleCollectorContext {
156157
}
157158
unsafe impl GcContext for SimpleCollectorContext {
158159
type System = SimpleCollector;
160+
type Id = CollectorId;
159161

160162
#[inline]
161163
unsafe fn basic_safepoint<T: Trace>(&mut self, value: &mut &mut T) {

libs/simple/src/context/simple.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
//!
44
//! In exchange, there is no locking :)
55
6-
use std::sync::{Arc};
76
use std::cell::{Cell, UnsafeCell, RefCell};
87

98
use slog::{Logger, FnValue, trace, o};

libs/simple/src/handles.rs

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use std::ptr::NonNull;
55
use std::marker::PhantomData;
66
use std::sync::atomic::{self, AtomicPtr, AtomicUsize, Ordering};
77

8-
use zerogc::{Trace, GcSafe, GcBindHandle, GcBrand, GcVisitor, NullTrace, TraceImmutable};
9-
use crate::{DynTrace, GcType, Gc, SimpleCollectorContext, SimpleCollector, MarkVisitor, GcHeader, MarkState, WeakCollectorRef};
8+
use zerogc::{Trace, GcSafe, GcBrand, GcVisitor, NullTrace, TraceImmutable, GcHandleSystem, GcBindHandle};
9+
use crate::{DynTrace, GcType, Gc, SimpleCollector, MarkVisitor, GcHeader, MarkState, WeakCollectorRef, CollectorId, SimpleCollectorContext, RawSimpleCollector};
1010

1111
const INITIAL_HANDLE_CAPACITY: usize = 128;
1212

@@ -370,7 +370,9 @@ impl<T: GcSafe> GcHandle<T> {
370370
}
371371
}
372372
unsafe impl<T: GcSafe> ::zerogc::GcHandle<T> for GcHandle<T> {
373-
type Context = SimpleCollectorContext;
373+
type System = SimpleCollector;
374+
type Id = CollectorId;
375+
374376
#[cfg(feature = "sync")]
375377
fn use_critical<R>(&self, func: impl FnOnce(&T) -> R) -> R {
376378
self.collector.ensure_valid(|collector| unsafe {
@@ -396,12 +398,10 @@ unsafe impl<T: GcSafe> ::zerogc::GcHandle<T> for GcHandle<T> {
396398
}
397399
}
398400
unsafe impl<'new_gc, T> GcBindHandle<'new_gc, T> for GcHandle<T>
399-
where T: GcSafe, T: GcBrand<'new_gc, SimpleCollector>,
401+
where T: GcSafe, T: GcBrand<'new_gc, CollectorId>,
400402
T::Branded: GcSafe {
401-
type System = SimpleCollector;
402-
type Bound = Gc<'new_gc, T::Branded>;
403403
#[inline]
404-
fn bind_to(&self, _context: &'new_gc Self::Context) -> Self::Bound {
404+
fn bind_to(&self, context: &'new_gc SimpleCollectorContext) -> Gc<'new_gc, T::Branded> {
405405
/*
406406
* We can safely assume the object will
407407
* be as valid as long as the context.
@@ -417,6 +417,11 @@ unsafe impl<'new_gc, T> GcBindHandle<'new_gc, T> for GcHandle<T>
417417
*/
418418
unsafe {
419419
let collector = self.collector.assume_valid();
420+
assert_eq!(
421+
collector.as_ref() as *const RawSimpleCollector,
422+
context.collector() as *const RawSimpleCollector,
423+
"Collectors mismatch"
424+
);
420425
let inner = self.inner.as_ref();
421426
let value = inner.value.load(Ordering::Acquire)
422427
as *mut T as *mut T::Branded;
@@ -529,4 +534,38 @@ unsafe impl<T: GcSafe + Sync> Send for GcHandle<T> {}
529534
/// it's safe to share garbage collected references between threads.
530535
///
531536
/// The collector itself is always safe
532-
unsafe impl<T: GcSafe + Sync> Sync for GcHandle<T> {}
537+
unsafe impl<T: GcSafe + Sync> Sync for GcHandle<T> {}
538+
539+
/// We support handles
540+
unsafe impl<'gc, T> GcHandleSystem<'gc, T> for SimpleCollector
541+
where T: GcSafe + 'gc,
542+
T: GcBrand<'static, CollectorId>,
543+
T::Branded: GcSafe {
544+
type Handle = GcHandle<T::Branded>;
545+
#[inline]
546+
fn create_handle(gc: Gc<'gc, T>) -> Self::Handle {
547+
use crate::StaticGcType;
548+
unsafe {
549+
let collector = gc.collector_id();
550+
let value = gc.as_raw_ptr();
551+
let raw = collector.as_ref().handle_list
552+
.alloc_raw_handle(value as *mut ());
553+
/*
554+
* WARN: Undefined Behavior
555+
* if we don't finish initializing
556+
* the handle!!!
557+
*
558+
* TODO: Encapsulate
559+
*/
560+
raw.type_info.store(
561+
<T as StaticGcType>::STATIC_TYPE
562+
as *const GcType
563+
as *mut GcType,
564+
Ordering::Release
565+
);
566+
raw.refcnt.store(1, Ordering::Release);
567+
let weak_collector = collector.weak_ref();
568+
GcHandle::new(NonNull::from(raw), weak_collector)
569+
}
570+
}
571+
}

0 commit comments

Comments
 (0)