How to define the future and handle
todo!
How to gracefully shutdown the nested runtime
Using the manutallyDrop to customize drop order of vars.
pub struct BackgroundShutdownRuntime(ManuallyDrop<Runtime>);
impl Debug for BackgroundShutdownRuntime {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("BackgroundShutdownRuntime").finish()
}
}
impl Drop for BackgroundShutdownRuntime {
fn drop(&mut self) {
// Safety: The runtime is only dropped once here.
let runtime = unsafe { ManuallyDrop::take(&mut self.0) };
runtime.shutdown_background();
}
}
How to implement the object pool
The object pool could be shared with the different threads, that means it should be thread safe
/// A concurrent object pool.
pub struct ObjectPool<T> {
inner: Arc<ObjectPoolInner<T>>,
}
impl<T> Clone for ObjectPool<T> {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
struct ObjectPoolInner<T> {
queue: Option<ArrayQueue<T>>,
create: Box<dyn Fn() -> T + Send + Sync + 'static>,
}
impl<T> ObjectPool<T>
where
T: Default + 'static,
{
/// Create a new concurrent object pool.
pub fn new(capacity: usize) -> Self {
Self::new_with_create(capacity, T::default)
}
}
impl<T> ObjectPool<T> {
/// Create a new concurrent object pool with object creation method.
pub fn new_with_create(capacity: usize, create: impl Fn() -> T + Send + Sync + 'static) -> Self {
let inner = ObjectPoolInner {
queue: if capacity == 0 {
None
} else {
Some(ArrayQueue::new(capacity))
},
create: Box::new(create),
};
Self { inner: Arc::new(inner) }
}
/// Get or create an object from the objcet pool.
pub fn acquire(&self) -> T {
self.inner.queue.as_ref().unwrap().pop()
match self.inner.queue.as_ref() {
Some(queue) => queue.pop().unwrap_or((self.inner.create)()),
None => (self.inner.create)(),
}
}
/// Give back or release an object from the objcet pool.
pub fn release(&self, item: T) {
if let Some(queue) = self.inner.queue.as_ref() {
let _ = queue.push(item);
}
}
}