From 45ac4fa56b6e5c31a28fd08eaad14a09bf3934f6 Mon Sep 17 00:00:00 2001 From: gdamore Date: Sun, 27 Oct 2024 18:55:51 +0000 Subject: deploy: ffeb31c64ea72c4eb287f75b641ca2a707df90b0 --- ref/api/synch.html | 438 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 438 insertions(+) create mode 100644 ref/api/synch.html (limited to 'ref/api/synch.html') diff --git a/ref/api/synch.html b/ref/api/synch.html new file mode 100644 index 00000000..1ac1cd57 --- /dev/null +++ b/ref/api/synch.html @@ -0,0 +1,438 @@ + + + + + + Synchronization - NNG Reference Manual (DRAFT) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + + + + + +
+
+ +

Synchronization Primitives

+

In order to allow safely accessing shared state, or to allow coordination between +different threads, NNG provides synchronization primitives in the +form of mutual exclusion locks and condition variables.

+

Correct use of these primitives will be needed when accessing shared state from +threads, or from callback functions associated with asynchronous operations. +(The need to do this in callbacks is because the callback may be executed under +a task thread other than the submitting thread.)

+

Mutual Exclusion Lock

+
typedef struct nng_mtx nng_mtx;
+
+

Mutual exclusion locks, or mutex locks, represented by the nng_mtx structure, +allow only a single thread to lock “own” the lock, acquired by nng_mtx_lock. +Any other thread trying to acquire the same mutex will wait until the owner has released the mutex +by calling nng_mtx_unlock.

+

Creating a Mutex

+
int nng_mutx_alloc(nng_mt **mtxp);
+
+

A mutex can be created by allocating one with nng_mtx_lock. +On success, a pointer to the mutex is returned through mtxp. +This function can fail due to insufficient memory or resources, in which +case it will return NNG_ENOMEM. Otherwise it will succceed and return zero.

+

Destroying a Mutex

+
void nng_mtx_free(nng_mtx *mtx);
+
+

When no longer needed, a mutex can be deallocated and its resources returned +to the caller, by calling nng_mtx_free. The mutex must not be locked +by any thread when calling this function.

+

Acquiring a Mutex

+
void nng_mtx_lock(nng_mtx *mtx);
+
+

The nng_mtx_lock function acquires ownership of a mutex, waiting for it to +unowned by any other threads if necessary.

+
+

+ + important +

+

A thread must not attempt to reqacuire the same mutex while it already “owns” the mutex. +If it does attempt to do so, the result will be a single party deadlock.

+
+

Releasing a Mutex

+
void nng_mtx_unlock(nng_mtx *mtx);
+
+

The nng_mtx_unlock function releases a mutex that the calling thread has previously +acquired with nng_mtx_lock.

+
+

+ + important +

+

A thread must not attempt to release (unlock) a mutex if it was not the thread +that acquired the mutex to begin with.

+
+

Condition Variable

+
typedef struct nng_cv nng_cv;
+
+

The nng_cv structure implements a condition variable, associated with the +the mutex mtx which was supplied when it was created.

+

Condition variables provide for a way to wait on an arbitrary condition, and to be woken +when the condition is signaled. +The mutex is dropped while the caller is asleep, and reacquired atomically when the caller +is woken.

+
+

+ + important +

+

The caller of nng_cv_until, nng_cv_wait, nng_cv_wake, and nng_cv_wake1 must +have ownership of the mutex mtx when calling these functions.

+
+

Creating a Condition Variable

+
int nng_cv_alloc(nng_cv **cvp, nng_mtx *mtx);
+
+

The nng_cv_alloc function allocates a condition variable, and associated with the mutex mtx, +and returns a pointer to it in cvp.

+

Destroy a Condition Variable

+
void nng_cv_free(nng_cv *cv);
+
+

The nng_cv_free function deallocates the condition variable cv.

+

Waiting for the Condition

+
int nng_cv_until(nng_cv *cv, nng_time when);
+void nng_cv_wait(nng_cv *cv);
+
+

The nng_cv_until and nng_cv_wait functions put the caller to sleep until the condition +variable cv is signaled, or (in the case of nng_cv_until), the specified time when +(as determined by nng_clock is reached.

+

While nng_cv_wait never fails and so has no return value, the nng_cv_until function can +return NNG_ETIMEDOUT if the time is reached before condition cv is signaled by +either nng_cv_wake or nng_cv_wake1.

+

Signaling the Condition

+
void nng_cv_wake(nng_cv *cv);
+void nng_cv_wake1(nng_cv *cv);
+
+

The nng_cv_wake and nng_cv_wake1 functions wake threads waiting in +nng_cv_until or nng_cv_wait. +The difference between these functions is that +nng_cv_wake will wake every thread, whereas nng_cv_wake1 will wake up exactly +one thread (which may be chosen randomly).

+
+

+ + tip +

+

Use of nng_cv_wake1 may be used to reduce the “thundering herd” syndrom of waking +all threads concurrently, but should only be used in circumstances where the application +does not depend on which thread will be woken. When in doubt, nng_cv_wake is safer.

+
+

Examples

+

Example 1: Allocating the condition variable

+
	nng_mtx *m;
+	nng_cv *cv;
+	nng_mtx_alloc(&m); // error checks elided
+	nng_cv_alloc(&cv, m);
+
+

Example 2: Waiting for the condition

+
    expire = nng_clock() + 1000; // 1 second in the future
+    nng_mtx_lock(m);  // assume cv was allocated using m
+    while (!condition_true) {
+        if (nng_cv_until(cv, expire) == NNG_ETIMEDOUT) {
+            printf("Time out reached!\n");
+            break;
+        }
+    }
+    // condition_true is true
+    nng_mtx_unlock(m);
+
+

Example 3: Signaling the condition

+
    nng_mtx_lock(m);
+    condition_true = true;
+    nng_cv_wake(cv);
+    nng_mtx_unlock(m);
+
+ + + + + +

See Also

+

Threads, +Time, +Asynchronous I/O

+ +
+ + +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + +
+ + -- cgit v1.2.3-70-g09d2