use std::fmt::Debug;
use std::sync::Arc;
use crate::pool_item;
use crate::samples::Randoms;
use crate::{id_provider::IdProvider, *};
use super::{RandomsAddRequest, SumRequest, SumResponse};
pub trait InnerThreadPool: Debug + Send {
type ThreadPool: SenderAndReceiver<Randoms> + Send + Sync + Debug;
}
#[derive(Debug)]
pub struct RandomsThreadPool;
impl InnerThreadPool for RandomsThreadPool {
type ThreadPool = ThreadPool<Randoms>;
}
impl<T: RequestWithResponse<Randoms> + Send + Sync> InnerThreadPool
for SenderAndReceiverMock<Randoms, T>
where
<T as request_with_response::RequestWithResponse<Randoms>>::Response: Send,
{
type ThreadPool = SenderAndReceiverMock<Randoms, T>;
}
#[derive(Debug, Clone)]
pub struct RandomsBatchAddRequest<P: InnerThreadPool> {
pub id: u64,
pub number_of_contained_randoms: usize,
pub id_provider: Arc<dyn IdProvider>,
pub randoms_thread_pool: Arc<P::ThreadPool>,
}
impl<P: InnerThreadPool> RandomsBatchAddRequest<P> {
pub fn id_provider(&self) -> &dyn IdProvider {
self.id_provider.as_ref()
}
pub fn id(&self) -> u64 {
self.id
}
}
impl<P: InnerThreadPool> IdTargeted for RandomsBatchAddRequest<P> {
fn id(&self) -> u64 {
self.id
}
}
impl<P: InnerThreadPool> RequestWithResponse<RandomsBatch<P>> for RandomsBatchAddRequest<P> {
type Response = AddResponse;
}
impl<P: InnerThreadPool> From<RandomsBatchAddRequest<P>>
for ThreadRequestResponse<RandomsBatch<P>>
{
fn from(request: RandomsBatchAddRequest<P>) -> Self {
ThreadRequestResponse::<RandomsBatch<P>>::AddPoolItem(RequestResponse::Request(request))
}
}
#[derive(Debug)]
pub struct RandomsBatch<P: InnerThreadPool> {
pub id: u64,
pub contained_random_ids: Vec<u64>,
pub id_provider: Arc<dyn IdProvider>,
pub randoms_thread_pool: Arc<P::ThreadPool>,
}
#[pool_item(Init = "RandomsBatchAddRequest<P>")]
impl<P: InnerThreadPool> RandomsBatch<P> {
pub fn new(add_request: RandomsBatchAddRequest<P>) -> Self {
let mut new = Self {
id: add_request.id,
contained_random_ids: vec![],
id_provider: Arc::clone(&add_request.id_provider),
randoms_thread_pool: Arc::clone(&add_request.randoms_thread_pool),
};
let mut ids = Vec::<u64>::default();
new.randoms_thread_pool()
.send_and_receive(
(0..add_request.number_of_contained_randoms)
.map(|_| RandomsAddRequest(new.id_provider.next_id())),
)
.expect("randoms thread pool to be available")
.for_each(|r: AddResponse| {
assert!(r.result().is_ok(), "Request to add Randoms failed");
ids.push(r.id());
});
new.contained_random_ids_mut().append(&mut ids);
new
}
pub fn randoms_thread_pool(&self) -> &P::ThreadPool {
self.randoms_thread_pool.as_ref()
}
#[messaging(SumOfSumsRequest, SumOfSumsResponse)]
pub fn sum_of_sums(&self) -> u128 {
self.randoms_thread_pool()
.send_and_receive(self.contained_random_ids.iter().map(|id| SumRequest(*id)))
.expect("randoms thread pool to be available")
.map(|response: SumResponse| response.sum())
.sum()
}
pub fn contained_random_ids_mut(&mut self) -> &mut Vec<u64> {
&mut self.contained_random_ids
}
}