Branch data Line data Source code
1 : : /* 2 : : * Copyright (C) 2026 by Thun Lu. All rights reserved. 3 : : * Author: Thun Lu <thun.lu@zohomail.cn> 4 : : * Repo: https://github.com/thun-res/vlink 5 : : * _ __ __ _ __ 6 : : * | | / / / / (_) ____ / /__ 7 : : * | | / / / / / / / __ \ / //_/ 8 : : * | |/ / / /___ / / / / / / / ,< 9 : : * |___/ /_____/ /_/ /_/ /_/ /_/|_| 10 : : * 11 : : * Licensed under the Apache License, Version 2.0 (the "License"); 12 : : * you may not use this file except in compliance with the License. 13 : : * You may obtain a copy of the License at 14 : : * 15 : : * http://www.apache.org/licenses/LICENSE-2.0 16 : : * 17 : : * Unless required by applicable law or agreed to in writing, software 18 : : * distributed under the License is distributed on an "AS IS" BASIS, 19 : : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 : : * See the License for the specific language governing permissions and 21 : : * limitations under the License. 22 : : */ 23 : : 24 : : #include "./impl/ack_manager.h" 25 : : 26 : : #include <mutex> 27 : : #include <set> 28 : : 29 : : #include "./base/memory_resource.h" 30 : : 31 : : namespace vlink { 32 : : 33 : : // AckManager 34 : 142 : AckManager::AckManager() noexcept = default; 35 : : 36 : 142 : AckManager::~AckManager() noexcept = default; 37 : : 38 : 100 : AckManager::RequestPtr AckManager::create_request() noexcept { 39 : 100 : std::unique_lock manager_lock(mtx_); 40 : : 41 : 100 : auto request = MemoryResource::make_shared<Request>(); 42 : : 43 : 100 : request->seq = request_seq_++; 44 : 100 : request->generation = generation_; 45 : : 46 : 100 : return request; 47 : 100 : } 48 : : 49 : 91 : bool AckManager::process(RequestPtr request, int ms, ProcessCallback&& process_callback) noexcept { 50 : : { 51 : 91 : std::lock_guard manager_lock(mtx_); 52 : : 53 [ + + - + : 91 : if VUNLIKELY (is_interrupted_ || request->generation != generation_) { + + ] 54 : 1 : return false; 55 : : } 56 : : 57 : 90 : request_set_.emplace(request); 58 [ + + ]: 91 : } 59 : : 60 [ + - ]: 90 : if VLIKELY (process_callback) { 61 [ + + ]: 90 : if VUNLIKELY (!process_callback()) { 62 : 3 : remove(request); 63 : 3 : return false; 64 : : } 65 : : } else { 66 : 0 : remove(request); 67 : 0 : return false; 68 : : } 69 : : 70 : 87 : bool ret = true; 71 : : 72 : : { 73 : 87 : std::unique_lock lock(request->mtx); 74 : : 75 : 695 : auto predicate = [this, &request]() -> bool { 76 [ + - ]: 141 : std::lock_guard manager_lock(mtx_); 77 [ + + + + : 282 : return is_interrupted_ || request->generation != generation_ || request_set_.count(request) == 0; + - + + ] 78 : 141 : }; 79 : : 80 [ + + ]: 87 : if VUNLIKELY (ms < 0) { 81 : 3 : request->cv.wait(lock, predicate); 82 : : } else { 83 : 84 : ret = request->cv.wait_for(lock, std::chrono::milliseconds(ms), predicate); 84 : : } 85 : 87 : } 86 : : 87 : : { 88 : 87 : std::lock_guard manager_lock(mtx_); 89 : 87 : request_set_.erase(request); 90 : : 91 [ + + + + : 87 : if VUNLIKELY (is_interrupted_ || request->generation != generation_) { + + ] 92 : 4 : return false; 93 : : } 94 [ + + ]: 87 : } 95 : : 96 : 83 : return ret; 97 : : } 98 : : 99 : 74 : bool AckManager::notify(RequestPtr request, NotifyCallback&& notify_callback) noexcept { 100 : : { 101 : 74 : std::lock_guard manager_lock(mtx_); 102 : : 103 [ + + ]: 74 : if VUNLIKELY (request_set_.erase(request) == 0) { 104 : 3 : return false; 105 : : } 106 [ + + ]: 74 : } 107 : : 108 : 71 : std::lock_guard lock(request->mtx); 109 : : 110 [ + + ]: 71 : if VLIKELY (notify_callback) { 111 : 61 : notify_callback(); 112 : : } 113 : : 114 : 71 : request->cv.notify_one(); 115 : : 116 : 71 : return true; 117 : 71 : } 118 : : 119 : 4 : bool AckManager::remove(RequestPtr request) noexcept { 120 : 4 : std::lock_guard manager_lock(mtx_); 121 : : 122 : 4 : return request_set_.erase(request) != 0; 123 : 4 : } 124 : : 125 : 118 : void AckManager::clear() noexcept { 126 : 118 : decltype(request_set_) temp_set; 127 : : 128 : : { 129 : 118 : std::lock_guard manager_lock(mtx_); 130 : : 131 : 118 : is_interrupted_ = true; 132 : 118 : ++generation_; 133 : : 134 : 118 : temp_set.swap(request_set_); 135 : 118 : } 136 : : 137 [ + + ]: 122 : for (const auto& request : temp_set) { 138 : 4 : std::lock_guard lock(request->mtx); 139 : 4 : request->cv.notify_all(); 140 : 4 : } 141 : 118 : } 142 : : 143 : 80 : void AckManager::reset_interrupted() noexcept { 144 : 80 : std::lock_guard manager_lock(mtx_); 145 : : 146 : 80 : is_interrupted_ = false; 147 : 80 : } 148 : : 149 : : } // namespace vlink