Home | History | Annotate | Download | only in core
      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  */
     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:
    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 
    138 private:
    139     SkBaseMutex* fMutex;
    140 };
    141 #define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
    142 
    143 #endif
    144