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 81 82 83 84
pub mod guard_drop;
pub mod new_pool_item_error;
use tracing::{event, Level};
use crate::{
id_targeted::IdTargeted, request_with_response::RequestWithResponse, thread_request_response::*,
};
use std::fmt::Debug;
pub use self::guard_drop::GuardDrop;
pub use self::new_pool_item_error::NewPoolItemError;
/// This is the trait that needs to be implemented by a struct in order that it can be
/// managed by the thread pool infrastructure
pub trait PoolItem: Debug
where
Self: Sized,
Self::Init: Send + IdTargeted + RequestWithResponse<Self, Response = AddResponse>,
Self::Api: Debug + Send + IdTargeted,
{
/// This is a struct that defines the message that will initiate a new instance
/// of the struct within the thread pool
type Init;
/// This is the enum that will define that messaging api that can be used to
/// communicate with instances of the struct
/// It will be an enum where each variant will define a request/response pair
/// of structs
type Api;
/// This is the function that will define how the struct processes the messages that
/// it receives.
/// It will typically consist of a match statement that will discriminate amongst
/// the various messages type defined in the Api
fn process_message(&mut self, request: Self::Api) -> ThreadRequestResponse<Self>;
/// The function called if an item with the specified is not found
/// The default behaviour is to panic
fn id_not_found(request: &Self::Api) -> ThreadRequestResponse<Self> {
// default behaviour is to panic
event!(Level::ERROR, "pool item with id {} not found", request.id());
panic!("pool item with id {} not found", request.id());
}
/// used for debug only; allows logging to output the name of the type
fn name() -> &'static str {
std::any::type_name::<Self>()
}
/// This function defines how a new struct will be created when it receives
/// The Init message.
/// It returns the created new instance of the struct
fn new_pool_item(request: Self::Init) -> Result<Self, NewPoolItemError>;
/// This function is a hook that is called when the pool is shutting down.
fn shutdown_pool(&self) -> Vec<ThreadShutdownResponse> {
Vec::<ThreadShutdownResponse>::default()
}
/// This method is called to optionally add tracing before each message is processed.
/// The tracing is removed once the message is processed.
/// If the tracing is being written to a file it is important that the file is not truncated
/// The implementation needs to return a vec of guards of any subscribers added.
fn add_pool_item_tracing(&self) -> Option<Vec<Box<dyn GuardDrop>>> {
// by default no pool item tracing
None
}
/// This method provides any required tracing in the pool items thread pool threads
/// This tracing is added when the thread is spawned and remains in place until the thread dies
#[allow(unused_variables)]
fn add_pool_thread_tracing(id: usize) -> Option<Vec<Box<dyn GuardDrop>>> {
// by default no pool thread tracing
None
}
/// This method defines the algorithm to be used for routing a given pool item id
/// to a given pool item thread.
/// Usually just modding with the thread count is sufficient assuming that ids
/// are assigned linearly
fn id_thread_router(id: usize, thread_count: usize) -> usize {
id % thread_count
}
}