Skip to content

Commit def2eea

Browse files
committed
Add refs API
1 parent 239fe51 commit def2eea

File tree

11 files changed

+79
-31
lines changed

11 files changed

+79
-31
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
- Add discard states tracker and `discarded` method to let users know how many bytes in ARENA are discarded.
1010
- Rename `OccupiedValue` to `VacantBuffer` and do not panic when users do not fully fill `VacantBuffer`
1111
- Add `tracing`
12+
- Add `SkipMap::refs` API to allow users get how many references.
1213

1314
## 0.9.0
1415

examples/heap.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub fn new_value(i: usize) -> Vec<u8> {
1111

1212
fn main() {
1313
const N: usize = 1000;
14-
let l = Arc::new(SkipMap::new(1 << 20).unwrap());
14+
let l = SkipMap::new(1 << 20).unwrap();
1515
let wg = Arc::new(());
1616
for i in 0..N {
1717
let w = wg.clone();

examples/mmap.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn main() {
1717
.read(true)
1818
.write(true);
1919

20-
let l = Arc::new(SkipMap::mmap_mut("test.wal", open_options, mmap_options).unwrap());
20+
let l = SkipMap::mmap_mut("test.wal", open_options, mmap_options).unwrap();
2121
let wg = Arc::new(());
2222
for i in 0..N {
2323
let w = wg.clone();

examples/mmap_anon.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ fn main() {
1313
const N: usize = 1000;
1414

1515
let mmap_options = skl::MmapOptions::default().len(1 << 20);
16-
let l = Arc::new(SkipMap::mmap_anon(mmap_options).unwrap());
16+
let l = SkipMap::mmap_anon(mmap_options).unwrap();
1717
let wg = Arc::new(());
1818
for i in 0..N {
1919
let w = wg.clone();

integration/src/bin/test-mmap-anon.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
use integration::{big_value, key, new_value};
22
use skl::*;
3-
use std::sync::Arc;
43

54
fn main() {
65
{
76
const N: usize = 10;
87

98
let mmap_options = MmapOptions::default().len(1 << 20);
10-
let l = Arc::new(SkipMap::mmap_anon(mmap_options).unwrap());
9+
let l = SkipMap::mmap_anon(mmap_options).unwrap();
1110
for i in 0..N {
1211
let l = l.clone();
1312
std::thread::spawn(move || {
1413
l.insert(0, &key(i), &new_value(i)).unwrap();
1514
drop(l);
1615
});
1716
}
18-
while Arc::strong_count(&l) > 1 {}
17+
while l.refs() > 1 {
18+
core::hint::spin_loop();
19+
}
1920
for i in 0..N {
2021
let l = l.clone();
2122
std::thread::spawn(move || {
@@ -24,21 +25,25 @@ fn main() {
2425
drop(l);
2526
});
2627
}
27-
while Arc::strong_count(&l) > 1 {}
28+
while l.refs() > 1 {
29+
core::hint::spin_loop();
30+
}
2831
}
2932

3033
{
3134
const N2: usize = 100;
3235

3336
let mmap_options = MmapOptions::default().len(120 << 20);
34-
let l = Arc::new(SkipMap::mmap_anon(mmap_options).unwrap());
37+
let l = SkipMap::mmap_anon(mmap_options).unwrap();
3538
for i in 0..N2 {
3639
let l = l.clone();
3740
std::thread::spawn(move || {
3841
l.insert(0, &key(i), &big_value(i)).unwrap();
3942
});
4043
}
41-
while Arc::strong_count(&l) > 1 {}
44+
while l.refs() > 1 {
45+
core::hint::spin_loop();
46+
}
4247
assert_eq!(N2, l.len());
4348
for i in 0..N2 {
4449
let l = l.clone();
@@ -47,6 +52,8 @@ fn main() {
4752
assert_eq!(l.get(0, &k).unwrap().value(), big_value(i), "broken: {i}");
4853
});
4954
}
50-
while Arc::strong_count(&l) > 1 {}
55+
while l.refs() > 1 {
56+
core::hint::spin_loop();
57+
}
5158
}
5259
}

integration/src/bin/test-mmap.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use integration::{key, new_value};
22
use skl::*;
3-
use std::sync::Arc;
43

54
fn main() {
65
let dir = tempfile::tempdir().unwrap();
@@ -13,15 +12,17 @@ fn main() {
1312
.read(true)
1413
.write(true);
1514
let mmap_options = MmapOptions::default();
16-
let l = Arc::new(SkipMap::mmap_mut(&p, open_options, mmap_options).unwrap());
15+
let l = SkipMap::mmap_mut(&p, open_options, mmap_options).unwrap();
1716
for i in 0..N {
1817
let l = l.clone();
1918
std::thread::spawn(move || {
2019
l.insert(0, &key(i), &new_value(i)).unwrap();
2120
drop(l);
2221
});
2322
}
24-
while Arc::strong_count(&l) > 1 {}
23+
while l.refs() > 1 {
24+
core::hint::spin_loop();
25+
}
2526
for i in 0..N {
2627
let l = l.clone();
2728
std::thread::spawn(move || {
@@ -30,15 +31,17 @@ fn main() {
3031
drop(l);
3132
});
3233
}
33-
while Arc::strong_count(&l) > 1 {}
34+
while l.refs() > 1 {
35+
core::hint::spin_loop();
36+
}
3437
}
3538

3639
{
3740
const N2: usize = 10;
3841

3942
let open_options = OpenOptions::default().read(true);
4043
let mmap_options = MmapOptions::default();
41-
let l = Arc::new(SkipMap::<u64>::mmap(&p, open_options, mmap_options).unwrap());
44+
let l = SkipMap::<u64>::mmap(&p, open_options, mmap_options).unwrap();
4245
assert_eq!(N2, l.len());
4346
for i in 0..N2 {
4447
let l = l.clone();
@@ -47,6 +50,8 @@ fn main() {
4750
assert_eq!(l.get(0, &k).unwrap().value(), new_value(i), "broken: {i}");
4851
});
4952
}
50-
while Arc::strong_count(&l) > 1 {}
53+
while l.refs() > 1 {
54+
core::hint::spin_loop();
55+
}
5156
}
5257
}

integration/src/bin/test-vec.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
use integration::{big_value, key, new_value};
22
use skl::*;
3-
use std::sync::Arc;
43

54
fn main() {
65
{
76
const N: usize = 10;
8-
let l = Arc::new(SkipMap::new(1 << 20).unwrap());
7+
let l = SkipMap::new(1 << 20).unwrap();
98
for i in 0..N {
109
let l = l.clone();
1110
std::thread::spawn(move || {
1211
l.insert(0, &key(i), &new_value(i)).unwrap();
1312
drop(l);
1413
});
1514
}
16-
while Arc::strong_count(&l) > 1 {}
15+
while l.refs() > 1 {
16+
core::hint::spin_loop();
17+
}
1718
for i in 0..N {
1819
let l = l.clone();
1920
std::thread::spawn(move || {
@@ -22,19 +23,23 @@ fn main() {
2223
drop(l);
2324
});
2425
}
25-
while Arc::strong_count(&l) > 1 {}
26+
while l.refs() > 1 {
27+
core::hint::spin_loop();
28+
}
2629
}
2730

2831
{
2932
const N2: usize = 10;
30-
let l = Arc::new(SkipMap::new(120 << 20).unwrap());
33+
let l = SkipMap::new(120 << 20).unwrap();
3134
for i in 0..N2 {
3235
let l = l.clone();
3336
std::thread::spawn(move || {
3437
l.insert(0, &key(i), &big_value(i)).unwrap();
3538
});
3639
}
37-
while Arc::strong_count(&l) > 1 {}
40+
while l.refs() > 1 {
41+
core::hint::spin_loop();
42+
}
3843
assert_eq!(N2, l.len());
3944
for i in 0..N2 {
4045
let l = l.clone();
@@ -43,6 +48,8 @@ fn main() {
4348
assert_eq!(l.get(0, &k).unwrap().value(), big_value(i), "broken: {i}");
4449
});
4550
}
46-
while Arc::strong_count(&l) > 1 {}
51+
while l.refs() > 1 {
52+
core::hint::spin_loop();
53+
}
4754
}
4855
}

src/arena.rs

+9
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,15 @@ impl Arena {
188188
self.header().min_version.load(Ordering::Acquire)
189189
}
190190

191+
#[inline]
192+
pub fn refs(&self) -> usize {
193+
unsafe {
194+
let shared: *mut Shared = self.inner.load(Ordering::Relaxed).cast();
195+
196+
(*shared).refs.load(Ordering::Acquire)
197+
}
198+
}
199+
191200
#[inline]
192201
pub(super) const fn atomic_height(&self) -> &AtomicU32 {
193202
&self.header().height

src/arena/shared.rs

+16-3
Original file line numberDiff line numberDiff line change
@@ -153,15 +153,20 @@ impl Shared {
153153
min_cap: usize,
154154
alignment: usize,
155155
) -> std::io::Result<Self> {
156-
let file = open_options.open(path.as_ref())?;
156+
let (create_new, file) = open_options.open(path.as_ref())?;
157157

158158
unsafe {
159-
mmap_options.map_mut(&file).and_then(|mmap| {
159+
mmap_options.map_mut(&file).and_then(|mut mmap| {
160160
let cap = mmap.len();
161161
if cap < min_cap {
162162
return Err(invalid_data(TooSmall::new(cap, min_cap)));
163163
}
164164

165+
if create_new {
166+
// initialize the memory with 0
167+
ptr::write_bytes(mmap.as_mut_ptr(), 0, cap);
168+
}
169+
165170
let data_offset = data_offset(alignment);
166171
let this = Self {
167172
cap,
@@ -190,7 +195,15 @@ impl Shared {
190195
min_cap: usize,
191196
alignment: usize,
192197
) -> std::io::Result<Self> {
193-
let file = open_options.open(path.as_ref())?;
198+
if !path.as_ref().exists() {
199+
return Err(std::io::Error::new(
200+
std::io::ErrorKind::NotFound,
201+
"file not found",
202+
));
203+
}
204+
205+
let (_, file) = open_options.open(path.as_ref())?;
206+
194207
unsafe {
195208
mmap_options.map(&file).and_then(|mmap| {
196209
let len = mmap.len();

src/map/api.rs

+6
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ impl<T, C> SkipMap<T, C> {
3838
self.len() == 0
3939
}
4040

41+
/// Gets the number of pointers to this `SkipMap` similar to [`Arc::strong_count`](std::sync::Arc::strong_count).
42+
#[inline]
43+
pub fn refs(&self) -> usize {
44+
self.arena.refs()
45+
}
46+
4147
/// Returns how many bytes are discarded by the ARENA.
4248
#[inline]
4349
pub fn discarded(&self) -> usize {

src/options.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl OpenOptions {
315315
self
316316
}
317317

318-
pub(crate) fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<File> {
318+
pub(crate) fn open<P: AsRef<Path>>(&self, path: P) -> io::Result<(bool, File)> {
319319
if let Some(size) = self.create_new {
320320
return self.opts.open(path).and_then(|f| {
321321
if self.lock_exclusive {
@@ -324,7 +324,7 @@ impl OpenOptions {
324324
f.lock_shared()?;
325325
}
326326

327-
f.set_len(size).map(|_| f)
327+
f.set_len(size).map(|_| (true, f))
328328
});
329329
}
330330

@@ -336,7 +336,7 @@ impl OpenOptions {
336336
} else if self.lock_shared {
337337
f.lock_shared()?;
338338
}
339-
Ok(f)
339+
Ok((false, f))
340340
})
341341
} else {
342342
self.opts.open(path).and_then(|f| {
@@ -346,7 +346,7 @@ impl OpenOptions {
346346
f.lock_shared()?;
347347
}
348348

349-
f.set_len(size).map(|_| f)
349+
f.set_len(size).map(|_| (true, f))
350350
})
351351
};
352352
}
@@ -357,7 +357,7 @@ impl OpenOptions {
357357
} else if self.lock_shared {
358358
f.lock_shared()?;
359359
}
360-
Ok(f)
360+
Ok((false, f))
361361
})
362362
}
363363

0 commit comments

Comments
 (0)