1/*
2 * Copyright 2016 Google Inc.
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 GrSingleOwner_DEFINED
9#define GrSingleOwner_DEFINED
10
11#include "SkTypes.h"
12
13#ifdef SK_DEBUG
14#include "SkMutex.h"
15#include "SkThreadID.h"
16
17// This is a debug tool to verify an object is only being used from one thread at a time.
18class GrSingleOwner {
19public:
20     GrSingleOwner() : fOwner(kIllegalThreadID), fReentranceCount(0) {}
21
22     struct AutoEnforce {
23         AutoEnforce(GrSingleOwner* so) : fSO(so) { fSO->enter(); }
24         ~AutoEnforce() { fSO->exit(); }
25
26         GrSingleOwner* fSO;
27     };
28
29private:
30     void enter() {
31         SkAutoMutexAcquire lock(fMutex);
32         SkThreadID self = SkGetThreadID();
33         SkASSERT(fOwner == self || fOwner == kIllegalThreadID);
34         fReentranceCount++;
35         fOwner = self;
36     }
37
38     void exit() {
39         SkAutoMutexAcquire lock(fMutex);
40         SkASSERT(fOwner == SkGetThreadID());
41         fReentranceCount--;
42         if (fReentranceCount == 0) {
43             fOwner = kIllegalThreadID;
44         }
45     }
46
47     SkMutex fMutex;
48     SkThreadID fOwner;    // guarded by fMutex
49     int fReentranceCount; // guarded by fMutex
50};
51#else
52class GrSingleOwner {}; // Provide a dummy implementation so we can pass pointers to constructors
53#endif
54
55#endif
56