use std::sync::Arc;
use crate::bindings::dataset::*;
use crate::cache::{Cache, CacheRawAPI};
use crate::errors::RandomXError::DatasetAllocationError;
use crate::flags::RandomXFlags;
use crate::try_alloc;
use crate::RResult;
#[derive(Debug)]
pub struct Dataset {
inner: Arc<DatasetInner>,
}
#[derive(Debug)]
struct DatasetInner {
dataset: *mut randomx_dataset,
}
unsafe impl Send for DatasetInner {}
unsafe impl Sync for DatasetInner {}
#[derive(Clone, Debug)]
pub struct DatasetHandle {
inner: Arc<DatasetInner>,
}
impl Dataset {
pub fn new(global_nonce: &[u8], flags: RandomXFlags) -> RResult<Self> {
let cache = Cache::new(global_nonce, flags)?;
Self::from_cache(&cache, flags.contains(RandomXFlags::LARGE_PAGES))
}
pub fn from_cache(cache: &Cache, large_pages_enabled: bool) -> RResult<Self> {
let mut dataset = Self::allocate(large_pages_enabled)?;
let items_count = dataset.items_count();
dataset.initialize(cache, 0, items_count);
Ok(dataset)
}
pub fn allocate(large_pages_enabled: bool) -> RResult<Self> {
let flags = if large_pages_enabled {
RandomXFlags::LARGE_PAGES
} else {
RandomXFlags::default()
};
let dataset =
try_alloc! { randomx_alloc_dataset(flags.bits()), DatasetAllocationError { flags } };
let dataset_inner = DatasetInner { dataset };
let dataset = Self {
inner: Arc::new(dataset_inner),
};
Ok(dataset)
}
pub fn items_count(&self) -> u64 {
unsafe { randomx_dataset_item_count() }
}
pub fn initialize(&mut self, cache: &impl CacheRawAPI, start_item: u64, items_count: u64) {
unsafe { randomx_init_dataset(self.raw(), cache.raw(), start_item, items_count) };
}
pub fn handle(&self) -> DatasetHandle {
DatasetHandle {
inner: self.inner.clone(),
}
}
pub(crate) fn raw(&self) -> *mut randomx_dataset {
self.inner.dataset
}
}
impl DatasetHandle {
pub fn items_count(&self) -> u64 {
unsafe { randomx_dataset_item_count() }
}
pub fn initialize(&mut self, cache: &impl CacheRawAPI, start_item: u64, items_count: u64) {
unsafe { randomx_init_dataset(self.raw(), cache.raw(), start_item, items_count) };
}
pub(crate) fn raw(&self) -> *mut randomx_dataset {
self.inner.dataset
}
}
impl Drop for DatasetInner {
fn drop(&mut self) {
unsafe { randomx_release_dataset(self.dataset) }
}
}
pub trait DatasetRawAPI {
fn raw(&self) -> *mut randomx_dataset;
}
impl DatasetRawAPI for Dataset {
fn raw(&self) -> *mut randomx_dataset {
self.raw()
}
}
impl DatasetRawAPI for DatasetHandle {
fn raw(&self) -> *mut randomx_dataset {
self.raw()
}
}