- const Statistic &operator=(unsigned Val) { Value = Val; return *this; }
- const Statistic &operator++() { ++Value; return *this; }
- unsigned operator++(int) { return Value++; }
- const Statistic &operator--() { --Value; return *this; }
- unsigned operator--(int) { return Value--; }
- const Statistic &operator+=(const unsigned &V) { Value += V; return *this; }
- const Statistic &operator-=(const unsigned &V) { Value -= V; return *this; }
- const Statistic &operator*=(const unsigned &V) { Value *= V; return *this; }
- const Statistic &operator/=(const unsigned &V) { Value /= V; return *this; }
+ const Statistic &operator=(unsigned Val) {
+ Value = Val;
+ return init();
+ }
+
+ const Statistic &operator++() {
+ // FIXME: This function and all those that follow carefully use an
+ // atomic operation to update the value safely in the presence of
+ // concurrent accesses, but not to read the return value, so the
+ // return value is not thread safe.
+ sys::AtomicIncrement(&Value);
+ return init();
+ }
+
+ unsigned operator++(int) {
+ init();
+ unsigned OldValue = Value;
+ sys::AtomicIncrement(&Value);
+ return OldValue;
+ }
+
+ const Statistic &operator--() {
+ sys::AtomicDecrement(&Value);
+ return init();
+ }
+
+ unsigned operator--(int) {
+ init();
+ unsigned OldValue = Value;
+ sys::AtomicDecrement(&Value);
+ return OldValue;
+ }
+
+ const Statistic &operator+=(const unsigned &V) {
+ if (!V) return *this;
+ sys::AtomicAdd(&Value, V);
+ return init();
+ }
+
+ const Statistic &operator-=(const unsigned &V) {
+ if (!V) return *this;
+ sys::AtomicAdd(&Value, -V);
+ return init();
+ }
+
+ const Statistic &operator*=(const unsigned &V) {
+ sys::AtomicMul(&Value, V);
+ return init();
+ }
+
+ const Statistic &operator/=(const unsigned &V) {
+ sys::AtomicDiv(&Value, V);
+ return init();
+ }
+
+protected:
+ Statistic &init() {
+ bool tmp = Initialized;
+ sys::MemoryFence();
+ if (!tmp) RegisterStatistic();
+ TsanHappensAfter(this);
+ return *this;
+ }
+ void RegisterStatistic();