• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 /** Atomic compare and set.
31  *  If *addr == before, set *addr to after and return true, otherwise return false.
32  *  This must act as a release (SL/S) memory barrier and as a compiler barrier.
33  */
34 static bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after);
35 
36 /** If sk_atomic_dec does not act as an acquire (L/SL) barrier,
37  *  this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
38  */
39 static void sk_membar_acquire__after_atomic_dec();
40 
41 /** If sk_atomic_conditional_inc does not act as an acquire (L/SL) barrier,
42  *  this must act as an acquire (L/SL) memory barrier and as a compiler barrier.
43  */
44 static void sk_membar_acquire__after_atomic_conditional_inc();
45 
46 #include SK_ATOMICS_PLATFORM_H
47 
48 /** Atomically adds one to the int referenced by addr iff the referenced int was not 0
49  *  and returns the previous value.
50  *  No additional memory barrier is required; this must act as a compiler barrier.
51  */
sk_atomic_conditional_inc(int32_t * addr)52 static inline int32_t sk_atomic_conditional_inc(int32_t* addr) {
53     int32_t prev;
54     do {
55         prev = *addr;
56         if (0 == prev) {
57             break;
58         }
59     } while (!sk_atomic_cas(addr, prev, prev+1));
60     return prev;
61 }
62 
63 // SK_BARRIERS_PLATFORM_H must provide implementations for the following declarations:
64 
65 /** Prevent the compiler from reordering across this barrier. */
66 static void sk_compiler_barrier();
67 
68 /** Read T*, with at least an acquire barrier.
69  *
70  *  Only needs to be implemented for T which can be atomically read.
71  */
72 template <typename T> T sk_acquire_load(T*);
73 
74 /** Write T*, with at least a release barrier.
75  *
76  *  Only needs to be implemented for T which can be atomically written.
77  */
78 template <typename T> void sk_release_store(T*, T);
79 
80 #include SK_BARRIERS_PLATFORM_H
81 
82 /** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations.
83 
84 class SkBaseMutex {
85 public:
86     void acquire();     // Block until this thread owns the mutex.
87     void release();     // Assuming this thread owns the mutex, release it.
88     void assertHeld();  // If SK_DEBUG, assert this thread owns the mutex.
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:
SkAutoMutexAcquire(SkBaseMutex & mutex)106     explicit SkAutoMutexAcquire(SkBaseMutex& mutex) : fMutex(&mutex) {
107         SkASSERT(fMutex != NULL);
108         mutex.acquire();
109     }
110 
SkAutoMutexAcquire(SkBaseMutex * mutex)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. */
~SkAutoMutexAcquire()118     ~SkAutoMutexAcquire() {
119         if (fMutex) {
120             fMutex->release();
121         }
122     }
123 
124     /** If the mutex has not been released, release it now. */
release()125     void release() {
126         if (fMutex) {
127             fMutex->release();
128             fMutex = NULL;
129         }
130     }
131 
132     /** Assert that we're holding the mutex. */
assertHeld()133     void assertHeld() {
134         SkASSERT(fMutex);
135         fMutex->assertHeld();
136     }
137 
138 private:
139     SkBaseMutex* fMutex;
140 };
141 #define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
142 
143 #endif
144