From 354bb40e75d94466e91fe6960523612c9d17ccfb Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Thu, 2 Nov 2017 23:11:29 +0300 Subject: Add implementation --- mysql/sql/atomic_class.h | 117 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 mysql/sql/atomic_class.h (limited to 'mysql/sql/atomic_class.h') diff --git a/mysql/sql/atomic_class.h b/mysql/sql/atomic_class.h new file mode 100644 index 0000000..04d3492 --- /dev/null +++ b/mysql/sql/atomic_class.h @@ -0,0 +1,117 @@ +/* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + + 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; version 2 of the + License. + + 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 St, Fifth Floor, Boston, MA + 02110-1301 USA */ + + +#ifndef ATOMIC_CLASS_H_INCLUDED +#define ATOMIC_CLASS_H_INCLUDED + +#include "my_atomic.h" + +/** + Wrapper class to use C++ syntax to access atomic integers. +*/ +#define DEFINE_ATOMIC_CLASS(NAME, SUFFIX, TYPE) \ + class Atomic_##NAME \ + { \ +public: \ + /* Create a new Atomic_* object. */ \ + Atomic_##NAME(TYPE n= 0) \ + { \ + my_atomic_store##SUFFIX(&value, n); \ + } \ + /* Atomically read the value. */ \ + TYPE atomic_get() \ + { \ + return my_atomic_load##SUFFIX(&value); \ + } \ + /* Atomically set the value. */ \ + void atomic_set(TYPE n) \ + { \ + my_atomic_store##SUFFIX(&value, n); \ + } \ + /* Atomically add to the value, and return the old value. */ \ + TYPE atomic_add(TYPE n) \ + { \ + return my_atomic_add##SUFFIX(&value, n); \ + } \ + /* Atomically set the value and return the old value. */ \ + TYPE atomic_get_and_set(TYPE n) \ + { \ + return my_atomic_fas##SUFFIX(&value, n); \ + } \ + /* If the old value is equal to *old, set the value to new and */ \ + /* return true. Otherwise, store the old value in '*old' and */ \ + /* return false. */ \ + bool atomic_compare_and_swap(TYPE *old, TYPE n) \ + { \ + return my_atomic_cas##SUFFIX(&value, old, n); \ + } \ + /* Read the value *non-atomically*. */ \ + TYPE non_atomic_get() \ + { \ + return value; \ + } \ + /* Set the value *non-atomically*. */ \ + void non_atomic_set(TYPE n) \ + { \ + value= n; \ + } \ + /* Add to the value *non-atomically*. */ \ + TYPE non_atomic_add(TYPE n) \ + { \ + TYPE ret= value; \ + value+= n; \ + return ret; \ + } \ + /* Set the value to the greatest of (old, n). */ \ + \ + /* The function will internally requires multiple atomic */ \ + /* operations. If the old value is known (or guessed), and less */ \ + /* than n, it requires one atomic operation less. Therefore, */ \ + /* the caller should set *guess to whatever is the likely value */ \ + /* that the variable currently has, if such a guess is known. */ \ + \ + /* @return If the new value is changed to n, *guess is set to */ \ + /* the old value and the the function returns true. Otherwise, */ \ + /* *guess is set to the current value (which is greater than or */ \ + /* equal to n), and the function returns false. */ \ + bool atomic_set_to_max(TYPE n, TYPE *guess= NULL) \ + { \ + TYPE _guess; \ + if (guess == NULL) \ + { \ + _guess= n - 1; \ + guess= &_guess; \ + } \ + else \ + DBUG_ASSERT(*guess < n); \ + bool ret; \ + do { \ + ret= atomic_compare_and_swap(guess, n); \ + } while (!ret && *guess < n); \ + return ret; \ + } \ + \ +private: \ + TYPE value; \ + } + +DEFINE_ATOMIC_CLASS(int32, 32, int32); +DEFINE_ATOMIC_CLASS(int64, 64, int64); +//DEFINE_ATOMIC_CLASS(pointer, ptr, void *); + +#endif //ifndef ATOMIC_CLASS_H_INCLUDED -- cgit v1.1