Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TRWSpinLock.cxx
Go to the documentation of this file.
1// @(#)root/thread:$Id$
2// Authors: Enric Tejedor CERN 12/09/2016
3// Philippe Canal FNAL 12/09/2016
4
5/*************************************************************************
6 * Copyright (C) 1995-2016, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13/** \class TRWSpinLock
14 \brief An implementation of a read-write lock with an internal spin lock.
15
16This class provides an implementation of a read-write lock that uses an
17internal spin lock and a condition variable to synchronize readers and
18writers when necessary.
19
20The implementation tries to make faster the scenario when readers come
21and go but there is no writer. In that case, readers will not pay the
22price of taking the internal spin lock.
23
24Moreover, this RW lock tries to be fair with writers, giving them the
25possibility to claim the lock and wait for only the remaining readers,
26thus preventing starvation.
27*/
28
29#include "ROOT/TRWSpinLock.hxx"
30
31using namespace ROOT;
32
33////////////////////////////////////////////////////////////////////////////
34/// Acquire the lock in read mode.
35void TRWSpinLock::ReadLock()
36{
38 if (!fWriter) {
39 // There is no writer, go freely to the critical section
40 ++fReaders;
42 } else {
43 // A writer claimed the RW lock, we will need to wait on the
44 // internal lock
46
47 std::unique_lock<ROOT::TSpinMutex> lock(fMutex);
48
49 // Wait for writers, if any
50 fCond.wait(lock, [this]{ return !fWriter; });
51
52 // This RW lock now belongs to the readers
53 ++fReaders;
54
55 lock.unlock();
56 }
57}
58
59//////////////////////////////////////////////////////////////////////////
60/// Release the lock in read mode.
62{
63 --fReaders;
64 if (fWriterReservation && fReaders == 0) {
65 // We still need to lock here to prevent interleaving with a writer
66 std::lock_guard<ROOT::TSpinMutex> lock(fMutex);
67
68 // Make sure you wake up a writer, if any
69 // Note: spurrious wakeups are okay, fReaders
70 // will be checked again in WriteLock
71 fCond.notify_all();
72 }
73}
74
75//////////////////////////////////////////////////////////////////////////
76/// Acquire the lock in write mode.
78{
80
81 std::unique_lock<ROOT::TSpinMutex> lock(fMutex);
82
83 // Wait for other writers, if any
84 fCond.wait(lock, [this]{ return !fWriter; });
85
86 // Claim the lock for this writer
87 fWriter = true;
88
89 // Wait until all reader reservations finish
90 while(fReaderReservation) {};
91
92 // Wait for remaining readers
93 fCond.wait(lock, [this]{ return fReaders == 0; });
94
96
97 lock.unlock();
98}
99
100//////////////////////////////////////////////////////////////////////////
101/// Release the lock in write mode.
103{
104 // We need to lock here to prevent interleaving with a reader
105 std::lock_guard<ROOT::TSpinMutex> lock(fMutex);
106
107 fWriter = false;
108
109 // Notify all potential readers/writers that are waiting
110 fCond.notify_all();
111}
112
113
115{
116 fLock.ReadLock();
117}
118
120{
122}
123
125{
127}
128
130{
132}
133
134
TRWSpinLockReadGuard(TRWSpinLock &lock)
TRWSpinLockWriteGuard(TRWSpinLock &lock)
void ReadLock()
Acquire the lock in read mode.
std::condition_variable_any fCond
! RWlock internal condition variable
std::atomic< int > fReaderReservation
! A reader wants access
std::atomic< bool > fWriter
! Is there a writer?
void ReadUnLock()
Release the lock in read mode.
ROOT::TSpinMutex fMutex
! RWlock internal mutex
void WriteLock()
Acquire the lock in write mode.
void WriteUnLock()
Release the lock in write mode.
std::atomic< int > fWriterReservation
! A writer wants access
std::atomic< int > fReaders
! Number of readers
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...