summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2016-10-09 15:27:22 +0000
committerSergei Petrunia <psergey@askmonty.org>2016-10-09 15:27:22 +0000
commit20bd26e6df3acf739ff1b2cffc41084367cd6dd0 (patch)
tree83e589f67b6e860a8ef161498eb9299ea5421e4c /include
parent4be8cae56afd7a31eb2477e9e4fe1c814748b06d (diff)
downloadmariadb-git-20bd26e6df3acf739ff1b2cffc41084367cd6dd0.tar.gz
Backport from facebook/mysql-5.6:
commit b5fda565d4bad66f3b5a6432236b96743ccfd323 Author: Steaphan Greene <steaphan@fb.com> Date: Fri Feb 7 21:34:04 2014 -0800 Add basic atomic_stats type Summary: WebScaleSQL Feature: Basic Stats Support This is a simple class template that implements an atomic stats variable. The focus is on performance, not accuracy. No set operations are guaranteed. The other operations are all atomic, so values should not actually be lost - however, there is no attempt to be consistent in reading multiple stats, nor any concern that different threads see any consistent view across multiple stats. Test Plan: This has been tested quite a bit in isolation, and no problems have been found. However, this has never been used in production. Also, a newer, more sophisticated, version of this is already in development. It also shows a small perf gain in the larger stats diffs (Table Stats, User Stats, etc...), when compared to the built-in MySQL atomics. Reviewers: pivanof Reviewed By: pivanof CC: jtolmer, MarkCallaghan, flamingcow, jeremycole, andrew-ford, inaam-rana, liang.guo.752 Differential Revision: https://reviews.facebook.net/D16029 Differential Revision: https://reviews.facebook.net/D16449
Diffstat (limited to 'include')
-rw-r--r--include/atomic_stat.h94
1 files changed, 94 insertions, 0 deletions
diff --git a/include/atomic_stat.h b/include/atomic_stat.h
new file mode 100644
index 00000000000..04e59bd9a8a
--- /dev/null
+++ b/include/atomic_stat.h
@@ -0,0 +1,94 @@
+/* This is an atomic integer abstract data type, for high-performance
+ tracking of a single stat. It intentionally permits inconsistent
+ atomic operations and reads, for better performance. This means
+ that, though no data should ever be lost by this stat, reads of it
+ at any time may not include all changes up to any particular point.
+
+ So, values read from these may only be approximately correct.
+
+ If your use-case will fail under these conditions, do not use this.
+
+ Copyright (C) 2012 - 2014 Steaphan Greene <steaphan@gmail.com>
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License
+ as published by the Free Software Foundation; either version 2
+ of the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the
+ Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _atomic_stat_h_
+#define _atomic_stat_h_
+
+#include <atomic>
+
+template < typename TYPE >
+class atomic_stat {
+public:
+ // Initialize value to the default for the type
+ atomic_stat() : value_(TYPE()) {};
+
+ // This enforces a strict order, as all absolute sets should
+ void clear() {
+ value_.store(TYPE(), std::memory_order_seq_cst);
+ };
+
+ // Reads can get any valid value, it doesn't matter which, exactly
+ TYPE load() const {
+ return value_.load(std::memory_order_relaxed);
+ };
+
+ // This only supplies relative arithmetic operations
+ // These are all done atomically, and so can show up in any order
+ void inc(const TYPE &other) {
+ value_.fetch_add(other, std::memory_order_relaxed);
+ };
+
+ void dec(const TYPE &other) {
+ value_.fetch_sub(other, std::memory_order_relaxed);
+ };
+
+ void inc() {
+ value_.fetch_add(1, std::memory_order_relaxed);
+ };
+
+ void dec() {
+ value_.fetch_sub(1, std::memory_order_relaxed);
+ };
+
+ // This will make one attempt to set the value to the max of
+ // the current value, and the passed-in value. It can fail
+ // for any reason, and we only try it once.
+ void set_max_maybe(const TYPE &new_val) {
+ TYPE old_val = value_;
+ if (new_val > old_val) {
+ value_.compare_exchange_weak(old_val, new_val,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ }
+ };
+
+ // This will make one attempt to assign the value to the passed-in
+ // value. It can fail for any reason, and we only try it once.
+ void set_maybe(const TYPE &new_val) {
+ TYPE old_val = value_;
+ value_.compare_exchange_weak(old_val, new_val,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ };
+
+private:
+ std::atomic<TYPE> value_;
+};
+
+#endif // _atomic_stat_h_