use std::sync::{Arc, Mutex};
use crate::concurrent::atomic_buffer::AtomicBuffer;
use crate::concurrent::counters::{CountersManager, CountersReader};
use crate::utils::types::Index;
pub struct AtomicCounter {
buffer: AtomicBuffer,
counter_id: i32,
counters_manager: Option<Arc<Mutex<CountersManager>>>, offset: Index,
}
impl AtomicCounter {
pub fn new(buffer: AtomicBuffer, counter_id: i32) -> Self {
let selfy = Self {
buffer,
counter_id,
counters_manager: None,
offset: CountersReader::counter_offset(counter_id),
};
selfy.buffer.put::<i64>(selfy.offset, 0);
selfy
}
pub fn new_opt(buffer: AtomicBuffer, counter_id: i32, counters_mgr: Arc<Mutex<CountersManager>>) -> Self {
let selfy = Self {
buffer,
counter_id,
counters_manager: Some(counters_mgr),
offset: CountersReader::counter_offset(counter_id),
};
selfy.buffer.put::<i64>(selfy.offset, 0);
selfy
}
pub fn id(&self) -> i32 {
self.counter_id
}
pub fn increment(&self) {
self.buffer.get_and_add_i64(self.offset, 1);
}
pub fn increment_ordered(&self) {
self.buffer.add_i64_ordered(self.offset, 1);
}
pub fn set(&self, value: i64) {
self.buffer.put_atomic_i64(self.offset, value);
}
pub fn set_ordered(&self, value: i64) {
self.buffer.put_ordered::<i64>(self.offset, value);
}
pub fn set_weak(&self, value: i64) {
self.buffer.put::<i64>(self.offset, value);
}
pub fn get_and_add(&self, value: i64) -> i64 {
self.buffer.get_and_add_i64(self.offset, value)
}
pub fn get_and_add_ordered(&self, increment: i64) -> i64 {
let current_value = self.buffer.get::<i64>(self.offset);
self.buffer.put_ordered::<i64>(self.offset, current_value + increment);
current_value
}
pub fn get_and_set(&self, value: i64) -> i64 {
let current_value = self.buffer.get::<i64>(self.offset);
self.buffer.put_atomic_i64(self.offset, value);
current_value
}
pub fn compare_and_set(&self, expected_value: i64, update_value: i64) -> bool {
self.buffer.compare_and_set_i64(self.offset, expected_value, update_value)
}
pub fn get(&self) -> i64 {
self.buffer.get_volatile::<i64>(self.offset)
}
pub fn get_weak(&self) -> i64 {
self.buffer.get::<i64>(self.offset)
}
}
impl Drop for AtomicCounter {
fn drop(&mut self) {
if let Some(mgr) = &self.counters_manager {
mgr.lock().expect("Can't lock mutex on counters_mgr").free(self.counter_id);
}
}
}