Skip to content

Commit e1860ae

Browse files
committed
Add no_std and no_alloc support
1 parent 6c0caa0 commit e1860ae

File tree

9 files changed

+348
-211
lines changed

9 files changed

+348
-211
lines changed

Cargo.toml

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ categories = ["caching", "memory-management", "concurrency"]
1313
keywords = ["hash", "interning", "hashconsing", "caching", "interner"]
1414
rust-version = "1.70"
1515

16+
# Ensures dev-dependencies to enable features on standard dependencies unless compiling examples,
17+
# tests, etc.
18+
resolver = "2"
19+
1620
[badges]
1721

1822
appveyor = { repository = "droundy/internment" }
@@ -31,25 +35,33 @@ once_cell = { version = "1.4", optional = true }
3135
tinyset = { version = "0.4.2", optional = true }
3236
memorable-wordlist = { version = "0.1.7", optional = true }
3337
hashbrown = { version = "0.15.0" }
34-
serde = { version = "1.0", optional = true }
35-
deepsize = { version = "0.2.0", optional = true }
38+
serde = { version = "1.0", optional = true, default-features = false }
39+
deepsize = { version = "0.2.0", optional = true, default-features = false }
3640

3741
arc-interner = { version = "0.7", optional = true }
3842

3943
append-only-vec = { version = "0.1.2", optional = true }
4044

45+
spin = { version = "0.9.8", default-features = false, optional = true, features = [
46+
"spin_mutex",
47+
] }
48+
portable-atomic = { version = "1", default-features = false, optional = true }
4149

4250
[features]
4351

44-
arc = ["dep:ahash", "dep:dashmap", "dep:once_cell"]
52+
arc = ["std", "dep:ahash", "dep:dashmap", "dep:once_cell"]
4553
bench = ["arc", "arena", "_experimental-new-intern", "dep:memorable-wordlist"]
46-
arena = []
47-
intern = []
48-
default = ["intern"]
49-
_experimental-new-intern = ["dep:append-only-vec"]
54+
arena = ["alloc"]
55+
intern = ["alloc"]
56+
default = ["intern", "std"]
57+
_experimental-new-intern = ["alloc", "dep:append-only-vec"]
58+
std = ["alloc"]
59+
alloc = ["serde?/alloc"]
60+
tinyset = ["std", "dep:tinyset"]
61+
portable-atomic = ["dep:portable-atomic", "spin?/portable_atomic"]
62+
critical-section = ["portable-atomic?/critical-section"]
5063

5164
[dev-dependencies]
52-
quickcheck = "^0.9.2"
5365
scaling = "0.1.3"
5466
rand = "0.7.2"
5567
serde_json = "1.0.87"

src/arc.rs

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
#![deny(missing_docs)]
22
use ahash::RandomState;
3-
use std::any::{Any, TypeId};
4-
use std::fmt::{Debug, Display, Pointer};
5-
type Container<T> = DashMap<BoxRefCount<T>, (), RandomState>;
6-
type Untyped = &'static (dyn Any + Send + Sync + 'static);
7-
use std::borrow::Borrow;
8-
use std::convert::AsRef;
9-
use std::ffi::OsStr;
10-
use std::hash::{Hash, Hasher};
11-
use std::ops::Deref;
12-
use std::path::Path;
13-
use std::sync::atomic::AtomicUsize;
14-
use std::sync::atomic::Ordering;
15-
3+
use alloc::{boxed::Box, string::String};
4+
use core::{
5+
any::{Any, TypeId},
6+
borrow::Borrow,
7+
convert::AsRef,
8+
fmt::{Debug, Display, Pointer},
9+
hash::{Hash, Hasher},
10+
ops::Deref,
11+
sync::atomic::{AtomicUsize, Ordering},
12+
};
1613
use dashmap::{mapref::entry::Entry, DashMap};
1714

15+
#[cfg(feature = "std")]
16+
use std::{ffi::OsStr, path::Path};
17+
18+
#[cfg(test)]
19+
use alloc::{string::ToString, vec};
20+
1821
#[cfg(feature = "serde")]
1922
use serde::{Deserialize, Deserializer, Serialize, Serializer};
2023

