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 */ 18static 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 */ 23static 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 */ 28static 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 */ 34static 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 */ 39static 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 */ 44static 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 */ 52static 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. */ 66static 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 */ 72template <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 */ 78template <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 84class SkBaseMutex { 85public: 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 91class SkMutex : SkBaseMutex { 92public: 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 104class SkAutoMutexAcquire : SkNoncopyable { 105public: 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 /** Assert that we're holding the mutex. */ 133 void assertHeld() { 134 SkASSERT(fMutex); 135 fMutex->assertHeld(); 136 } 137 138private: 139 SkBaseMutex* fMutex; 140}; 141#define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire) 142 143#endif 144