From: Ben Pfaff Date: Mon, 12 Aug 2013 20:45:01 +0000 (-0700) Subject: seq: Add some comments. X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=5d389d55c78a20bd18b68b35f0e6cabae2686dcb;p=sliver-openvswitch.git seq: Add some comments. Signed-off-by: Ben Pfaff --- diff --git a/lib/seq.c b/lib/seq.c index abe1ad8e1..36e506570 100644 --- a/lib/seq.c +++ b/lib/seq.c @@ -106,7 +106,11 @@ seq_change(struct seq *seq) ovs_mutex_unlock(&seq_mutex); } -/* Returns 'seq''s current sequence number (which could change immediately). */ +/* Returns 'seq''s current sequence number (which could change immediately). + * + * seq_read() and seq_wait() can be used together to yield a race-free wakeup + * when an object changes, even without an ability to lock the object. See + * Usage in seq.h for details. */ uint64_t seq_read(const struct seq *seq) OVS_EXCLUDED(seq_mutex) @@ -156,7 +160,11 @@ seq_wait__(struct seq *seq, uint64_t value) /* Causes the following poll_block() to wake up when 'seq''s sequence number * changes from 'value'. (If 'seq''s sequence number isn't 'value', then - * poll_block() won't block at all.) */ + * poll_block() won't block at all.) + * + * seq_read() and seq_wait() can be used together to yield a race-free wakeup + * when an object changes, even without an ability to lock the object. See + * Usage in seq.h for details. */ void seq_wait(const struct seq *seq_, uint64_t value) OVS_EXCLUDED(seq_mutex) diff --git a/lib/seq.h b/lib/seq.h index 3423e217d..c764809e5 100644 --- a/lib/seq.h +++ b/lib/seq.h @@ -20,7 +20,7 @@ /* Thread-safe, pollable sequence number. * * - * Background + * Motivation * ========== * * It is sometimes desirable to take an action whenever an object changes. @@ -66,6 +66,44 @@ * poll_block(); * * + * Alternate Usage + * =============== + * + * struct seq can also be used as a sort of pollable condition variable. + * Suppose that we want a thread to process items in a queue, and thus to be + * able to wake up whenever the queue is nonempty. This requires a lock to + * protect the queue and a seq to signal that the queue has become nonempty, + * e.g.: + * + * struct ovs_mutex mutex; + * struct list queue OVS_GUARDED_BY(mutex); + * struct seq nonempty_seq; + * + * To add an element to the queue: + * + * ovs_mutex_lock(&mutex); + * list_push_back(&queue, ...element...); + * if (list_is_singleton(&queue)) { // The 'if' test here is optional. + * seq_change(&nonempty_seq); + * } + * ovs_mutex_unlock(&mutex); + * + * To wait for the queue to become nonempty: + * + * ovs_mutex_lock(&mutex); + * if (list_is_empty(&queue)) { + * seq_wait(&nonempty_seq, seq_read(&nonempty_seq)); + * } else { + * poll_immediate_wake(); + * } + * ovs_mutex_unlock(&mutex); + * + * (In the above code 'mutex' prevents the queue from changing between + * seq_read() and seq_wait(). Otherwise, it would be necessary to seq_read(), + * check for a nonempty queue, and then seq_wait() on the previously read + * sequence number, as under Usage above.) + * + * * Thread-safety * ============= *