24+
type Container<T> = DashMap<BoxRefCount<T>, (), RandomState>;
25+
type Untyped = &'static (dyn Any + Send + Sync + 'static);
26+
2127
/// A pointer to a reference-counted interned object.
2228
///
2329
/// This type requires feature "arc". The interned object will be held in memory only until its
@@ -46,7 +52,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
4652
/// ```
4753
#[cfg_attr(docsrs, doc(cfg(feature = "arc")))]
4854
pub struct ArcIntern<T: ?Sized + Eq + Hash + Send + Sync + 'static> {
49-
pub(crate) pointer: std::ptr::NonNull<RefCount<T>>,
55+
pub(crate) pointer: core::ptr::NonNull<RefCount<T>>,
5056
}
5157

5258
#[cfg(feature = "deepsize")]
@@ -64,10 +70,10 @@ pub fn deep_size_of_arc_interned<
6470
T: ?Sized + Eq + Hash + Send + Sync + 'static + deepsize::DeepSizeOf,
6571
>() -> usize {
6672
let x = ArcIntern::<T>::get_container();
67-
let pointers = x.capacity() * std::mem::size_of::<BoxRefCount<T>>();
73+
let pointers = x.capacity() * core::mem::size_of::<BoxRefCount<T>>();
6874
let heap_memory = x
6975
.iter()
70-
.map(|n| std::mem::size_of::<usize>() + n.key().0.data.deep_size_of())
76+
.map(|n| core::mem::size_of::<usize>() + n.key().0.data.deep_size_of())
7177
.sum::<usize>();
7278
pointers + heap_memory
7379
}
@@ -226,7 +232,7 @@ impl<T: Eq + Hash + Send + Sync + 'static> ArcIntern<T> {
226232
if oldval != 0 {
227233
// we can only use this value if the value is not about to be freed
228234
return ArcIntern {
229-
pointer: std::ptr::NonNull::from(b.0.borrow()),
235+
pointer: core::ptr::NonNull::from(b.0.borrow()),
230236
};
231237
} else {
232238
// we have encountered a race condition here.
@@ -243,7 +249,7 @@ impl<T: Eq + Hash + Send + Sync + 'static> ArcIntern<T> {
243249
Entry::Vacant(e) => {
244250
// We can insert, all is good
245251
let p = ArcIntern {
246-
pointer: std::ptr::NonNull::from(e.key().0.borrow()),
252+
pointer: core::ptr::NonNull::from(e.key().0.borrow()),
247253
};
248254
e.insert(());
249255
return p;
@@ -257,6 +263,7 @@ impl<T: Eq + Hash + Send + Sync + 'static> ArcIntern<T> {
257263
}
258264
// yield so that the object can finish being freed,
259265
// and then we will be able to intern a new copy.
266+
#[cfg(feature = "std")]
260267
std::thread::yield_now();
261268
}
262269
}
@@ -304,7 +311,7 @@ impl<T: ?Sized + Eq + Hash + Send + Sync> Drop for ArcIntern<T> {
304311
// happens before decreasing the reference count, which
305312
// happens before this fence, which happens before the
306313
// deletion of the data.
307-
std::sync::atomic::fence(Ordering::SeqCst);
314+
core::sync::atomic::fence(Ordering::SeqCst);
308315

309316
// removed is declared before m, so the mutex guard will be
310317
// dropped *before* the removed content is dropped, since it
@@ -324,6 +331,7 @@ impl<T: ?Sized + Send + Sync + Hash + Eq> AsRef<T> for ArcIntern<T> {
324331
}
325332
}
326333

