Alpha ZealPHP is early-stage and under active development. APIs may change between minor versions until v1.0. Feedback and bug reports welcome on GitHub.
API Index — Namespaces, Packages, Reports, Indices

Counter
in package

Counter — backend-agnostic atomic integer.

Default backend is OpenSwoole\Atomic for lock-free cross-worker sharing. Switch to Redis for cross-NODE atomicity:

Counter::defaultBackend('redis');

The instance API stays exactly as it was; existing new Counter(0) call sites in the codebase keep working unchanged.

Usage:

$hits = new Counter(0);
$hits->increment();          // +1, returns new value
$hits->increment(5);         // +5
$hits->compareAndSet(6, 0);  // atomic CAS (Lua on Redis backend)

Table of Contents

Constants

BACKEND_ATOMIC  : mixed = 'atomic'
BACKEND_MEMCACHED  : mixed = 'memcached'
BACKEND_REDIS  : mixed = 'redis'

Properties

$anonSerial  : int
Monotonically increasing serial for anonymous counter names.
$backend  : CounterBackend|null
$backendConfig  : array{kind: string, conn?: string|array}
$name  : string

Methods

__construct()  : mixed
compareAndSet()  : bool
Compare-and-swap: if current value equals $expected, set to $new.
decrement()  : int
Atomically subtract $by and return the new value.
defaultBackend()  : CounterBackend
Get or set the process-wide default counter backend.
expire()  : bool
Set TTL on the underlying key (N-3).
get()  : int
Read the current value.
increment()  : int
Atomically add $by and return the new value.
incrementBounded()  : int|null
Bounded atomic increment (N-2). Increments only if the result would stay within $maxBound. Returns the new value, or NULL when the cap would be exceeded.
mincr()  : array<string, int>
Batch atomic increment (N-4). Pipelined on Redis (one round-trip for the whole batch); sequential on Atomic.
raw()  : Long
Return the raw OpenSwoole\Atomic\Long (64-bit signed). Only available on the atomic backend; throws on the redis backend (no atomic equivalent there).
reset()  : void
Reset to zero.
set()  : void
Set the value (not atomic relative to concurrent add/sub).
buildBackend()  : CounterBackend
memcachedServersFromEnv()  : string
poolOptsFromEnv()  : array{prefer?: "auto"|"phpredis"|"predis"}
redisUrlFromEnv()  : string

Constants

BACKEND_ATOMIC

public mixed BACKEND_ATOMIC = 'atomic'

BACKEND_MEMCACHED

public mixed BACKEND_MEMCACHED = 'memcached'

BACKEND_REDIS

public mixed BACKEND_REDIS = 'redis'

Properties

$anonSerial

Monotonically increasing serial for anonymous counter names.

private static int $anonSerial = 0

spl_object_id() would reuse IDs after GC, leaking state between objects that happen to land on the same slot.

$backendConfig

private static array{kind: string, conn?: string|array} $backendConfig = ['kind' => 'atomic']

Methods

__construct()

public __construct([int $initial = 0 ][, string|null $name = null ]) : mixed
Parameters
$initial : int = 0

starting value (defaults to 0)

$name : string|null = null

optional shared name; auto-generated unique when null

compareAndSet()

Compare-and-swap: if current value equals $expected, set to $new.

public compareAndSet(int $expected, int $new) : bool

On the Redis backend this is one round-trip via a Lua script.

Parameters
$expected : int
$new : int
Return values
bool

decrement()

Atomically subtract $by and return the new value.

public decrement([int $by = 1 ]) : int
Parameters
$by : int = 1
Return values
int

defaultBackend()

Get or set the process-wide default counter backend.

public static defaultBackend([string|null $kind = null ][, string|array<string, mixed> $conn = [] ]) : CounterBackend
Parameters
$kind : string|null = null

'atomic' (default) or 'redis'; null to read current

$conn : string|array<string, mixed> = []

redis URL or ['url'=>, 'pool_size'=>, 'prefix'=>]

Return values
CounterBackend

expire()

Set TTL on the underlying key (N-3).

public expire(int $seconds) : bool

Atomic backend: no-op, returns false. Shared memory has no TTL — the counter survives until the OpenSwoole master dies. Redis backend: applies EXPIRE on the counter's key. Returns true if the TTL was set; false if the key doesn't exist.

Parameters
$seconds : int
Return values
bool

get()

Read the current value.

public get() : int
Return values
int

increment()

Atomically add $by and return the new value.

public increment([int $by = 1 ]) : int
Parameters
$by : int = 1
Return values
int

incrementBounded()

Bounded atomic increment (N-2). Increments only if the result would stay within $maxBound. Returns the new value, or NULL when the cap would be exceeded.

public incrementBounded([int $by = 1 ][, int $maxBound = PHP_INT_MAX ]) : int|null

$slots = new Counter(0, 'free_slots'); if ($slots->incrementBounded(1, 100) === null) { return 'pool full'; }

Parameters
$by : int = 1
$maxBound : int = PHP_INT_MAX
Return values
int|null

mincr()

Batch atomic increment (N-4). Pipelined on Redis (one round-trip for the whole batch); sequential on Atomic.

public static mincr(array<string, int> $deltas) : array<string, int>

$hits = Counter::mincr(['page:home' => 1, 'page:about' => 1]); // ['page:home' => 142, 'page:about' => 87]

Parameters
$deltas : array<string, int>

name → delta

Return values
array<string, int>

name → new value

raw()

Return the raw OpenSwoole\Atomic\Long (64-bit signed). Only available on the atomic backend; throws on the redis backend (no atomic equivalent there).

public raw() : Long

NOTE: as of the 64-bit-counter fix this returns OpenSwoole\Atomic\Long, not the 32-bit OpenSwoole\Atomic it returned previously — so counters no longer silently wrap at 2^32.

Return values
Long

reset()

Reset to zero.

public reset() : void

set()

Set the value (not atomic relative to concurrent add/sub).

public set(int $value) : void
Parameters
$value : int

buildBackend()

private static buildBackend(array{kind: string, conn?: string|array$cfg) : CounterBackend
Parameters
$cfg : array{kind: string, conn?: string|array}
Return values
CounterBackend

memcachedServersFromEnv()

private static memcachedServersFromEnv() : string
Return values
string

poolOptsFromEnv()

private static poolOptsFromEnv() : array{prefer?: "auto"|"phpredis"|"predis"}
Return values
array{prefer?: "auto"|"phpredis"|"predis"}

redisUrlFromEnv()

private static redisUrlFromEnv() : string
Return values
string
On this page