aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/messagebus/futex_like.h
blob: fa4be8a1417068a59c0e020beaee87578a27e869 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#pragma once

#include <library/cpp/deprecated/atomic/atomic.h>

#include <util/system/condvar.h>
#include <util/system/mutex.h>
#include <util/system/platform.h>

class TFutexLike {
private:
#ifdef _linux_
    int Value;
#else
    TAtomic Value;
    TMutex Mutex;
    TCondVar CondVar;
#endif

public:
    TFutexLike()
        : Value(0)
    {
    }

    int AddAndGet(int add) {
#ifdef _linux_
        //return __atomic_add_fetch(&Value, add, __ATOMIC_SEQ_CST);
        return __sync_add_and_fetch(&Value, add);
#else
        return AtomicAdd(Value, add);
#endif
    }

    int GetAndAdd(int add) {
        return AddAndGet(add) - add;
    }

// until we have modern GCC
#if 0
    int GetAndSet(int newValue) {
#ifdef _linux_
        return __atomic_exchange_n(&Value, newValue, __ATOMIC_SEQ_CST);
#else
        return AtomicSwap(&Value, newValue);
#endif
    }
#endif

    int Get() {
#ifdef _linux_
        //return __atomic_load_n(&Value, __ATOMIC_SEQ_CST);
        __sync_synchronize();
        return Value;
#else
        return AtomicGet(Value);
#endif
    }

    void Set(int newValue) {
#ifdef _linux_
        //__atomic_store_n(&Value, newValue, __ATOMIC_SEQ_CST);
        Value = newValue;
        __sync_synchronize();
#else
        AtomicSet(Value, newValue);
#endif
    }

    int GetAndIncrement() {
        return AddAndGet(1) - 1;
    }

    int IncrementAndGet() {
        return AddAndGet(1);
    }

    int GetAndDecrement() {
        return AddAndGet(-1) + 1;
    }

    int DecrementAndGet() {
        return AddAndGet(-1);
    }

    void Wake(size_t count = Max<size_t>());

    void Wait(int expected);
};