| Index: include/private/SkMutex.h
 | 
| diff --git a/include/private/SkMutex.h b/include/private/SkMutex.h
 | 
| index b9af00f8a8be02fc1e3b7794e23d761b1c94c761..8c78e1205c8796261be4b19468338a00af8afdc5 100644
 | 
| --- a/include/private/SkMutex.h
 | 
| +++ b/include/private/SkMutex.h
 | 
| @@ -8,20 +8,33 @@
 | 
|  #ifndef SkMutex_DEFINED
 | 
|  #define SkMutex_DEFINED
 | 
|  
 | 
| +// This file is not part of the public Skia API.
 | 
|  #include "../private/SkSemaphore.h"
 | 
| -#include "../private/SkThreadID.h"
 | 
|  #include "SkTypes.h"
 | 
|  
 | 
| -// TODO: no need for this anymore.
 | 
| -#define SK_DECLARE_STATIC_MUTEX(name) static SkMutex name;
 | 
| +#ifdef SK_DEBUG
 | 
| +    #include "../private/SkThreadID.h"
 | 
| +#endif
 | 
|  
 | 
| -class SkMutex {
 | 
| -public:
 | 
| -    constexpr SkMutex() = default;
 | 
| +#define SK_MUTEX_SEMAPHORE_INIT {1, {0}}
 | 
|  
 | 
| -    SkMutex(const SkMutex&)            = delete;
 | 
| -    SkMutex& operator=(const SkMutex&) = delete;
 | 
| +#ifdef SK_DEBUG
 | 
| +    #define SK_BASE_MUTEX_INIT {SK_MUTEX_SEMAPHORE_INIT, 0}
 | 
| +#else
 | 
| +    #define SK_BASE_MUTEX_INIT {SK_MUTEX_SEMAPHORE_INIT}
 | 
| +#endif
 | 
|  
 | 
| +// Using POD-style initialization prevents the generation of a static initializer.
 | 
| +//
 | 
| +// Without magic statics there are no thread safety guarantees on initialization
 | 
| +// of local statics (even POD). As a result, it is illegal to use
 | 
| +// SK_DECLARE_STATIC_MUTEX in a function.
 | 
| +//
 | 
| +// Because SkBaseMutex is not a primitive, a static SkBaseMutex cannot be
 | 
| +// initialized in a class with this macro.
 | 
| +#define SK_DECLARE_STATIC_MUTEX(name) namespace {} static SkBaseMutex name = SK_BASE_MUTEX_INIT;
 | 
| +
 | 
| +struct SkBaseMutex {
 | 
|      void acquire() {
 | 
|          fSemaphore.wait();
 | 
|          SkDEBUGCODE(fOwner = SkGetThreadID();)
 | 
| @@ -37,9 +50,20 @@
 | 
|          SkASSERT(fOwner == SkGetThreadID());
 | 
|      }
 | 
|  
 | 
| -private:
 | 
| -    SkSemaphore fSemaphore{1};
 | 
| -    SkDEBUGCODE(SkThreadID fOwner{kIllegalThreadID};)
 | 
| +    SkBaseSemaphore fSemaphore;
 | 
| +    SkDEBUGCODE(SkThreadID fOwner;)
 | 
| +};
 | 
| +
 | 
| +// This needs to use subclassing instead of encapsulation to make SkAutoMutexAcquire to work.
 | 
| +class SkMutex : public SkBaseMutex {
 | 
| +public:
 | 
| +    SkMutex () {
 | 
| +        fSemaphore = SK_MUTEX_SEMAPHORE_INIT;
 | 
| +        SkDEBUGCODE(fOwner = kIllegalThreadID);
 | 
| +    }
 | 
| +    ~SkMutex () { fSemaphore.deleteSemaphore(); }
 | 
| +    SkMutex(const SkMutex&) = delete;
 | 
| +    SkMutex& operator=(const SkMutex&) = delete;
 | 
|  };
 | 
|  
 | 
|  template <typename Lock>
 | 
| @@ -92,10 +116,10 @@
 | 
|      Lock &fLock;
 | 
|  };
 | 
|  
 | 
| -typedef SkAutoTAcquire<SkMutex> SkAutoMutexAcquire;
 | 
| +typedef SkAutoTAcquire<SkBaseMutex> SkAutoMutexAcquire;
 | 
|  #define SkAutoMutexAcquire(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexAcquire)
 | 
|  
 | 
| -typedef SkAutoTExclusive<SkMutex> SkAutoMutexExclusive;
 | 
| +typedef SkAutoTExclusive<SkBaseMutex> SkAutoMutexExclusive;
 | 
|  #define SkAutoMutexExclusive(...) SK_REQUIRE_LOCAL_VAR(SkAutoMutexExclusive)
 | 
|  
 | 
|  #endif//SkMutex_DEFINED
 | 
| 
 |