Line data Source code
1 : /*
2 : ___________________________________________
3 : | _ ___ _ |
4 : | | | |__ \ | | |
5 : | | |__ ) |__ _ __ _ ___ _ __ | |_ |
6 : | | '_ \ / // _` |/ _` |/ _ \ '_ \| __| | HTTP/2 AGENT FOR MOCK TESTING
7 : | | | | |/ /| (_| | (_| | __/ | | | |_ | Version 0.0.z
8 : | |_| |_|____\__,_|\__, |\___|_| |_|\__| | https://github.com/testillano/h2agent
9 : | __/ | |
10 : | |___/ |
11 : |___________________________________________|
12 :
13 : Licensed under the MIT License <http://opensource.org/licenses/MIT>.
14 : SPDX-License-Identifier: MIT
15 : Copyright (c) 2021 Eduardo Ramos
16 :
17 : Permission is hereby granted, free of charge, to any person obtaining a copy
18 : of this software and associated documentation files (the "Software"), to deal
19 : in the Software without restriction, including without limitation the rights
20 : to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 : copies of the Software, and to permit persons to whom the Software is
22 : furnished to do so, subject to the following conditions:
23 :
24 : The above copyright notice and this permission notice shall be included in all
25 : copies or substantial portions of the Software.
26 :
27 : THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 : IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 : FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 : AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 : LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32 : OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 : SOFTWARE.
34 : */
35 :
36 : #include <algorithm>
37 : #include <chrono>
38 :
39 : #include <WaitManager.hpp>
40 : #include <Vault.hpp>
41 :
42 : namespace h2agent
43 : {
44 : namespace model
45 : {
46 :
47 37 : bool WaitManager::waitForVault(const std::string &key, const nlohmann::json &targetValue,
48 : unsigned int timeoutMs,
49 : nlohmann::json &resultValue, nlohmann::json &previousValue) {
50 :
51 37 : timeoutMs = std::min(timeoutMs, MAX_TIMEOUT_MS);
52 :
53 37 : std::unique_lock<std::mutex> lock(mutex_);
54 :
55 37 : if (active_waiters_ >= MAX_WAITERS) {
56 1 : return false; // caller should return 429
57 : }
58 :
59 36 : if (shutdown_) return false;
60 :
61 : // Capture initial value
62 36 : previousValue = nullptr;
63 36 : if (vault_) vault_->tryGet(key, previousValue);
64 :
65 : // Check if already satisfied
66 36 : if (!targetValue.is_null() && previousValue == targetValue) {
67 1 : resultValue = previousValue;
68 1 : return true;
69 : }
70 :
71 35 : active_waiters_++;
72 35 : bool result = cv_.wait_for(lock, std::chrono::milliseconds(timeoutMs), [&] {
73 70 : if (shutdown_) return true;
74 70 : resultValue = nullptr;
75 70 : bool exists = vault_ && vault_->tryGet(key, resultValue);
76 70 : if (targetValue.is_null()) {
77 4 : return exists && resultValue != previousValue;
78 : }
79 66 : return exists && resultValue == targetValue;
80 : });
81 35 : active_waiters_--;
82 :
83 35 : if (shutdown_) return false;
84 :
85 35 : if (!result) {
86 1 : resultValue = nullptr;
87 1 : if (vault_) vault_->tryGet(key, resultValue);
88 : }
89 :
90 35 : return result;
91 37 : }
92 :
93 0 : void WaitManager::shutdown() {
94 0 : std::lock_guard<std::mutex> lock(mutex_);
95 0 : shutdown_ = true;
96 0 : cv_.notify_all();
97 0 : }
98 :
99 7 : void WaitManager::notify() {
100 7 : cv_.notify_all();
101 7 : }
102 :
103 0 : size_t WaitManager::activeWaiters() const {
104 0 : return active_waiters_;
105 : }
106 :
107 0 : bool WaitManager::isFull() const {
108 0 : return active_waiters_ >= MAX_WAITERS;
109 : }
110 :
111 : }
112 : }
|