LoggedAtomic: Expand set of operations supported, serialize logging 09/69009/4
authorDave Rigby <daver@couchbase.com>
Wed, 19 Oct 2016 10:20:40 +0000 (11:20 +0100)
committerDave Rigby <daver@couchbase.com>
Fri, 21 Oct 2016 10:46:45 +0000 (10:46 +0000)
Add support for increment & decrement (fetch_{add,sub}), assignment
and conversion to T.

Also add a mutex to serialize access to stderr, to prevent corruption
in log messages.

Change-Id: I0a617f702a22d287fb87bd1001ee0300b6551b9e
Reviewed-on: http://review.couchbase.org/69009
Tested-by: buildbot <build@couchbase.com>
Reviewed-by: Daniel Owen <owend@couchbase.com>
Reviewed-by: Jim Walker <jim@couchbase.com>
Reviewed-by: Will Gardner <willg@rdner.io>
src/atomic.h

index 55cb63e..a32418d 100644 (file)
@@ -339,22 +339,63 @@ class LoggedAtomic {
 public:
     LoggedAtomic(T initial)
         : value(initial) {
-        std::cerr << "LoggedAtomic[" << this << "]::LoggedAtomic: " << value.load() << std::endl;
+        std::lock_guard<std::mutex> lock(stderr_mutex);
+        std::cerr << "LoggedAtomic[" << this << "]::LoggedAtomic: "
+                  << value.load() << std::endl;
 
     }
 
+    T operator=(T desired) {
+        std::lock_guard<std::mutex> lock(stderr_mutex);
+        value.store(desired);
+        std::cerr << "LoggedAtomic[" << this << "]::operator=: "
+                  << value.load() << std::endl;
+        return value.load();
+    }
+
     T load() const {
+        std::lock_guard<std::mutex> lock(stderr_mutex);
         auto result = value.load();
-        std::cerr << "LoggedAtomic[" << this << "]::load: " << result << std::endl;
+        std::cerr << "LoggedAtomic[" << this << "]::load: " << result
+                  << std::endl;
         return result;
     }
 
     void store(T desired) {
+        std::lock_guard<std::mutex> lock(stderr_mutex);
         value.store(desired);
-        std::cerr << "LoggedAtomic[" << this << "]::store: " << value.load() << std::endl;
+        std::cerr << "LoggedAtomic[" << this << "]::store: " << value.load()
+                  << std::endl;
+    }
+
+    operator T() const {
+        std::lock_guard<std::mutex> lock(stderr_mutex);
+        auto result = value.load();
+        std::cerr << "LoggedAtomic[" << this << "]::operator T: " << result
+                  << std::endl;
+        return result;
+    }
+
+    T fetch_add(T arg,
+                std::memory_order order = std::memory_order_seq_cst ) {
+        std::lock_guard<std::mutex> lock(stderr_mutex);
+        T result = value.fetch_add(arg, order);
+        std::cerr << "LoggedAtomic[" << this << "]::fetch_add(" << arg
+                  << "): " << result << std::endl;
+        return value.load();
+    }
+
+    T fetch_sub(T arg,
+                std::memory_order order = std::memory_order_seq_cst ) {
+        std::lock_guard<std::mutex> lock(stderr_mutex);
+        T result = value.fetch_sub(arg, order);
+        std::cerr << "LoggedAtomic[" << this << "]::fetch_sub(" << arg
+                  << "): " << result << std::endl;
+        return value.load();
     }
 
 protected:
+    mutable std::mutex stderr_mutex;
     std::atomic<T> value;
 };