use core::time::Duration;
use std::ops::Deref;
use std::rc::Rc;
use std::sync::Arc;
use std::time::Instant;
use futures::lock::Mutex;
#[derive(Clone)]
#[cfg(any(feature = "count", feature = "rate"))]
pub struct LocalCounter(Rc<CounterInner>);
impl Deref for LocalCounter {
type Target = Rc<CounterInner>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl LocalCounter {
#[inline]
pub fn new(period: Duration) -> Self {
Self(Rc::new(CounterInner::new_inner(period)))
}
#[inline]
pub async fn serialize(&self) -> bincode::Result<Vec<u8>> {
bincode::serialize(self.0 .0.lock().await.deref())
}
#[inline]
pub async fn deserialize(bytes: &[u8]) -> bincode::Result<LocalCounter> {
let inner = bincode::deserialize::<Inner>(bytes)?;
Ok(LocalCounter(Rc::new(CounterInner(Mutex::new(inner)))))
}
}
#[derive(Clone)]
#[cfg(any(feature = "count", feature = "rate"))]
pub struct Counter(Arc<CounterInner>);
impl Deref for Counter {
type Target = Arc<CounterInner>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl Counter {
#[cfg(feature = "rate")]
#[inline]
pub fn new(period: Duration) -> Self {
Self(Arc::new(CounterInner::new_inner(period)))
}
#[cfg(not(feature = "rate"))]
#[inline]
pub fn new() -> Self {
Self(Arc::new(CounterInner::new_inner(Duration::from_secs(3))))
}
#[inline]
pub async fn serialize(&self) -> bincode::Result<Vec<u8>> {
bincode::serialize(self.0 .0.lock().await.deref())
}
#[inline]
pub async fn deserialize(bytes: &[u8]) -> bincode::Result<Counter> {
let inner = bincode::deserialize::<Inner>(bytes)?;
Ok(Counter(Arc::new(CounterInner(Mutex::new(inner)))))
}
}
#[cfg(any(feature = "count", feature = "rate"))]
pub struct CounterInner(Mutex<Inner>);
impl Deref for CounterInner {
type Target = Mutex<Inner>;
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[cfg(feature = "rate")]
#[derive(Serialize, Deserialize)]
struct Rater {
total: isize,
rate: f64,
recent: isize,
period: Duration,
#[serde(skip, default = "Rater::now_default")]
now: Instant,
auto_update: bool,
}
#[cfg(feature = "rate")]
impl Rater {
fn now_default() -> Instant {
Instant::now()
}
}
#[derive(Serialize, Deserialize)]
#[cfg(any(feature = "count", feature = "rate"))]
pub struct Inner {
#[cfg(feature = "count")]
curr: isize,
#[cfg(feature = "count")]
max: isize,
#[cfg(feature = "rate")]
rater: Rater,
}
#[cfg(any(feature = "count", feature = "rate"))]
impl CounterInner {
#[inline]
fn new_inner(period: Duration) -> Self {
let inner = Inner {
#[cfg(feature = "count")]
curr: 0,
#[cfg(feature = "count")]
max: 0,
#[cfg(feature = "rate")]
rater: Rater {
total: 0,
rate: 0.0,
now: Instant::now(),
recent: 0,
period,
auto_update: true,
},
};
Self(Mutex::new(inner))
}
#[inline]
pub async fn inc(&self) {
self.incs(1).await;
}
#[inline]
pub async fn incs(&self, c: isize) {
let mut inner = self.0.lock().await;
#[cfg(feature = "count")]
{
inner.curr += c;
inner.max = inner.max.max(inner.curr);
}
#[cfg(feature = "rate")]
{
inner.rater.total += c;
if inner.rater.auto_update {
let elapsed = inner.rater.now.elapsed();
if elapsed >= inner.rater.period {
let period_count = inner.rater.total - inner.rater.recent;
inner.rater.rate = period_count as f64 / elapsed.as_secs_f64();
inner.rater.now = Instant::now();
inner.rater.recent = inner.rater.total;
}
}
}
}
#[inline]
#[cfg(feature = "rate")]
pub async fn close_auto_update(&self) {
self.0.lock().await.rater.auto_update = false;
}
#[inline]
#[cfg(feature = "rate")]
pub async fn rate_update(&self) {
let mut inner = self.0.lock().await;
let elapsed = inner.rater.now.elapsed();
if elapsed >= inner.rater.period {
let period_count = inner.rater.total - inner.rater.recent;
inner.rater.rate = period_count as f64 / elapsed.as_secs_f64();
inner.rater.now = Instant::now();
inner.rater.recent = inner.rater.total;
}
}
#[inline]
pub async fn sets(&self, c: isize) {
let mut inner = self.0.lock().await;
#[cfg(feature = "count")]
{
inner.curr = c;
inner.max = inner.max.max(inner.curr);
}
#[cfg(feature = "rate")]
{
inner.rater.total = c;
}
}
#[inline]
#[cfg(feature = "count")]
pub async fn dec(&self) {
self.decs(1).await
}
#[inline]
#[cfg(feature = "count")]
pub async fn decs(&self, c: isize) {
let mut inner = self.0.lock().await;
inner.curr -= c;
}
#[inline]
#[cfg(feature = "count")]
pub async fn set_curr_min(&self, count: isize) {
let mut inner = self.0.lock().await;
inner.curr = inner.curr.min(count);
}
#[inline]
#[cfg(feature = "count")]
pub async fn set_max_max(&self, max: isize) {
let mut inner = self.0.lock().await;
inner.max = inner.max.max(max);
}
#[inline]
#[cfg(feature = "count")]
pub async fn count(&self) -> isize {
self.0.lock().await.curr
}
#[inline]
#[cfg(feature = "count")]
pub async fn max(&self) -> isize {
self.0.lock().await.max
}
#[inline]
#[cfg(feature = "rate")]
pub async fn total(&self) -> isize {
self.0.lock().await.rater.total
}
#[inline]
#[cfg(feature = "rate")]
pub async fn rate(&self) -> f64 {
self.0.lock().await.rater.rate
}
#[inline]
pub async fn add(&self, other: &Self) {
let mut inner = self.0.lock().await;
let other = other.0.lock().await;
#[cfg(feature = "count")]
{
inner.curr += other.curr;
inner.max += other.max;
}
#[cfg(feature = "rate")]
{
inner.rater.total += other.rater.total;
inner.rater.rate += other.rater.rate;
}
}
#[inline]
pub async fn set(&self, other: &Self) {
let mut inner = self.0.lock().await;
let other = other.0.lock().await;
#[cfg(feature = "count")]
{
inner.curr = other.curr;
inner.max = other.max;
}
#[cfg(feature = "rate")]
{
inner.rater.total = other.rater.total;
inner.rater.rate = other.rater.rate;
inner.rater.now = other.rater.now;
inner.rater.recent = other.rater.recent;
}
}
}