package flow

import (
	
	
	
)

// Snapshot is a rate/total snapshot.
type Snapshot struct {
	Rate       float64
	Total      uint64
	LastUpdate time.Time
}

// NewMeter returns a new Meter with the correct idle time.
//
// While zero-value Meters can be used, their "last update" time will start at
// the program start instead of when the meter was created.
func () *Meter {
	return &Meter{
		snapshot: Snapshot{
			LastUpdate: cl.Now(),
		},
	}
}

func ( Snapshot) () string {
	return fmt.Sprintf("%d (%f/s)", .Total, .Rate)
}

// Meter is a meter for monitoring a flow.
type Meter struct {
	accumulator atomic.Uint64

	// managed by the sweeper loop.
	registered bool

	// Take lock.
	snapshot Snapshot
}

// Mark updates the total.
func ( *Meter) ( uint64) {
	if  > 0 && .accumulator.Add() ==  {
		// The accumulator is 0 so we probably need to register. We may
		// already _be_ registered however, if we are, the registration
		// loop will notice that `m.registered` is set and ignore us.
		globalSweeper.Register()
	}
}

// Snapshot gets a snapshot of the total and rate.
func ( *Meter) () Snapshot {
	globalSweeper.snapshotMu.RLock()
	defer globalSweeper.snapshotMu.RUnlock()
	return .snapshot
}

// Reset sets accumulator, total and rate to zero.
func ( *Meter) () {
	globalSweeper.snapshotMu.Lock()
	.accumulator.Store(0)
	.snapshot.Rate = 0
	.snapshot.Total = 0
	globalSweeper.snapshotMu.Unlock()
}

func ( *Meter) () string {
	return .Snapshot().String()
}