Upstream version 5.34.92.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / include / core / SkThread.h
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #ifndef SkThread_DEFINED
9 #define SkThread_DEFINED
10
11 #include "SkTypes.h"
12
13 // SK_ATOMICS_PLATFORM_H must provide inline implementations for the following declarations.
14
15 /** Atomically adds one to the int referenced by addr and returns the previous value.
16  *  No additional memory barrier is required; this must act as a compiler barrier.
17  */
18 static int32_t sk_atomic_inc(int32_t* addr);
19
20 /** Atomically adds inc to the int referenced by addr and returns the previous value.
21  *  No additional memory barrier is required; this must act as a compiler barrier.
22  */
23 static int32_t sk_atomic_add(int32_t* addr, int32_t inc);
24
25 /** Atomically subtracts one from the int referenced by addr and returns the previous value.
26  *  This must act as a release (SL/S) memory barrier and as a compiler barrier.
27  */
28 static int32_t sk_atomic_dec(int32_t* addr);
29
30 /** Atomically adds one to the int referenced by addr iff the referenced int was not 0
31  *  and returns the previous value.
32  *  No additional memory barrier is required; this must act as a compiler barrier.
33  */
34 static int32_t sk_atomic_conditional_inc(int32_t* addr);
35
36 /** Atomic compare and set.
37  *  If *addr == before, set *addr to after and return true, otherwise return false.
38  *  This must act as a release (SL/S) memory barrier and as a compiler barrier.
39  */
40 static bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after);
41
42 /** If sk_atomic_dec does not act as an acquire (L/SL) barrier,
43  *  this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
44  */
45 static void sk_membar_acquire__after_atomic_dec();
46
47 /** If sk_atomic_conditional_inc does not act as an acquire (L/SL) barrier,
48  *  this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
49  */
50 static void sk_membar_acquire__after_atomic_conditional_inc();
51
52 #include SK_ATOMICS_PLATFORM_H
53
54 // This is POD and must be zero-initialized.
55 struct SkSpinlock {
56     void acquire() {
57         SkASSERT(shouldBeZero == 0);
58         // No memory barrier needed, but sk_atomic_cas gives us at least release anyway.
59         while (!sk_atomic_cas(&thisIsPrivate, 0, 1)) {
60             // spin
61         }
62     }
63
64     void release() {
65         SkASSERT(shouldBeZero == 0);
66         // This requires a release memory barrier before storing, which sk_atomic_cas guarantees.
67         SkAssertResult(sk_atomic_cas(&thisIsPrivate, 1, 0));
68     }
69
70     int32_t thisIsPrivate;
71     SkDEBUGCODE(int32_t shouldBeZero;)
72 };
73
74 class SkAutoSpinlock : SkNoncopyable {
75 public:
76     explicit SkAutoSpinlock(SkSpinlock* lock) : fLock(lock) { fLock->acquire(); }
77     ~SkAutoSpinlock() { fLock->release(); }
78 private:
79     SkSpinlock* fLock;
80 };
81 #define SkAutoSpinlock(...) SK_REQUIRE_LOCAL_VAR(SkAutoSpinlock)
82
83 /** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations.
84
85 class SkBaseMutex {
86 public:
87     void acquire();
88     void release();
89 };
90
91 class SkMutex : SkBaseMutex {
92 public:
93     SkMutex();
94     ~SkMutex();
95 };
96
97 #define SK_DECLARE_STATIC_MUTEX(name) static SkBaseMutex name = ...
98 #define SK_DECLARE_GLOBAL_MUTEX(name) SkBaseMutex name = ...
99 */
100
101 #include SK_MUTEX_PLATFORM_H
102
103
104 class SkAutoMutexAcquire : SkNoncopyable {
105 public:
106     explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) {
107         SkASSERT(fMutex != NULL);
108         mutex.acquire();
109     }
110
111     explicit SkAutoMutexAcquire(SkBaseMutex* mutex) : fMutex(mutex) {
112         if (mutex) {
113             mutex->acquire();
114         }
115     }
116
117     /** If the mutex has not been released, release it now. */
118     ~SkAutoMutexAcquire() {
119         if (fMutex) {
120             fMutex->release();
121         }
122     }
123
124     /** If the mutex has not been released, release it now. */
125     void release() {
126         if (fMutex) {
127             fMutex->release();
128             fMutex = NULL;
129         }
130     }
131
132 private:
133     SkBaseMutex* fMutex;
134 };
135 #define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
136
137 #endif