LCOV - code coverage report
Current view: top level - home/h/core/forks/m4-libzmq/src - atomic_counter.hpp (source / functions) Hit Total Coverage
Test: zeromq-4.2.0 Code Coverage Lines: 7 7 100.0 %
Date: 2016-05-09 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :     Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
       3             : 
       4             :     This file is part of libzmq, the ZeroMQ core engine in C++.
       5             : 
       6             :     libzmq is free software; you can redistribute it and/or modify it under
       7             :     the terms of the GNU Lesser General Public License (LGPL) as published
       8             :     by the Free Software Foundation; either version 3 of the License, or
       9             :     (at your option) any later version.
      10             : 
      11             :     As a special exception, the Contributors give you permission to link
      12             :     this library with independent modules to produce an executable,
      13             :     regardless of the license terms of these independent modules, and to
      14             :     copy and distribute the resulting executable under terms of your choice,
      15             :     provided that you also meet, for each linked independent module, the
      16             :     terms and conditions of the license of that module. An independent
      17             :     module is a module which is not derived from or based on this library.
      18             :     If you modify this library, you must extend this exception to your
      19             :     version of the library.
      20             : 
      21             :     libzmq is distributed in the hope that it will be useful, but WITHOUT
      22             :     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      23             :     FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
      24             :     License for more details.
      25             : 
      26             :     You should have received a copy of the GNU Lesser General Public License
      27             :     along with this program.  If not, see <http://www.gnu.org/licenses/>.
      28             : */
      29             : 
      30             : #ifndef __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
      31             : #define __ZMQ_ATOMIC_COUNTER_HPP_INCLUDED__
      32             : 
      33             : #include "stdint.hpp"
      34             : #include "platform.hpp"
      35             : 
      36             : #if defined ZMQ_FORCE_MUTEXES
      37             : #define ZMQ_ATOMIC_COUNTER_MUTEX
      38             : #elif defined ZMQ_HAVE_ATOMIC_INTRINSICS
      39             : #define ZMQ_ATOMIC_COUNTER_INTRINSIC
      40             : #elif (defined ZMQ_CXX11 && defined __cplusplus && __cplusplus >= 201103L)
      41             : #define ZMQ_ATOMIC_COUNTER_CXX11
      42             : #elif (defined __i386__ || defined __x86_64__) && defined __GNUC__
      43             : #define ZMQ_ATOMIC_COUNTER_X86
      44             : #elif defined __ARM_ARCH_7A__ && defined __GNUC__
      45             : #define ZMQ_ATOMIC_COUNTER_ARM
      46             : #elif defined ZMQ_HAVE_WINDOWS
      47             : #define ZMQ_ATOMIC_COUNTER_WINDOWS
      48             : #elif (defined ZMQ_HAVE_SOLARIS || defined ZMQ_HAVE_NETBSD || defined ZMQ_HAVE_GNU)
      49             : #define ZMQ_ATOMIC_COUNTER_ATOMIC_H
      50             : #elif defined __tile__
      51             : #define ZMQ_ATOMIC_COUNTER_TILE
      52             : #else
      53             : #define ZMQ_ATOMIC_COUNTER_MUTEX
      54             : #endif
      55             : 
      56             : #if defined ZMQ_ATOMIC_COUNTER_MUTEX
      57             : #include "mutex.hpp"
      58             : #elif defined ZMQ_ATOMIC_COUNTER_CXX11
      59             : #include <atomic>
      60             : #elif defined ZMQ_ATOMIC_COUNTER_WINDOWS
      61             : #include "windows.hpp"
      62             : #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
      63             : #include <atomic.h>
      64             : #elif defined ZMQ_ATOMIC_COUNTER_TILE
      65             : #include <arch/atomic.h>
      66             : #endif
      67             : 
      68             : namespace zmq
      69             : {
      70             : 
      71             :     //  This class represents an integer that can be incremented/decremented
      72             :     //  in atomic fashion.
      73             : 
      74             :     class atomic_counter_t
      75             :     {
      76             :     public:
      77             : 
      78             :         typedef uint32_t integer_t;
      79             : 
      80             :         inline atomic_counter_t (integer_t value_ = 0) :
      81       34722 :             value (value_)
      82             :         {
      83             :         }
      84             : 
      85         243 :         inline ~atomic_counter_t ()
      86             :         {
      87         243 :         }
      88             : 
      89             :         //  Set counter value (not thread-safe).
      90             :         inline void set (integer_t value_)
      91             :         {
      92        9059 :             value = value_;
      93             :         }
      94             : 
      95             :         //  Atomic addition. Returns the old value.
      96             :         inline integer_t add (integer_t increment_)
      97             :         {
      98             :             integer_t old_value;
      99             : 
     100             : #if defined ZMQ_ATOMIC_COUNTER_WINDOWS
     101             :             old_value = InterlockedExchangeAdd ((LONG*) &value, increment_);
     102             : #elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
     103      705349 :             old_value = __atomic_fetch_add(&value, increment_, __ATOMIC_ACQ_REL);
     104             : #elif defined ZMQ_ATOMIC_COUNTER_CXX11
     105             :             old_value = value.fetch_add(increment_, std::memory_order_acq_rel);
     106             : #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
     107             :             integer_t new_value = atomic_add_32_nv (&value, increment_);
     108             :             old_value = new_value - increment_;
     109             : #elif defined ZMQ_ATOMIC_COUNTER_TILE
     110             :             old_value = arch_atomic_add (&value, increment_);
     111             : #elif defined ZMQ_ATOMIC_COUNTER_X86
     112             :             __asm__ volatile (
     113             :                 "lock; xadd %0, %1 \n\t"
     114             :                 : "=r" (old_value), "=m" (value)
     115             :                 : "0" (increment_), "m" (value)
     116             :                 : "cc", "memory");
     117             : #elif defined ZMQ_ATOMIC_COUNTER_ARM
     118             :             integer_t flag, tmp;
     119             :             __asm__ volatile (
     120             :                 "       dmb     sy\n\t"
     121             :                 "1:     ldrex   %0, [%5]\n\t"
     122             :                 "       add     %2, %0, %4\n\t"
     123             :                 "       strex   %1, %2, [%5]\n\t"
     124             :                 "       teq     %1, #0\n\t"
     125             :                 "       bne     1b\n\t"
     126             :                 "       dmb     sy\n\t"
     127             :                 : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value)
     128             :                 : "Ir"(increment_), "r"(&value)
     129             :                 : "cc");
     130             : #elif defined ZMQ_ATOMIC_COUNTER_MUTEX
     131             :             sync.lock ();
     132             :             old_value = value;
     133             :             value += increment_;
     134             :             sync.unlock ();
     135             : #else
     136             : #error atomic_counter is not implemented for this platform
     137             : #endif
     138             :             return old_value;
     139             :         }
     140             : 
     141             :         //  Atomic subtraction. Returns false if the counter drops to zero.
     142             :         inline bool sub (integer_t decrement)
     143             :         {
     144             : #if defined ZMQ_ATOMIC_COUNTER_WINDOWS
     145             :             LONG delta = - ((LONG) decrement);
     146             :             integer_t old = InterlockedExchangeAdd ((LONG*) &value, delta);
     147             :             return old - decrement != 0;
     148             : #elif defined ZMQ_ATOMIC_COUNTER_INTRINSIC
     149      677193 :             integer_t nv = __atomic_sub_fetch(&value, decrement, __ATOMIC_ACQ_REL);
     150             :             return nv != 0;
     151             : #elif defined ZMQ_ATOMIC_COUNTER_CXX11
     152             :             integer_t old = value.fetch_sub(decrement, std::memory_order_acq_rel);
     153             :             return old - decrement != 0;
     154             : #elif defined ZMQ_ATOMIC_COUNTER_ATOMIC_H
     155             :             int32_t delta = - ((int32_t) decrement);
     156             :             integer_t nv = atomic_add_32_nv (&value, delta);
     157             :             return nv != 0;
     158             : #elif defined ZMQ_ATOMIC_COUNTER_TILE
     159             :             int32_t delta = - ((int32_t) decrement);
     160             :             integer_t nv = arch_atomic_add (&value, delta);
     161             :             return nv != 0;
     162             : #elif defined ZMQ_ATOMIC_COUNTER_X86
     163             :             integer_t oldval = -decrement;
     164             :             volatile integer_t *val = &value;
     165             :             __asm__ volatile ("lock; xaddl %0,%1"
     166             :                 : "=r" (oldval), "=m" (*val)
     167             :                 : "0" (oldval), "m" (*val)
     168             :                 : "cc", "memory");
     169             :             return oldval != decrement;
     170             : #elif defined ZMQ_ATOMIC_COUNTER_ARM
     171             :             integer_t old_value, flag, tmp;
     172             :             __asm__ volatile (
     173             :                 "       dmb     sy\n\t"
     174             :                 "1:     ldrex   %0, [%5]\n\t"
     175             :                 "       sub     %2, %0, %4\n\t"
     176             :                 "       strex   %1, %2, [%5]\n\t"
     177             :                 "       teq     %1, #0\n\t"
     178             :                 "       bne     1b\n\t"
     179             :                 "       dmb     sy\n\t"
     180             :                 : "=&r"(old_value), "=&r"(flag), "=&r"(tmp), "+Qo"(value)
     181             :                 : "Ir"(decrement), "r"(&value)
     182             :                 : "cc");
     183             :             return old_value - decrement != 0;
     184             : #elif defined ZMQ_ATOMIC_COUNTER_MUTEX
     185             :             sync.lock ();
     186             :             value -= decrement;
     187             :             bool result = value ? true : false;
     188             :             sync.unlock ();
     189             :             return result;
     190             : #else
     191             : #error atomic_counter is not implemented for this platform
     192             : #endif
     193             :         }
     194             : 
     195             :         inline integer_t get () const
     196             :         {
     197      111986 :             return value;
     198             :         }
     199             : 
     200             :     private:
     201             : 
     202             : #if defined ZMQ_ATOMIC_COUNTER_CXX11
     203             :         std::atomic<integer_t> value;
     204             : #else
     205             :         volatile integer_t value;
     206             : #endif
     207             : 
     208             : #if defined ZMQ_ATOMIC_COUNTER_MUTEX
     209             :         mutex_t sync;
     210             : #endif
     211             : 
     212             : #if ! defined ZMQ_ATOMIC_COUNTER_CXX11
     213             :         atomic_counter_t (const atomic_counter_t&);
     214             :         const atomic_counter_t& operator = (const atomic_counter_t&);
     215             : #endif
     216             :     };
     217             : 
     218             : }
     219             : 
     220             : //  Remove macros local to this file.
     221             : #undef ZMQ_ATOMIC_COUNTER_MUTEX
     222             : #undef ZMQ_ATOMIC_COUNTER_INTRINSIC
     223             : #undef ZMQ_ATOMIC_COUNTER_CXX11
     224             : #undef ZMQ_ATOMIC_COUNTER_X86
     225             : #undef ZMQ_ATOMIC_COUNTER_ARM
     226             : #undef ZMQ_ATOMIC_COUNTER_WINDOWS
     227             : #undef ZMQ_ATOMIC_COUNTER_ATOMIC_H
     228             : #undef ZMQ_ATOMIC_COUNTER_TILE
     229             : 
     230             : #endif

Generated by: LCOV version 1.10