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 "include/core/SkTypes.h"
12
13#ifdef SK_DEBUG
14#include "include/private/SkMutex.h"
15#include "include/private/SkThreadID.h"
16
17#define GR_ASSERT_SINGLE_OWNER(obj) \
18 GrSingleOwner::AutoEnforce debug_SingleOwner(obj, __FILE__, __LINE__);
19
20// This is a debug tool to verify an object is only being used from one thread at a time.
21class GrSingleOwner {
22public:
23 GrSingleOwner() : fOwner(kIllegalThreadID), fReentranceCount(0) {}
24
25 struct AutoEnforce {
26 AutoEnforce(GrSingleOwner* so, const char* file, int line)
27 : fFile(file), fLine(line), fSO(so) {
28 fSO->enter(file, line);
29 }
30 ~AutoEnforce() { fSO->exit(fFile, fLine); }
31
32 const char* fFile;
33 int fLine;
34 GrSingleOwner* fSO;
35 };
36
37private:
38 void enter(const char* file, int line) {
39 SkAutoMutexExclusive lock(fMutex);
40 SkThreadID self = SkGetThreadID();
41 SkASSERTF(fOwner == self || fOwner == kIllegalThreadID, "%s:%d Single owner failure.",
42 file, line);
43 fReentranceCount++;
44 fOwner = self;
45 }
46
47 void exit(const char* file, int line) {
48 SkAutoMutexExclusive lock(fMutex);
49 SkASSERTF(fOwner == SkGetThreadID(), "%s:%d Single owner failure.", file, line);
50 fReentranceCount--;
51 if (fReentranceCount == 0) {
52 fOwner = kIllegalThreadID;
53 }
54 }
55
56 SkMutex fMutex;
57 SkThreadID fOwner SK_GUARDED_BY(fMutex);
58 int fReentranceCount SK_GUARDED_BY(fMutex);
59};
60#else
61#define GR_ASSERT_SINGLE_OWNER(obj)
62class GrSingleOwner {}; // Provide a dummy implementation so we can pass pointers to constructors
63#endif
64
65#endif
66