blob: 21c9f46d64058f28e4d1273d5b40095340a8a4dd [file] [log] [blame]
herbc782b2a2015-06-29 13:46:55 -07001/*
2 * Copyright 2015 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 SkSharedLock_DEFINED
9#define SkSharedLock_DEFINED
10
herbb906daf2015-09-29 09:37:59 -070011#include "SkAtomics.h"
herbc782b2a2015-06-29 13:46:55 -070012#include "SkSemaphore.h"
13#include "SkTypes.h"
herb966e3d32015-09-18 07:00:48 -070014
15#ifdef SK_DEBUG
16 #include "SkMutex.h"
mtklein5f939ab2016-03-16 10:28:35 -070017 #include <memory>
herb966e3d32015-09-18 07:00:48 -070018#endif // SK_DEBUG
19
20// There are two shared lock implementations one debug the other is high performance. They implement
21// an interface similar to pthread's rwlocks.
22// This is a shared lock implementation similar to pthreads rwlocks. The high performance
23// implementation is cribbed from Preshing's article:
herbc782b2a2015-06-29 13:46:55 -070024// http://preshing.com/20150316/semaphores-are-surprisingly-versatile/
25//
26// This lock does not obey strict queue ordering. It will always alternate between readers and
27// a single writer.
28class SkSharedMutex {
29public:
30 SkSharedMutex();
herbdec1afc2015-06-30 14:12:16 -070031 ~SkSharedMutex();
herbc782b2a2015-06-29 13:46:55 -070032 // Acquire lock for exclusive use.
33 void acquire();
34
35 // Release lock for exclusive use.
36 void release();
37
herbab42ec72015-08-19 13:40:12 -070038 // Fail if exclusive is not held.
herbab42ec72015-08-19 13:40:12 -070039 void assertHeld() const;
herbab42ec72015-08-19 13:40:12 -070040
herbc782b2a2015-06-29 13:46:55 -070041 // Acquire lock for shared use.
42 void acquireShared();
43
44 // Release lock for shared use.
45 void releaseShared();
46
herbab42ec72015-08-19 13:40:12 -070047 // Fail if shared lock not held.
herbab42ec72015-08-19 13:40:12 -070048 void assertHeldShared() const;
herbab42ec72015-08-19 13:40:12 -070049
herbc782b2a2015-06-29 13:46:55 -070050private:
herb966e3d32015-09-18 07:00:48 -070051#ifdef SK_DEBUG
52 class ThreadIDSet;
mtklein5f939ab2016-03-16 10:28:35 -070053 std::unique_ptr<ThreadIDSet> fCurrentShared;
54 std::unique_ptr<ThreadIDSet> fWaitingExclusive;
55 std::unique_ptr<ThreadIDSet> fWaitingShared;
herb966e3d32015-09-18 07:00:48 -070056 int fSharedQueueSelect{0};
57 mutable SkMutex fMu;
58 SkSemaphore fSharedQueue[2];
herbc782b2a2015-06-29 13:46:55 -070059 SkSemaphore fExclusiveQueue;
herb966e3d32015-09-18 07:00:48 -070060#else
61 SkAtomic<int32_t> fQueueCounts;
62 SkSemaphore fSharedQueue;
63 SkSemaphore fExclusiveQueue;
64#endif // SK_DEBUG
herbc782b2a2015-06-29 13:46:55 -070065};
66
herb966e3d32015-09-18 07:00:48 -070067#ifndef SK_DEBUG
68inline void SkSharedMutex::assertHeld() const {};
69inline void SkSharedMutex::assertHeldShared() const {};
70#endif // SK_DEBUG
herbab42ec72015-08-19 13:40:12 -070071
herb12449a92015-10-21 19:11:13 -070072class SkAutoSharedMutexShared {
73public:
74 SkAutoSharedMutexShared(SkSharedMutex& lock) : fLock(lock) { lock.acquireShared(); }
75 ~SkAutoSharedMutexShared() { fLock.releaseShared(); }
76private:
77 SkSharedMutex& fLock;
78};
79
80#define SkAutoSharedMutexShared(...) SK_REQUIRE_LOCAL_VAR(SkAutoSharedMutexShared)
81
herbc782b2a2015-06-29 13:46:55 -070082#endif // SkSharedLock_DEFINED