OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "device/base/synchronization/one_writer_seqlock.h" | 5 #include "device/base/synchronization/one_writer_seqlock.h" |
6 | 6 |
7 namespace device { | 7 namespace device { |
8 | 8 |
9 OneWriterSeqLock::OneWriterSeqLock() : sequence_(0) {} | 9 OneWriterSeqLock::OneWriterSeqLock() : sequence_(0) {} |
10 | 10 |
11 base::subtle::Atomic32 OneWriterSeqLock::ReadBegin() const { | 11 base::subtle::Atomic32 OneWriterSeqLock::ReadBegin() const { |
12 base::subtle::Atomic32 version; | 12 base::subtle::Atomic32 version; |
13 for (;;) { | 13 for (;;) { |
14 version = base::subtle::NoBarrier_Load(&sequence_); | 14 version = base::subtle::NoBarrier_Load(&sequence_); |
15 | 15 |
16 // If the counter is even, then the associated data might be in a | 16 // If the counter is even, then the associated data might be in a |
17 // consistent state, so we can try to read. | 17 // consistent state, so we can try to read. |
18 if ((version & 1) == 0) | 18 if ((version & 1) == 0) |
19 break; | 19 break; |
20 | 20 |
21 // Otherwise, the writer is in the middle of an update. Retry the read. | 21 // Otherwise, the writer is in the middle of an update. Retry the read. |
22 base::PlatformThread::YieldCurrentThread(); | 22 base::PlatformThread::YieldCurrentThread(); |
23 } | 23 } |
24 return version; | 24 return version; |
25 } | 25 } |
26 | 26 |
| 27 void OneWriterSeqLock::TryRead(bool* can_read, |
| 28 base::subtle::Atomic32* version) const { |
| 29 DCHECK(can_read); |
| 30 DCHECK(version); |
| 31 |
| 32 *version = base::subtle::NoBarrier_Load(&sequence_); |
| 33 // If the counter is even, then the associated data might be in a |
| 34 // consistent state, so we can try to read. |
| 35 *can_read = (*version & 1) == 0; |
| 36 } |
| 37 |
27 bool OneWriterSeqLock::ReadRetry(base::subtle::Atomic32 version) const { | 38 bool OneWriterSeqLock::ReadRetry(base::subtle::Atomic32 version) const { |
28 // If the sequence number was updated then a read should be re-attempted. | 39 // If the sequence number was updated then a read should be re-attempted. |
29 // -- Load fence, read membarrier | 40 // -- Load fence, read membarrier |
30 return base::subtle::Release_Load(&sequence_) != version; | 41 return base::subtle::Release_Load(&sequence_) != version; |
31 } | 42 } |
32 | 43 |
33 void OneWriterSeqLock::WriteBegin() { | 44 void OneWriterSeqLock::WriteBegin() { |
34 // Increment the sequence number to odd to indicate the beginning of a write | 45 // Increment the sequence number to odd to indicate the beginning of a write |
35 // update. | 46 // update. |
36 base::subtle::Barrier_AtomicIncrement(&sequence_, 1); | 47 base::subtle::Barrier_AtomicIncrement(&sequence_, 1); |
37 // -- Store fence, write membarrier | 48 // -- Store fence, write membarrier |
38 } | 49 } |
39 | 50 |
40 void OneWriterSeqLock::WriteEnd() { | 51 void OneWriterSeqLock::WriteEnd() { |
41 // Increment the sequence to an even number to indicate the completion of | 52 // Increment the sequence to an even number to indicate the completion of |
42 // a write update. | 53 // a write update. |
43 // -- Store fence, write membarrier | 54 // -- Store fence, write membarrier |
44 base::subtle::Barrier_AtomicIncrement(&sequence_, 1); | 55 base::subtle::Barrier_AtomicIncrement(&sequence_, 1); |
45 } | 56 } |
46 | 57 |
47 } // namespace device | 58 } // namespace device |
OLD | NEW |