1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
use randomx_bindings_sys::*; use std::sync::Arc; use std::thread; use std::vec::Vec; use crate::cache::*; use crate::error::*; use crate::flags::*; pub struct RandomxDataset { pub(crate) dataset: *mut randomx_dataset, } impl RandomxDataset { pub fn new(flags: RandomxFlags, key: &[u8], num_threads: u8) -> Result<Self, RandomxError> { assert!(num_threads > 0); let cache = RandomxCache::new(flags, key)?; let dataset = unsafe { randomx_alloc_dataset(flags.bits()) }; if dataset.is_null() { return Err(RandomxError::DatasetAllocError); } let mut dataset = RandomxDataset { dataset }; let count = unsafe { randomx_dataset_item_count() }; if num_threads == 1 { unsafe { randomx_init_dataset(dataset.dataset, cache.cache, 0, count); } } else { let mut handles = Vec::new(); let cache_arc = Arc::new(cache); let dataset_arc = Arc::new(dataset); let size = count / num_threads as u64; let last = count % num_threads as u64; let mut start = 0; for i in 0..num_threads { let cache = cache_arc.clone(); let dataset = dataset_arc.clone(); let mut this_size = size; if i == num_threads - 1 { this_size += last; } let this_start = start; handles.push(thread::spawn(move || unsafe { randomx_init_dataset(dataset.dataset, cache.cache, this_start, this_size); })); start += this_size; } for handle in handles { let _ = handle.join(); } dataset = match Arc::try_unwrap(dataset_arc) { Ok(dataset) => dataset, Err(_) => return Err(RandomxError::DatasetAllocError), }; } Ok(dataset) } } impl Drop for RandomxDataset { fn drop(&mut self) { unsafe { randomx_release_dataset(self.dataset) } } } unsafe impl Send for RandomxDataset {} unsafe impl Sync for RandomxDataset {}