1 /* 2 * This file is part of PowerDNS or dnsdist. 3 * Copyright -- PowerDNS.COM B.V. and its contributors 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * In addition, for the avoidance of any doubt, permission is granted to 10 * link this program with OpenSSL and to (re)distribute the binaries 11 * produced as the result of such linking. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 */ 22 #pragma once 23 24 #define CPU_LEVEL1_DCACHE_LINESIZE 64 // Until we know better via configure/getconf 25 26 namespace pdns { 27 template <typename T> 28 class stat_t_trait { 29 public: 30 typedef T base_t; 31 typedef std::atomic<base_t> atomic_t; 32 stat_t_trait()33 stat_t_trait() : stat_t_trait(base_t(0)) { 34 } stat_t_trait(const base_t x)35 stat_t_trait(const base_t x) { 36 new(&counter) atomic_t(x); 37 } ~stat_t_trait()38 ~stat_t_trait() { 39 reinterpret_cast<atomic_t *>(&counter)->~atomic_t(); 40 } 41 stat_t_trait(const stat_t_trait&) = delete; operator ++(int)42 base_t operator++(int) { 43 return (*reinterpret_cast<atomic_t *>(&counter))++; 44 } operator ++()45 base_t operator++() { 46 return ++(*reinterpret_cast<atomic_t *>(&counter)); 47 } operator --(int)48 base_t operator--(int) { 49 return (*reinterpret_cast<atomic_t *>(&counter))--; 50 } operator --()51 base_t operator--() { 52 return --(*reinterpret_cast<atomic_t *>(&counter)); 53 } operator +=(const stat_t_trait & v)54 base_t operator+=(const stat_t_trait& v) { 55 return *reinterpret_cast<atomic_t *>(&counter) += *reinterpret_cast<const atomic_t *>(&v.counter); 56 } operator -=(const stat_t_trait & v)57 base_t operator-=(const stat_t_trait& v) { 58 return *reinterpret_cast<atomic_t *>(&counter) -= *reinterpret_cast<const atomic_t *>(&v.counter); 59 } load() const60 base_t load() const { 61 return reinterpret_cast<const atomic_t *>(&counter)->load(); 62 } store(base_t v)63 void store(base_t v) { 64 reinterpret_cast<atomic_t *>(&counter)->store(v); 65 } operator base_t() const66 operator base_t() const { 67 return reinterpret_cast<const atomic_t *>(&counter)->load(); 68 } 69 70 private: 71 typename std::aligned_storage<sizeof(base_t), CPU_LEVEL1_DCACHE_LINESIZE>::type counter; 72 }; 73 74 typedef stat_t_trait<uint64_t> stat_t; 75 typedef stat_t_trait<uint32_t> stat32_t; 76 typedef stat_t_trait<uint16_t> stat16_t; 77 } 78