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); 19static int64_t sk_atomic_inc(int64_t* addr); 20 21/** Atomically adds inc to the int referenced by addr and returns the previous value. 22 * No additional memory barrier is required; this must act as a compiler barrier. 23 */ 24static int32_t sk_atomic_add(int32_t* addr, int32_t inc); 25 26/** Atomically subtracts one from the int referenced by addr and returns the previous value. 27 * This must act as a release (SL/S) memory barrier and as a compiler barrier. 28 */ 29static int32_t sk_atomic_dec(int32_t* addr); 30 31/** Atomic compare and set. 32 * If *addr == before, set *addr to after and return true, otherwise return false. 33 * This must act as a release (SL/S) memory barrier and as a compiler barrier. 34 */ 35static bool sk_atomic_cas(int32_t* addr, int32_t before, int32_t after); 36 37/** If sk_atomic_dec does not act as an acquire (L/SL) barrier, 38 * this must act as an acquire (L/SL) memory barrier and as a compiler barrier. 39 */ 40static void sk_membar_acquire__after_atomic_dec(); 41 42/** If sk_atomic_conditional_inc 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 */ 45static void sk_membar_acquire__after_atomic_conditional_inc(); 46 47#include SK_ATOMICS_PLATFORM_H 48 49/** Atomically adds one to the int referenced by addr iff the referenced int was not 0 50 * and returns the previous value. 51 * No additional memory barrier is required; this must act as a compiler barrier. 52 */ 53template<typename INT_TYPE> static inline INT_TYPE sk_atomic_conditional_inc(INT_TYPE* addr) { 54 INT_TYPE prev; 55 do { 56 prev = *addr; 57 if (0 == prev) { 58 break; 59 } 60 } while (!sk_atomic_cas(addr, prev, prev+1)); 61 return prev; 62} 63 64// SK_BARRIERS_PLATFORM_H must provide implementations for the following declarations: 65 66/** Prevent the compiler from reordering across this barrier. */ 67static void sk_compiler_barrier(); 68 69/** Read T*, with at least an acquire barrier. 70 * 71 * Only needs to be implemented for T which can be atomically read. 72 */ 73template <typename T> T sk_acquire_load(T*); 74 75/** Write T*, with at least a release barrier. 76 * 77 * Only needs to be implemented for T which can be atomically written. 78 */ 79template <typename T> void sk_release_store(T*, T); 80 81#include SK_BARRIERS_PLATFORM_H 82 83/** SK_MUTEX_PLATFORM_H must provide the following (or equivalent) declarations. 84 85class SkBaseMutex { 86public: 87 void acquire(); // Block until this thread owns the mutex. 88 void release(); // Assuming this thread owns the mutex, release it. 89 void assertHeld(); // If SK_DEBUG, assert this thread owns the mutex. 90}; 91 92class SkMutex : SkBaseMutex { 93public: 94 SkMutex(); 95 ~SkMutex(); 96}; 97 98#define SK_DECLARE_STATIC_MUTEX(name) static 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