use core::cell::Cell;
use core::sync::atomic::{AtomicBool, Ordering};
use std::io;
static COUNTING: AtomicBool = AtomicBool::new(false);
pub(crate) fn start() {
COUNTING.store(true, Ordering::Relaxed);
}
#[inline(always)]
pub(crate) fn counting() -> bool {
COUNTING.load(Ordering::Relaxed)
}
struct Cells {
reads: Cell<u64>,
writes: Cell<u64>,
bytes_read: Cell<u64>,
bytes_written: Cell<u64>,
accepts: Cell<u64>,
}
thread_local! {
static CELLS: Cells = const {
Cells {
reads: Cell::new(0),
writes: Cell::new(0),
bytes_read: Cell::new(0),
bytes_written: Cell::new(0),
accepts: Cell::new(0),
}
};
}
#[derive(Default)]
pub(crate) struct Taken {
pub(crate) reads: u64,
pub(crate) writes: u64,
pub(crate) bytes_read: u64,
pub(crate) bytes_written: u64,
pub(crate) accepts: u64,
}
#[inline(always)]
pub(crate) fn read(bytes: usize) {
if counting() {
add_read(bytes);
}
}
#[inline(always)]
pub(crate) fn wrote(bytes: usize) {
if counting() {
add_write(bytes);
}
}
#[inline(always)]
pub(crate) fn accepted(count: usize) {
if counting() {
add_accepts(count);
}
}
#[inline(always)]
pub(crate) fn reading(result: &io::Result<usize>) {
if counting() {
count_reading(result);
}
}
#[inline(always)]
pub(crate) fn received<A>(result: &io::Result<(usize, A)>) {
if counting() {
count_received(result);
}
}
#[inline(always)]
pub(crate) fn writing(result: &io::Result<usize>) {
if counting() {
count_writing(result);
}
}
#[cfg(readiness)]
#[inline(always)]
pub(crate) fn accepting<A>(result: &io::Result<A>) {
if result.is_ok() {
accepted(1);
}
}
#[cold]
#[inline(never)]
pub(crate) fn add_read(bytes: usize) {
CELLS.with(|c| {
c.reads.set(c.reads.get() + 1);
c.bytes_read.set(c.bytes_read.get() + bytes as u64);
});
}
#[cold]
#[inline(never)]
pub(crate) fn add_write(bytes: usize) {
CELLS.with(|c| {
c.writes.set(c.writes.get() + 1);
c.bytes_written.set(c.bytes_written.get() + bytes as u64);
});
}
#[inline(never)]
fn add_accepts(count: usize) {
CELLS.with(|c| c.accepts.set(c.accepts.get() + count as u64));
}
#[inline(never)]
fn count_reading(result: &io::Result<usize>) {
if let Ok(n) = result {
add_read(*n);
}
}
#[inline(never)]
fn count_received<A>(result: &io::Result<(usize, A)>) {
if let Ok((n, _)) = result {
add_read(*n);
}
}
#[inline(never)]
fn count_writing(result: &io::Result<usize>) {
if let Ok(n @ 1..) = result {
add_write(*n);
}
}
pub(crate) fn take() -> Taken {
CELLS.with(|c| Taken {
reads: c.reads.take(),
writes: c.writes.take(),
bytes_read: c.bytes_read.take(),
bytes_written: c.bytes_written.take(),
accepts: c.accepts.take(),
})
}