Skip to content

Commit

Permalink
feat: add threading primitives with feature toggle (#263)
Browse files Browse the repository at this point in the history
If the `threading` feature is set, the `threading` module will contain thread-safe primitives
for shared ownership and mutation, otherwise these will be their single threaded counterparts.

This way, single-threaded applications don't have to pay for threaded primitives.
  • Loading branch information
Byron committed Nov 26, 2021
1 parent db1bb99 commit 7e95d8a
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 1 deletion.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ gitoxide-core-tools = ["gitoxide-core/organize", "gitoxide-core/estimate-hours"]
gitoxide-core-blocking-client = ["gitoxide-core/blocking-client"]
gitoxide-core-async-client = ["gitoxide-core/async-client", "futures-lite"]
http-client-curl = ["git-transport-for-configuration-only/http-client-curl"]
fast = ["git-features/parallel", "git-features/fast-sha1", "git-features/zlib-ng-compat"]
fast = ["git-features/threading", "git-features/parallel", "git-features/fast-sha1", "git-features/zlib-ng-compat"]

pretty-cli = ["clap",
"gitoxide-core/serde1",
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ check: ## Build all code in suitable configurations
&& cargo check
cd git-features && cargo check --all-features \
&& cargo check --features parallel \
&& cargo check --features threading \
&& cargo check --features rustsha1 \
&& cargo check --features fast-sha1 \
&& cargo check --features progress \
Expand Down
3 changes: 3 additions & 0 deletions cargo-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ All feature toggles are additive.
* Use scoped threads and channels to parallelize common workloads on multiple objects. If enabled, it is used everywhere
where it makes sense.
* As caches are likely to be used and instantiated per thread, more memory will be used on top of the costs for threads.
* **threading**
* If set, the `threading` module will contain thread-safe primitives for shared ownership and mutation, otherwise these will be their single threaded counterparts.
* This way, single-threaded applications don't have to pay for threaded primitives.
* **crc32**
* provide a proven and fast `crc32` implementation.
* **io-pipe**
Expand Down
5 changes: 5 additions & 0 deletions git-features/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ test = false

[features]
default = []
threading = ["parking_lot"]
progress = ["prodash"]
parallel = ["crossbeam-utils", "crossbeam-channel", "num_cpus", "jwalk"]
fast-sha1 = ["sha-1"]
Expand Down Expand Up @@ -51,6 +52,10 @@ required-features = ["io-pipe"]
[dependencies]
git-hash = { version ="^0.8.0", path = "../git-hash" }


# 'threading' feature
parking_lot = { version = "0.11.0", default-features = false, optional = true }

# 'parallel' feature
crossbeam-utils = { version = "0.8.5", optional = true }
crossbeam-channel = { version = "0.5.0", optional = true }
Expand Down
1 change: 1 addition & 0 deletions git-features/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod io;
pub mod parallel;
#[cfg(feature = "progress")]
pub mod progress;
pub mod threading;
///
#[cfg(feature = "zlib")]
pub mod zlib;
Expand Down
74 changes: 74 additions & 0 deletions git-features/src/threading.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
//! Type definitions for putting shared ownership and synchronized mutation behind the `threading` feature toggle.
//!
//! That way, single-threaded applications will not have to use thread-safe primitives, and simply do not specify the 'threading' feature.

#[cfg(feature = "threading")]
mod _impl {
use std::sync::Arc;

/// A reference counted pointer type for shared ownership.
pub type OwnShared<T> = Arc<T>;
/// A synchronization primitive which can start read-only and transition to support mutation.
pub type MutableOnDemand<T> = parking_lot::RwLock<T>;

/// Get an upgradable shared reference through a [`MutableOnDemand`] for read-only access.
///
/// This access can be upgraded using [`upgrade_ref_to_mut()`].
pub fn get_ref_upgradeable<T>(v: &MutableOnDemand<T>) -> parking_lot::RwLockUpgradableReadGuard<'_, T> {
v.upgradable_read()
}

/// Get a shared reference through a [`MutableOnDemand`] for read-only access.
pub fn get_ref<T>(v: &MutableOnDemand<T>) -> parking_lot::RwLockReadGuard<'_, T> {
v.read()
}

/// Get a mutable reference through a [`MutableOnDemand`] for read-write access.
pub fn get_mut<T>(v: &MutableOnDemand<T>) -> parking_lot::RwLockWriteGuard<'_, T> {
v.write()
}

/// Upgrade a handle previously obtained with [`get_ref_upgradeable()`] to support mutation.
pub fn upgrade_ref_to_mut<T>(
v: parking_lot::RwLockUpgradableReadGuard<'_, T>,
) -> parking_lot::RwLockWriteGuard<'_, T> {
parking_lot::RwLockUpgradableReadGuard::upgrade(v)
}
}

#[cfg(not(feature = "threading"))]
mod _impl {
use std::{
cell::{Ref, RefCell, RefMut},
rc::Rc,
};

/// A reference counted pointer type for shared ownership.
pub type OwnShared<T> = Rc<T>;
/// A synchronization primitive which can start read-only and transition to support mutation.
pub type MutableOnDemand<T> = RefCell<T>;

/// Get an upgradable shared reference through a [`MutableOnDemand`] for read-only access.
///
/// This access can be upgraded using [`upgrade_ref_to_mut()`].
pub fn get_ref_upgradeable<T>(v: &RefCell<T>) -> RefMut<'_, T> {
v.borrow_mut()
}

/// Get a shared reference through a [`MutableOnDemand`] for read-only access.
pub fn get_mut<T>(v: &RefCell<T>) -> RefMut<'_, T> {
v.borrow_mut()
}

/// Get a mutable reference through a [`MutableOnDemand`] for read-write access.
pub fn get_ref<T>(v: &RefCell<T>) -> Ref<'_, T> {
v.borrow()
}

/// Upgrade a handle previously obtained with [`get_ref_upgradeable()`] to support mutation.
pub fn upgrade_ref_to_mut<T>(v: RefMut<'_, T>) -> RefMut<'_, T> {
v
}
}

pub use _impl::*;

0 comments on commit 7e95d8a

Please sign in to comment.