/*
- * Copyright (c) 2013 Nicira, Inc.
+ * Copyright (c) 2013, 2014 Nicira, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/* Thread-safe, pollable sequence number.
*
*
- * Background
+ * Motivation
* ==========
*
* It is sometimes desirable to take an action whenever an object changes.
* 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 ovs_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
* =============
*
- * Fully thread safe.
+ * Fully thread safe. seq_change() synchronizes with seq_read() and
+ * seq_wait() on the same variable in release-acquire fashion. That
+ * is, all effects of the memory accesses performed by a thread prior
+ * to seq_change() are visible to the threads returning from
+ * seq_read() or seq_wait() observing that change.
*/
#include <stdint.h>
+#include "util.h"
/* For implementation of an object with a sequence number attached. */
struct seq *seq_create(void);
/* For observers. */
uint64_t seq_read(const struct seq *);
-void seq_wait(const struct seq *, uint64_t value);
+
+void seq_wait_at(const struct seq *, uint64_t value, const char *where);
+#define seq_wait(seq, value) seq_wait_at(seq, value, OVS_SOURCE_LOCATOR)
/* For poll_block() internal use. */
void seq_woke(void);