1/*
2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11// Atomic system independant 32-bit signed integer.
12// Mac implementation.
13#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
14#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
15
16#include <stdlib.h>
17#include <libkern/OSAtomic.h>
18
19#include "common_types.h"
20
21namespace webrtc {
22class Atomic32Impl
23{
24public:
25    inline Atomic32Impl(WebRtc_Word32 initialValue);
26    inline ~Atomic32Impl();
27
28    inline WebRtc_Word32 operator++();
29    inline WebRtc_Word32 operator--();
30
31    inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
32    inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
33    inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
34    inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
35
36    inline bool CompareExchange(WebRtc_Word32 newValue,
37                                WebRtc_Word32 compareValue);
38
39    inline WebRtc_Word32 Value() const;
40private:
41    void*        _ptrMemory;
42    // Volatile ensures full memory barriers.
43    volatile WebRtc_Word32* _value;
44};
45
46// TODO (hellner) use aligned_malloc instead of doing it manually.
47inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
48    :
49    _ptrMemory(NULL),
50    _value(NULL)
51{   // Align the memory associated with _value on a 32-bit boundary. This is a
52    // requirement for the used Mac APIs to be atomic.
53    // Keep _ptrMemory to be able to reclaim memory.
54    _ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
55    _value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3));
56    *_value = initialValue;
57}
58
59inline Atomic32Impl::~Atomic32Impl()
60{
61    if(_ptrMemory != NULL)
62    {
63        free(_ptrMemory);
64    }
65}
66
67inline WebRtc_Word32 Atomic32Impl::operator++()
68{
69    return OSAtomicIncrement32Barrier(
70               reinterpret_cast<volatile int32_t*>(_value));
71}
72
73inline WebRtc_Word32 Atomic32Impl::operator--()
74{
75    return OSAtomicDecrement32Barrier(
76               reinterpret_cast<volatile int32_t*>(_value));
77}
78
79inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
80{
81    *_value = *rhs._value;
82    return *this;
83}
84
85inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
86{
87    *_value = rhs;
88    return *this;
89}
90
91inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
92{
93    return OSAtomicAdd32Barrier(rhs,
94                                reinterpret_cast<volatile int32_t*>(_value));
95}
96
97inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
98{
99    return OSAtomicAdd32Barrier(-rhs,
100                                reinterpret_cast<volatile int32_t*>(_value));
101}
102
103inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
104                                          WebRtc_Word32 compareValue)
105{
106    return OSAtomicCompareAndSwap32Barrier(
107               compareValue,
108               newValue,
109               reinterpret_cast<volatile int32_t*>(_value));
110}
111
112inline WebRtc_Word32 Atomic32Impl::Value() const
113{
114    return *_value;
115}
116} // namespace webrtc
117#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
118