diff --git a/src/id_generator.rs b/src/id_generator.rs new file mode 100644 index 0000000..2e89049 --- /dev/null +++ b/src/id_generator.rs @@ -0,0 +1,39 @@ +use std::collections::VecDeque; +use std::sync::atomic::{AtomicUsize, Ordering}; + + + +pub struct IdGenerator { + name: String, + counter: AtomicUsize, + max_count: usize, + cache: VecDeque, +} + +impl IdGenerator { + fn new(name: &str, max_count: usize) -> Self { + IdGenerator { + name: String::from(name), + counter: AtomicUsize::new(0), + max_count, + cache: VecDeque::new(), + } + } + + fn name(&self) -> &String { + &self.name + } + + fn poll(&mut self) -> usize { + if self.cache.is_empty() { + self.fill(); + } + self.cache.pop_front().unwrap() + } + + fn fill(&mut self) { + let current = self.counter.fetch_add(self.max_count, Ordering::Relaxed); + let new_ids = (current..(current + self.max_count)).collect::>(); + self.cache.extend(new_ids); + } +} diff --git a/src/my_rpc_server.rs b/src/my_rpc_server.rs index b02254f..2301637 100644 --- a/src/my_rpc_server.rs +++ b/src/my_rpc_server.rs @@ -21,13 +21,9 @@ pub mod bidirectional { } // my service -pub mod id_generator; pub mod my_rpc_service; -pub mod object_pool; pub mod quick_rpc_service; -use id_generator::IdGenerator; use my_rpc_service::MyRpcService; -use object_pool::ObjectPool; diff --git a/src/object_pool.rs b/src/object_pool.rs new file mode 100644 index 0000000..14bd5c6 --- /dev/null +++ b/src/object_pool.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; +use std::sync::atomic::{AtomicPtr, Ordering}; + + + +pub struct ObjectPool { + objects: AtomicPtr>, +} + +impl ObjectPool { + fn new() -> Self { + ObjectPool { + objects: AtomicPtr::new(std::ptr::null_mut()), + } + } + + pub fn invoke(&mut self, name: String, new_fn: F1, invoke_fn: F2) -> R + where + F1: FnOnce() -> T, + F2: FnOnce(&mut T) -> R, + { + let objects_map_ptr = self.objects.load(Ordering::Acquire); + let mut objects_map = unsafe { &mut *objects_map_ptr }; + + if objects_map_ptr.is_null() { + let new_map = Box::new(HashMap::new()); + let new_map_ptr = Box::into_raw(new_map); + if self + .objects + .compare_exchange(objects_map_ptr, new_map_ptr, Ordering::Release, Ordering::Relaxed) + .is_ok() + { + objects_map = unsafe { &mut *new_map_ptr }; + } + } + + match objects_map.entry(name.clone()) { + std::collections::hash_map::Entry::Occupied(mut occupied_entry) => { + return invoke_fn(occupied_entry.get_mut()); + } + std::collections::hash_map::Entry::Vacant(vacant_entry) => { + let mut new_object = new_fn(); + let result = invoke_fn(&mut new_object); + vacant_entry.insert(new_object); + return result; + } + } + } +}