334+
#[cfg_attr(not(feature = "std"), allow(unused_macros))]
327335
macro_rules! impl_as_ref {
328336
($from:ty => $to:ty) => {
329337
impl AsRef<$to> for ArcIntern<$from> {
@@ -336,9 +344,13 @@ macro_rules! impl_as_ref {
336344
};
337345
}
338346

347+
#[cfg(feature = "std")]
339348
impl_as_ref!(str => OsStr);
349+
#[cfg(feature = "std")]
340350
impl_as_ref!(str => Path);
351+
#[cfg(feature = "std")]
341352
impl_as_ref!(OsStr => Path);
353+
#[cfg(feature = "std")]
342354
impl_as_ref!(Path => OsStr);
343355

344356
impl<T: ?Sized + Eq + Hash + Send + Sync> Deref for ArcIntern<T> {
@@ -351,14 +363,14 @@ impl<T: ?Sized + Eq + Hash + Send + Sync> Deref for ArcIntern<T> {
351363

352364
impl<T: ?Sized + Eq + Hash + Send + Sync + Display> Display for ArcIntern<T> {
353365
#[inline]
354-
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
366+
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
355367
self.deref().fmt(f)
356368
}
357369
}
358370

359371
impl<T: ?Sized + Eq + Hash + Send + Sync> Pointer for ArcIntern<T> {
360372
#[inline]
361-
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
373+
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
362374
Pointer::fmt(&self.get_pointer(), f)
363375
}
364376
}
@@ -378,14 +390,14 @@ impl<T: ?Sized + Eq + Hash + Send + Sync> Hash for ArcIntern<T> {
378390
impl<T: ?Sized + Eq + Hash + Send + Sync> PartialEq for ArcIntern<T> {
379391
#[inline(always)]
380392
fn eq(&self, other: &Self) -> bool {
381-
std::ptr::eq(self.get_pointer(), other.get_pointer())
393+
core::ptr::eq(self.get_pointer(), other.get_pointer())
382394
}
383395
}
384396
impl<T: ?Sized + Eq + Hash + Send + Sync> Eq for ArcIntern<T> {}
385397

386398
impl<T: ?Sized + Eq + Hash + Send + Sync + PartialOrd> PartialOrd for ArcIntern<T> {
387399
#[inline]
388-
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
400+
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
389401
self.as_ref().partial_cmp(other)
390402
}
391403
#[inline]
@@ -407,7 +419,7 @@ impl<T: ?Sized + Eq + Hash + Send + Sync + PartialOrd> PartialOrd for ArcIntern<
407419
}
408420
impl<T: ?Sized + Eq + Hash + Send + Sync + Ord> Ord for ArcIntern<T> {
409421
#[inline]
410-
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
422+
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
411423
self.as_ref().cmp(other)
412424
}
413425
}
@@ -450,7 +462,11 @@ where
450462
#[cfg(test)]
451463
mod arc_test {
452464
use super::ArcIntern;
453-
use super::{Borrow, Deref};
465+
use alloc::string::String;
466+
use core::borrow::Borrow;
467+
use core::ops::Deref;
468+
use std::println;
469+
454470
#[test]
455471
fn eq_string() {
456472
assert_eq!(ArcIntern::new("hello"), ArcIntern::new("hello"));
@@ -532,14 +548,14 @@ fn test_arcintern_nested_drop() {
532548
}
533549

534550
impl<T: ?Sized + Eq + Hash + Send + Sync + Debug> Debug for ArcIntern<T> {
535-
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
551+
fn fmt(&self, f: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
536552
self.deref().fmt(f)
537553
}
538554
}
539555

540556
#[cfg(test)]
541557
#[derive(Eq, PartialEq, Hash)]
542-
pub struct TestStructCount(String, u64, std::sync::Arc<bool>);
558+
pub struct TestStructCount(String, u64, alloc::sync::Arc<bool>);
543559

544560
#[cfg(test)]
545561
#[derive(Eq, PartialEq, Hash)]
@@ -549,7 +565,7 @@ pub struct TestStruct(String, u64);
549565
// multiple threads.
550566
#[test]
551567
fn multithreading1() {
552-
use std::sync::Arc;
568+
use alloc::sync::Arc;
553569
use std::thread;
554570
let mut thandles = vec![];
555571
let drop_check = Arc::new(true);
@@ -576,12 +592,12 @@ fn multithreading1() {
576592
#[test]
577593
fn arc_has_niche() {
578594
assert_eq!(
579-
std::mem::size_of::<ArcIntern<String>>(),
580-
std::mem::size_of::<usize>(),
595+
core::mem::size_of::<ArcIntern<String>>(),
596+
core::mem::size_of::<usize>(),
581597
);
582598
assert_eq!(
583-
std::mem::size_of::<Option<ArcIntern<String>>>(),
584-
std::mem::size_of::<usize>(),
599+
core::mem::size_of::<Option<ArcIntern<String>>>(),
600+
core::mem::size_of::<usize>(),
585601
);
586602
}
587603

@@ -617,7 +633,7 @@ fn test_shrink_to_fit() {
617633
struct Value(usize);
618634
assert_eq!(0, ArcIntern::<Value>::get_container().capacity());
619635
{
620-
let v = ArcIntern::new(Value(0));
636+
let _v = ArcIntern::new(Value(0));
621637
assert!(ArcIntern::<Value>::get_container().capacity() >= 1);
622638
ArcIntern::<Value>::shrink_to_fit();
623639
assert!(ArcIntern::<Value>::get_container().capacity() >= 1);

0 commit comments

Comments
 (0)