linux-sysprog · intermediate · ~12 min
Wrap a mutex + state in a tiny opaque struct.
Package a mutex-protected long into a small opaque counter type with create / increment / read / free operations — a reusable thread-safe building block.
Implement these four functions for a thread-safe counter:
typedef struct ts_counter ts_counter_t;
ts_counter_t *tsc_new(void);
void tsc_inc(ts_counter_t *c);
long tsc_value(ts_counter_t *c);
void tsc_free(ts_counter_t *c);
tsc_new: no parameters.tsc_inc, tsc_value, tsc_free: a counter handle c.tsc_new allocates a counter starting at 0 (with its own pthread_mutex_t) and returns it, or NULL on allocation failure.tsc_inc increments the counter under the lock.tsc_value returns the current value, read under the lock.tsc_free destroys the mutex and frees the counter (safe on NULL).c = tsc_new() -> non-NULL
tsc_value(c) -> 0
tsc_inc(c); tsc_inc(c); tsc_inc(c)
tsc_value(c) -> 3
4 threads each call tsc_inc 1000 times
tsc_value(c) -> 3 + 4000 = 4003 (no lost updates)
tsc_free(c)
tsc_free(NULL) is a safe no-op.Encapsulate a primitive into a reusable thread-safe API — the building block of every server's stats counter.
tsc_new takes nothing; tsc_inc/tsc_value/tsc_free take a ts_counter_t* handle.
tsc_new returns a new zeroed counter (or NULL); tsc_inc increments; tsc_value returns the current value under the lock; tsc_free releases it.
Each counter owns a pthread_mutex_t guarding its long. Read and increment both under the lock; tsc_free(NULL) is safe.
#include <pthread.h>
#include <stddef.h>
struct ts_counter;
typedef struct ts_counter ts_counter_t;
ts_counter_t *tsc_new(void) { return NULL; }
void tsc_inc(ts_counter_t *c) { (void)c; }
long tsc_value(ts_counter_t *c) { (void)c; return 0; }
void tsc_free(ts_counter_t *c) { (void)c; }
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.