Permalink
Browse files

Rename `conc::gc()` to `conc::try_gc()` and introduce `conc::gc()` fo…

…r forced, deterministic GCs.
  • Loading branch information...
ticki committed Jun 21, 2017
1 parent e261914 commit 73a4cec90db8dee6b6f3a23761182132a53b7781
Showing with 60 additions and 17 deletions.
  1. +10 −8 conc/src/atomic.rs
  2. +12 −5 conc/src/global.rs
  3. +38 −4 conc/src/lib.rs
View
@@ -411,10 +411,11 @@ mod tests {
assert!(opt.load(atomic::Ordering::Relaxed).is_none());
// To check that GC doesn't segfault or something.
::gc();
::gc();
::gc();
::gc();
let _ = ::try_gc();
let _ = ::try_gc();
let _ = ::try_gc();
let _ = ::try_gc();
let _ = ::try_gc();
}
#[test]
@@ -444,10 +445,11 @@ mod tests {
assert!(opt.load(atomic::Ordering::Relaxed).is_none());
// To check that GC doesn't segfault or something.
::gc();
::gc();
::gc();
::gc();
let _ = ::try_gc();
let _ = ::try_gc();
let _ = ::try_gc();
let _ = ::try_gc();
let _ = ::try_gc();
}
}
View
@@ -37,9 +37,10 @@ pub fn export_garbage(garbage: Vec<Garbage>) {
/// Attempt to garbage collect.
///
/// If another garbage collection is currently running, nothing will happen.
pub fn gc() {
STATE.try_gc();
/// If another garbage collection is currently running, the thread will do nothing, and `Err(())`
/// will be returned. Otherwise, it returns `Ok(())`.
pub fn try_gc() -> Result<(), ()> {
STATE.try_gc()
}
/// Tick the clock.
@@ -101,17 +102,23 @@ impl State {
/// Try to collect the garbage.
///
/// This will handle all of the messages in the channel and then attempt at collect the
/// garbage. If another thread is currently collecting garbage, it will be equivalent to NOP.
/// garbage. If another thread is currently collecting garbage, `Err(())` is returned,
/// otherwise it returns `Ok(())`.
///
/// Garbage collection works by scanning the hazards and dropping all the garbage which is not
/// currently active in the hazards.
fn try_gc(&self) {
fn try_gc(&self) -> Result<(), ()> {
// Lock the "garbo" (the part of the state needed to GC).
if let Ok(mut garbo) = self.garbo.try_lock() {
// Handle all the messages sent.
garbo.handle_all();
// Collect the garbage.
garbo.gc();
Ok(())
} else {
// Another thread is collecting.
Err(())
}
}
}
View
@@ -100,14 +100,18 @@ pub use guard::Guard;
use std::mem;
use garbage::Garbage;
/// Collect garbage.
/// Attempt to collect garbage.
///
/// This function does two things:
///
/// 1. Export garbage from current thread to the global queue.
/// 2. Collect all the garbage and run destructors on the unused items.
///
/// If another thread is currently doing 2., it will be skipped.
/// If another thread is currently doing 2., it will be skipped. This makes it different from
/// `conc::gc()`, which will block.
///
/// If 2. fails (that is, another thread is garbage collecting), `Err(())` is returned. Otherwise
/// `Ok(())` is returned.
///
/// # Use case
///
@@ -121,11 +125,41 @@ use garbage::Garbage;
///
/// This cannot collect un-propagated garbage accumulated locally in other threads. This will only
/// attempt to collect the accumulated local and global (propagated) garbage.
pub fn gc() {
pub fn try_gc() -> Result<(), ()> {
// Export the local garbage to ensure that the garbage of the current thread gets collected.
local::export_garbage();
// Run the global GC.
global::gc();
global::try_gc()
}
/// Collect garbage.
///
/// This function does two things:
///
/// 1. Export garbage from current thread to the global queue.
/// 2. Collect all the garbage and run destructors on the unused items.
///
/// If another thread is currently doing 2., it will block until it can be done. This makes it
/// different from `conc::try_gc()`, which will skip the step.
///
/// # Use case
///
/// This is really only neccesary in one case: If you want to ensure that all the destructors of
/// inactive hazards in the current thread are run. If the destructors hold some special logic, you
/// want to execute, this will force the (inactive) ones to run these destructors and thus execute
/// the logic.
///
/// If you just want to reduce memory usage, you will probably be better off with `conc::try_gc()`.
///
/// # Other threads
///
/// This cannot collect un-propagated garbage accumulated locally in other threads. This will only
/// collect the accumulated local and global (propagated) garbage.
pub fn gc() {
// Export the local garbage to ensure that the garbage of the current thread gets collected.
local::export_garbage();
// Try to garbage collect until it succeeds.
while let Err(()) = global::try_gc() {}
}
/// Declare a pointer unreachable garbage to be deleted eventually.

0 comments on commit 73a4cec

Please sign in to comment.