Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(59)

Side by Side Diff: src/core/SkSharedMutex.cpp

Issue 1215503005: Implement shared locks in the style of pthread's rwlock. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Reformat test case. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/core/SkSharedMutex.h ('k') | tests/SkSharedMutexTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
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 #include "SkSharedMutex.h"
9
10 #include "SkAtomics.h"
11 #include "SkSemaphore.h"
12 #include "SkTypes.h"
13
14 // The fQueueCounts fields holds many counts in an int32_t in order to make mana ging them atomic.
15 // These three counts must be the same size, so each gets 10 bits. The 10 bits r epresent
16 // the log of the count which is 1024.
17 //
18 // The three counts held in fQueueCounts are:
19 // * Shared - the number of shared lock holders currently running.
20 // * WaitingExclusive - the number of threads waiting for an exclusive lock.
21 // * WaitingShared - the number of threads waiting to run while waiting for an e xclusive thread
22 // to finish.
23 static const int kLogThreadCount = 10;
24
25 enum {
26 kSharedOffset = (0 * kLogThreadCount),
27 kWaitingExlusiveOffset = (1 * kLogThreadCount),
28 kWaitingSharedOffset = (2 * kLogThreadCount),
29 kSharedMask = ((1 << kLogThreadCount) - 1) << kSharedOffset,
30 kWaitingExclusiveMask = ((1 << kLogThreadCount) - 1) << kWaitingExlusiveOff set,
31 kWaitingSharedMask = ((1 << kLogThreadCount) - 1) << kWaitingSharedOffse t,
32 };
33
34 SkSharedMutex::SkSharedMutex() : fQueueCounts(0) { }
35
36 void SkSharedMutex::acquire() {
37 // Increment the count of exclusive queue waiters.
38 int32_t oldQueueCounts = fQueueCounts.fetch_add(1 << kWaitingExlusiveOffset,
39 sk_memory_order_acquire);
40
41 // If there are no other exclusive waiters and no shared threads are running then run
42 // else wait.
43 if ((oldQueueCounts & kWaitingExclusiveMask) > 0 || (oldQueueCounts & kShare dMask) > 0) {
44 fExclusiveQueue.wait();
45 }
46 }
47
48 void SkSharedMutex::release() {
49 int32_t oldQueueCounts = fQueueCounts.load(sk_memory_order_relaxed);
50 int32_t waitingShared;
51 int32_t newQueueCounts;
52 do {
53 newQueueCounts = oldQueueCounts;
54
55 // Decrement exclusive waiters.
56 newQueueCounts -= 1 << kWaitingExlusiveOffset;
57
58 // The number of threads waiting to acquire a shared lock.
59 waitingShared = (oldQueueCounts & kWaitingSharedMask) >> kWaitingSharedO ffset;
60
61 // If there are any move the counts of all the shared waiters to actual shared. They are
62 // going to run next.
63 if (waitingShared > 0) {
64
65 // Set waiting shared to zero.
66 newQueueCounts &= ~kWaitingSharedMask;
67
68 // Because this is the exclusive release, then there are zero reader s. So, the bits
69 // for shared locks should be zero. Since those bits are zero, we ca n just |= in the
70 // waitingShared count instead of clearing with an &= and then |= th e count.
71 newQueueCounts |= waitingShared << kSharedOffset;
72 }
73
74 } while (!fQueueCounts.compare_exchange(&oldQueueCounts, newQueueCounts,
75 sk_memory_order_release, sk_memory_o rder_relaxed));
76
77 if (waitingShared > 0) {
78 // Run all the shared.
79 fSharedQueue.signal(waitingShared);
80 } else if ((newQueueCounts & kWaitingExclusiveMask) > 0) {
81 // Run a single exclusive waiter.
82 fExclusiveQueue.signal();
83 }
84 }
85
86 void SkSharedMutex::acquireShared() {
87 int32_t oldQueueCounts = fQueueCounts.load(sk_memory_order_relaxed);
88 int32_t newQueueCounts;
89 do {
90 newQueueCounts = oldQueueCounts;
91 // If there are waiting exclusives then this shared lock waits else it r uns.
92 if ((newQueueCounts & kWaitingExclusiveMask) > 0) {
93 newQueueCounts += 1 << kWaitingSharedOffset;
94 } else {
95 newQueueCounts += 1 << kSharedOffset;
96 }
97 } while (!fQueueCounts.compare_exchange(&oldQueueCounts, newQueueCounts,
98 sk_memory_order_acquire, sk_memory_o rder_relaxed));
99
100 // If there are waiting exclusives, then this shared waits until after it ru ns.
101 if ((newQueueCounts & kWaitingExclusiveMask) > 0) {
102 fSharedQueue.wait();
103 }
104 }
105
106 void SkSharedMutex::releaseShared() {
107 // Decrement the shared count.
108 int32_t oldQueueCounts = fQueueCounts.fetch_add(-1 << kSharedOffset,
109 sk_memory_order_release);
110
111 // If shared count is going to zero (because the old count == 1) and there a re exclusive
112 // waiters, then run a single exclusive waiter.
113 if (((oldQueueCounts & kSharedMask) >> kSharedOffset) == 1
114 && (oldQueueCounts & kWaitingExclusiveMask) > 0) {
115 fExclusiveQueue.signal();
116 }
117 }
OLDNEW
« no previous file with comments | « src/core/SkSharedMutex.h ('k') | tests/SkSharedMutexTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698