PageRenderTime 19ms CodeModel.GetById 13ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/sparrowhawk/foundation/ESFSharedCounter.h

http://github.com/jtblatt/duderino
C Header | 157 lines | 93 code | 36 blank | 28 comment | 1 complexity | f4db596c085c5b474fdcb34f2a711a06 MD5 | raw file
  1/** @file ESFSharedCounter.h
  2 *  @brief A threadsafe counter
  3 *
  4 * Copyright (c) 2011 Yahoo! Inc.
  5 * The copyrights embodied in the content of this file are licensed by Yahoo! Inc.
  6 * under the BSD (revised) open source license.
  7 *
  8 * Derived from code that is Copyright (c) 2009 Joshua Blatt and offered under both
  9 * BSD and Apache 2.0 licenses (http://sourceforge.net/projects/sparrowhawk/).
 10 *
 11 *    $Author: blattj $
 12 *    $Date: 2009/05/25 21:51:08 $
 13 *    $Name:  $
 14 *    $Revision: 1.3 $
 15 */
 16
 17#ifndef ESF_SHARED_COUNTER_H
 18#define ESF_SHARED_COUNTER_H
 19
 20#ifndef ESF_CONFIG_H
 21#include <ESFConfig.h>
 22#endif
 23
 24#ifndef ESF_ALLOCATOR_H
 25#include <ESFAllocator.h>
 26#endif
 27
 28#ifndef HAVE_X86_ASM
 29
 30#ifndef ESF_MUTEX_H
 31#include <ESFMutex.h>
 32#endif
 33
 34#endif
 35
 36/** @defgroup counter Counters */
 37
 38/** ESFSharedCounter is an integer type that can be safely accessed by
 39 *  multiple threads.
 40 *
 41 *  @ingroup counter
 42 */
 43class ESFSharedCounter {
 44public:
 45    /**    Default constructor. */
 46    ESFSharedCounter();
 47
 48    ESFSharedCounter(ESFSharedCounter &counter);
 49
 50    virtual ~ESFSharedCounter();
 51
 52    ESFSharedCounter &operator=(ESFSharedCounter &counter);
 53
 54    inline void set(int value) {
 55        _counter = value;
 56    }
 57
 58    inline int get() const {
 59        return _counter;
 60    }
 61
 62    inline int inc() {
 63        unsigned int counter = 0;
 64
 65#ifdef HAVE_X86_ASM
 66        __asm__ __volatile__("lock; incl %0; movl %0, %1"
 67                :"=m" (_counter), "=r" (counter)
 68                :"m" (_counter)
 69                : "memory");
 70#else
 71        _lock.writeAcquire();
 72
 73        counter = _counter++;
 74
 75        _lock.writeRelease();
 76#endif
 77
 78        return counter;
 79    }
 80
 81    inline int dec() {
 82        unsigned int counter = 0;
 83
 84#ifdef HAVE_X86_ASM
 85        __asm__ __volatile__("lock; decl %0; movl %0, %1"
 86                :"=m" (_counter), "=r" (counter)
 87                :"m" (_counter)
 88                : "memory");
 89#else
 90        _lock.writeAcquire();
 91
 92        counter = _counter--;
 93
 94        _lock.writeRelease();
 95#endif
 96
 97        return counter;
 98    }
 99
100    inline void add(int value) {
101#ifdef HAVE_X86_ASM
102        __asm__ __volatile__("lock ; addl %1,%0"
103                :"=m" (_counter)
104                :"ir" (value), "m" (_counter));
105#else
106        _lock.writeAcquire();
107
108        _counter += value;
109
110        _lock.writeRelease();
111#endif
112    }
113
114    inline void sub(int value) {
115#ifdef HAVE_X86_ASM
116        __asm__ __volatile__("lock ; subl %1,%0"
117                :"=m" (_counter)
118                :"ir" (value), "m" (_counter));
119#else
120        _lock.writeAcquire();
121
122        _counter -= value;
123
124        _lock.writeRelease();
125#endif
126    }
127
128    inline bool decAndTest() {
129        unsigned char c;
130
131        __asm__ __volatile__("lock ; decl %0; sete %1"
132                :"=m" (_counter), "=qm" (c)
133                :"m" (_counter)
134                : "memory");
135        return c != 0;
136    }
137
138    /** Placement new.
139     *
140     *  @param size The size of the object.
141     *  @param allocator The source of the object's memory.
142     *  @return The new object or NULL of the memory allocation failed.
143     */
144    inline void *operator new(size_t size, ESFAllocator *allocator) {
145        return allocator->allocate(size);
146    }
147
148private:
149
150#ifndef HAVE_X86_ASM
151    ESFMutex _lock;
152#endif
153
154    volatile int _counter;
155};
156
157#endif /* ! ESF_SHARED_COUNTER_H */