1/*
2 * Copyright 2010-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License").
5 * You may not use this file except in compliance with the License.
6 * A copy of the License is located at
7 *
8 * http://aws.amazon.com/apache2.0
9 *
10 * or in the "license" file accompanying this file. This file is distributed
11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 * express or implied. See the License for the specific language governing
13 * permissions and limitations under the License.
14 */
15
16#include <aws/core/utils/threading/ReaderWriterLock.h>
17#include <cstdint>
18#include <limits>
19#include <cassert>
20
21using namespace Aws::Utils::Threading;
22
23static const int64_t MaxReaders = std::numeric_limits<std::int32_t>::max();
24
25ReaderWriterLock::ReaderWriterLock() :
26 m_readers(0),
27 m_holdouts(0),
28 m_readerSem(0, static_cast<size_t>(MaxReaders)),
29 m_writerSem(0, 1)
30{
31}
32
33void ReaderWriterLock::LockReader()
34{
35 if (++m_readers < 0)
36 {
37 m_readerSem.WaitOne();
38 }
39}
40
41void ReaderWriterLock::UnlockReader()
42{
43 if (--m_readers < 0 && --m_holdouts == 0)
44 {
45 m_writerSem.Release();
46 }
47}
48
49void ReaderWriterLock::LockWriter()
50{
51 m_writerLock.lock();
52 if(const auto current = m_readers.fetch_sub(MaxReaders))
53 {
54 assert(current > 0);
55 const auto holdouts = m_holdouts.fetch_add(current) + current;
56 assert(holdouts >= 0);
57 if(holdouts > 0)
58 {
59 m_writerSem.WaitOne();
60 }
61 }
62}
63
64void ReaderWriterLock::UnlockWriter()
65{
66 assert(m_holdouts == 0);
67 const auto current = m_readers.fetch_add(MaxReaders) + MaxReaders;
68 assert(current >= 0);
69 for(int64_t r = 0; r < current; r++)
70 {
71 m_readerSem.Release();
72 }
73 m_writerLock.unlock();
74}
75