Skip to content

Commit 2ecf144

Browse files
committed
wip: Use Arc instead of Rc references, impl Send and/or Sync for types
1 parent d7adb08 commit 2ecf144

File tree

6 files changed

+78
-59
lines changed

6 files changed

+78
-59
lines changed

src/bam/mod.rs

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::path::Path;
2121
use std::rc::Rc;
2222
use std::slice;
2323
use std::str;
24+
use std::sync::Arc;
2425

2526
use url::Url;
2627

@@ -250,7 +251,7 @@ pub trait Read: Sized {
250251
#[derive(Debug)]
251252
pub struct Reader {
252253
htsfile: *mut htslib::htsFile,
253-
header: Rc<HeaderView>,
254+
header: Arc<HeaderView>,
254255
tpool: Option<ThreadPool>,
255256
}
256257

@@ -298,7 +299,7 @@ impl Reader {
298299

299300
Ok(Reader {
300301
htsfile,
301-
header: Rc::new(HeaderView::new(header)),
302+
header: Arc::new(HeaderView::new(header)),
302303
tpool: None,
303304
})
304305
}
@@ -383,7 +384,7 @@ impl Read for Reader {
383384
-2 => Some(Err(Error::BamTruncatedRecord)),
384385
-4 => Some(Err(Error::BamInvalidRecord)),
385386
_ => {
386-
record.set_header(Rc::clone(&self.header));
387+
record.set_header(Arc::clone(&self.header));
387388

388389
Some(Ok(()))
389390
}
@@ -591,8 +592,8 @@ impl<'a, T: AsRef<[u8]>, X: Into<FetchCoordinate>, Y: Into<FetchCoordinate>> Fro
591592
#[derive(Debug)]
592593
pub struct IndexedReader {
593594
htsfile: *mut htslib::htsFile,
594-
header: Rc<HeaderView>,
595-
idx: Rc<IndexView>,
595+
header: Arc<HeaderView>,
596+
idx: Arc<IndexView>,
596597
itr: Option<*mut htslib::hts_itr_t>,
597598
tpool: Option<ThreadPool>,
598599
}
@@ -637,8 +638,8 @@ impl IndexedReader {
637638
} else {
638639
Ok(IndexedReader {
639640
htsfile,
640-
header: Rc::new(HeaderView::new(header)),
641-
idx: Rc::new(IndexView::new(idx)),
641+
header: Arc::new(HeaderView::new(header)),
642+
idx: Arc::new(IndexView::new(idx)),
642643
itr: None,
643644
tpool: None,
644645
})
@@ -665,8 +666,8 @@ impl IndexedReader {
665666
} else {
666667
Ok(IndexedReader {
667668
htsfile,
668-
header: Rc::new(HeaderView::new(header)),
669-
idx: Rc::new(IndexView::new(idx)),
669+
header: Arc::new(HeaderView::new(header)),
670+
idx: Arc::new(IndexView::new(idx)),
670671
itr: None,
671672
tpool: None,
672673
})
@@ -908,15 +909,14 @@ impl IndexedReader {
908909
#[derive(Debug)]
909910
pub struct IndexView {
910911
inner: *mut hts_sys::hts_idx_t,
911-
owned: bool,
912912
}
913913

914+
unsafe impl Send for IndexView {}
915+
unsafe impl Sync for IndexView {}
916+
914917
impl IndexView {
915918
fn new(hts_idx: *mut hts_sys::hts_idx_t) -> Self {
916-
Self {
917-
inner: hts_idx,
918-
owned: true,
919-
}
919+
Self { inner: hts_idx }
920920
}
921921

922922
#[inline]
@@ -960,10 +960,8 @@ impl IndexView {
960960

961961
impl Drop for IndexView {
962962
fn drop(&mut self) {
963-
if self.owned {
964-
unsafe {
965-
htslib::hts_idx_destroy(self.inner);
966-
}
963+
unsafe {
964+
htslib::hts_idx_destroy(self.inner);
967965
}
968966
}
969967
}
@@ -977,7 +975,7 @@ impl Read for IndexedReader {
977975
-2 => Some(Err(Error::BamTruncatedRecord)),
978976
-4 => Some(Err(Error::BamInvalidRecord)),
979977
_ => {
980-
record.set_header(Rc::clone(&self.header));
978+
record.set_header(Arc::clone(&self.header));
981979

982980
Some(Ok(()))
983981
}
@@ -1060,7 +1058,7 @@ impl Format {
10601058
#[derive(Debug)]
10611059
pub struct Writer {
10621060
f: *mut htslib::htsFile,
1063-
header: Rc<HeaderView>,
1061+
header: Arc<HeaderView>,
10641062
tpool: Option<ThreadPool>,
10651063
}
10661064

@@ -1134,7 +1132,7 @@ impl Writer {
11341132

11351133
Ok(Writer {
11361134
f,
1137-
header: Rc::new(HeaderView::new(header_record)),
1135+
header: Arc::new(HeaderView::new(header_record)),
11381136
tpool: None,
11391137
})
11401138
}
@@ -1364,9 +1362,11 @@ fn itr_next(
13641362
#[derive(Debug)]
13651363
pub struct HeaderView {
13661364
inner: *mut htslib::bam_hdr_t,
1367-
owned: bool,
13681365
}
13691366

1367+
unsafe impl Send for HeaderView {}
1368+
unsafe impl Sync for HeaderView {}
1369+
13701370
impl HeaderView {
13711371
/// Create a new HeaderView from a pre-populated Header object
13721372
pub fn from_header(header: &Header) -> Self {
@@ -1399,8 +1399,8 @@ impl HeaderView {
13991399
}
14001400

14011401
/// Create a new HeaderView from the underlying Htslib type, and own it.
1402-
pub fn new(inner: *mut htslib::bam_hdr_t) -> Self {
1403-
HeaderView { inner, owned: true }
1402+
fn new(inner: *mut htslib::bam_hdr_t) -> Self {
1403+
HeaderView { inner }
14041404
}
14051405

14061406
#[inline]
@@ -1480,17 +1480,14 @@ impl Clone for HeaderView {
14801480
fn clone(&self) -> Self {
14811481
HeaderView {
14821482
inner: unsafe { htslib::sam_hdr_dup(self.inner) },
1483-
owned: true,
14841483
}
14851484
}
14861485
}
14871486

14881487
impl Drop for HeaderView {
14891488
fn drop(&mut self) {
1490-
if self.owned {
1491-
unsafe {
1492-
htslib::sam_hdr_destroy(self.inner);
1493-
}
1489+
unsafe {
1490+
htslib::sam_hdr_destroy(self.inner);
14941491
}
14951492
}
14961493
}

src/bam/record.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ use std::marker::PhantomData;
1111
use std::mem::{size_of, MaybeUninit};
1212
use std::ops;
1313
use std::os::raw::c_char;
14-
use std::rc::Rc;
1514
use std::slice;
1615
use std::str;
16+
use std::sync::Arc;
1717

1818
use byteorder::{LittleEndian, ReadBytesExt};
1919

@@ -53,7 +53,7 @@ pub struct Record {
5353
pub inner: htslib::bam1_t,
5454
own: bool,
5555
cigar: Option<CigarStringView>,
56-
header: Option<Rc<HeaderView>>,
56+
header: Option<Arc<HeaderView>>,
5757
}
5858

5959
unsafe impl Send for Record {}
@@ -183,7 +183,7 @@ impl Record {
183183
}
184184
}
185185

186-
pub fn set_header(&mut self, header: Rc<HeaderView>) {
186+
pub fn set_header(&mut self, header: Arc<HeaderView>) {
187187
self.header = Some(header);
188188
}
189189

src/bcf/header.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
3535
use std::ffi;
3636
use std::os::raw::c_char;
37-
use std::rc::Rc;
3837
use std::slice;
3938
use std::str;
39+
use std::sync::Arc;
4040

4141
use crate::htslib;
4242

@@ -65,10 +65,13 @@ custom_derive! {
6565
/// A BCF header.
6666
#[derive(Debug)]
6767
pub struct Header {
68-
pub inner: *mut htslib::bcf_hdr_t,
68+
pub(crate) inner: *mut htslib::bcf_hdr_t,
6969
pub subset: Option<SampleSubset>,
7070
}
7171

72+
unsafe impl Send for Header {}
73+
unsafe impl Sync for Header {}
74+
7275
impl Default for Header {
7376
fn default() -> Self {
7477
Self::new()
@@ -266,11 +269,14 @@ pub enum HeaderRecord {
266269

267270
#[derive(Debug)]
268271
pub struct HeaderView {
269-
pub inner: *mut htslib::bcf_hdr_t,
272+
pub(crate) inner: *mut htslib::bcf_hdr_t,
270273
}
271274

275+
unsafe impl Send for HeaderView {}
276+
unsafe impl Sync for HeaderView {}
277+
272278
impl HeaderView {
273-
pub fn new(inner: *mut htslib::bcf_hdr_t) -> Self {
279+
pub(crate) fn new(inner: *mut htslib::bcf_hdr_t) -> Self {
274280
HeaderView { inner }
275281
}
276282

@@ -513,8 +519,15 @@ impl HeaderView {
513519
/// Create an empty record using this header view.
514520
///
515521
/// The record can be reused multiple times.
522+
///
523+
/// # Performance
524+
///
525+
/// This is quite slow and resource-intensive as it clones the actual
526+
/// header, instead of the reference to it. Therefore, whenever possible
527+
/// / feasible you should use [`Record::new`](crate::bcf::Record::new) with
528+
/// a reference to your header.
516529
pub fn empty_record(&self) -> crate::bcf::Record {
517-
crate::bcf::Record::new(Rc::new(self.clone()))
530+
crate::bcf::Record::new(Arc::new(self.clone()))
518531
}
519532
}
520533

0 commit comments

Comments
 (0)