use std::sync::atomic::{AtomicI32, Ordering};
const INITIAL_REQUEST_ID: i32 = 9000;
#[derive(Debug)]
pub(crate) struct IdGenerator {
next_id: AtomicI32,
}
impl IdGenerator {
pub(crate) fn new(start: i32) -> Self {
Self {
next_id: AtomicI32::new(start),
}
}
pub(crate) fn new_request_id_generator() -> Self {
Self::new(INITIAL_REQUEST_ID)
}
pub(crate) fn new_order_id_generator(start: i32) -> Self {
Self::new(start)
}
pub(crate) fn next(&self) -> i32 {
self.next_id.fetch_add(1, Ordering::Relaxed)
}
#[allow(dead_code)]
pub(crate) fn current(&self) -> i32 {
self.next_id.load(Ordering::Relaxed)
}
pub(crate) fn set(&self, value: i32) {
self.next_id.store(value, Ordering::Relaxed);
}
#[allow(dead_code)]
pub(crate) fn reset(&self, start: i32) {
self.set(start);
}
}
impl Default for IdGenerator {
fn default() -> Self {
Self::new(0)
}
}
#[derive(Debug)]
pub(crate) struct ClientIdManager {
request_ids: IdGenerator,
order_ids: IdGenerator,
}
impl ClientIdManager {
pub(crate) fn new(initial_order_id: i32) -> Self {
Self {
request_ids: IdGenerator::new_request_id_generator(),
order_ids: IdGenerator::new_order_id_generator(initial_order_id),
}
}
pub(crate) fn next_request_id(&self) -> i32 {
self.request_ids.next()
}
pub(crate) fn next_order_id(&self) -> i32 {
self.order_ids.next()
}
pub(crate) fn set_order_id(&self, order_id: i32) {
self.order_ids.set(order_id);
}
#[allow(dead_code)]
pub(crate) fn current_order_id(&self) -> i32 {
self.order_ids.current()
}
#[allow(dead_code)]
pub(crate) fn current_request_id(&self) -> i32 {
self.request_ids.current()
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::Arc;
use std::thread;
#[test]
fn test_id_generator_basic() {
let gen = IdGenerator::new(100);
assert_eq!(gen.current(), 100);
assert_eq!(gen.next(), 100);
assert_eq!(gen.next(), 101);
assert_eq!(gen.next(), 102);
assert_eq!(gen.current(), 103);
}
#[test]
fn test_id_generator_set() {
let gen = IdGenerator::new(100);
assert_eq!(gen.next(), 100);
gen.set(200);
assert_eq!(gen.next(), 200);
assert_eq!(gen.next(), 201);
}
#[test]
fn test_id_generator_thread_safe() {
let gen = Arc::new(IdGenerator::new(0));
let mut handles = vec![];
for _ in 0..10 {
let gen_clone = Arc::clone(&gen);
let handle = thread::spawn(move || {
let mut ids = vec![];
for _ in 0..100 {
ids.push(gen_clone.next());
}
ids
});
handles.push(handle);
}
let mut all_ids = vec![];
for handle in handles {
all_ids.extend(handle.join().unwrap());
}
all_ids.sort();
assert_eq!(all_ids.len(), 1000);
for (i, id) in all_ids.iter().enumerate() {
assert_eq!(*id, i as i32);
}
}
#[test]
fn test_request_id_generator() {
let gen = IdGenerator::new_request_id_generator();
assert_eq!(gen.current(), INITIAL_REQUEST_ID);
assert_eq!(gen.next(), INITIAL_REQUEST_ID);
assert_eq!(gen.next(), INITIAL_REQUEST_ID + 1);
}
#[test]
fn test_client_id_manager() {
let manager = ClientIdManager::new(50);
assert_eq!(manager.current_request_id(), INITIAL_REQUEST_ID);
assert_eq!(manager.next_request_id(), INITIAL_REQUEST_ID);
assert_eq!(manager.next_request_id(), INITIAL_REQUEST_ID + 1);
assert_eq!(manager.current_order_id(), 50);
assert_eq!(manager.next_order_id(), 50);
assert_eq!(manager.next_order_id(), 51);
manager.set_order_id(100);
assert_eq!(manager.next_order_id(), 100);
assert_eq!(manager.next_order_id(), 101);
}
}