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/publisher_impl.h" 25 : : 26 : : #include <atomic> 27 : : #include <mutex> 28 : : #include <utility> 29 : : 30 : : #include "./base/condition_variable.h" 31 : : #include "./base/utils.h" 32 : : 33 : : namespace vlink { 34 : : 35 : : // PublisherImplHelper 36 : : struct PublisherImplHelper final { 37 : : std::atomic_bool has_subscribers{false}; 38 : : NodeImpl::ConnectCallback connected_callback; 39 : : ConditionVariable connected_cv; 40 : : std::mutex mtx; 41 : : std::recursive_mutex callback_mtx; 42 : : }; 43 : : 44 : : // PublisherImpl 45 : 340 : PublisherImpl::~PublisherImpl() = default; 46 : : 47 : 311 : void PublisherImpl::interrupt() { 48 : : { 49 [ + - ]: 311 : std::lock_guard sync_lock(helper_->mtx); 50 [ + - ]: 311 : NodeImpl::interrupt(); 51 : 311 : } 52 : : 53 : 311 : helper_->connected_cv.notify_all(); 54 : 311 : } 55 : : 56 : 14 : void PublisherImpl::detect_subscribers(ConnectCallback&& callback) { 57 [ + - ]: 14 : std::unique_lock lock(helper_->callback_mtx); 58 : 14 : helper_->connected_callback = std::move(callback); 59 : : 60 [ + + ]: 14 : if (helper_->has_subscribers.load(std::memory_order_acquire)) { 61 [ + - ]: 1 : auto callback_copy = helper_->connected_callback; 62 [ + - ]: 1 : lock.unlock(); 63 [ + - ]: 1 : callback_copy(true); 64 : 1 : } 65 : 14 : } 66 : : 67 : 207 : bool PublisherImpl::wait_for_subscribers(std::chrono::milliseconds timeout) { 68 [ + - + + ]: 207 : if VLIKELY (has_subscribers()) { 69 : 152 : return true; 70 : : } 71 : : 72 : 55 : Utils::yield_cpu(); 73 : : 74 [ + - ]: 55 : std::unique_lock lock(helper_->mtx); 75 : : 76 [ + - ]: 55 : reset_interrupted(); 77 : : 78 : 176 : auto predicate = [this]() -> bool { 79 [ + + + + ]: 110 : return helper_->has_subscribers.load(std::memory_order_acquire) || is_interrupted(); 80 : 55 : }; 81 : : 82 [ + + ]: 55 : if VUNLIKELY (timeout.count() < 0) { 83 [ + - ]: 1 : helper_->connected_cv.wait(lock, std::move(predicate)); 84 : 1 : return helper_->has_subscribers.load(std::memory_order_acquire); 85 : : } else { 86 [ + - + + : 54 : return helper_->connected_cv.wait_for(lock, timeout, std::move(predicate)) && !is_interrupted(); + - + + ] 87 : : } 88 : 55 : } 89 : : 90 : 1 : bool PublisherImpl::write(const IntraData& intra_data) { 91 : : (void)intra_data; 92 : : 93 [ + - + - ]: 2 : VLOG_W("Function [write(const IntraData&)] is not supported."); 94 : : 95 : 1 : return false; 96 : : } 97 : : 98 : 716 : void PublisherImpl::update_subscribers() { 99 : 716 : Utils::yield_cpu(); 100 : : 101 [ + - ]: 716 : std::unique_lock lock(helper_->callback_mtx); 102 [ + - ]: 716 : const bool has_subscribers_now = has_subscribers(); 103 : : 104 [ + + ]: 716 : if (helper_->has_subscribers.exchange(has_subscribers_now, std::memory_order_acq_rel) == has_subscribers_now) { 105 : 189 : return; 106 : : } 107 : : 108 : : { 109 [ + - ]: 527 : std::lock_guard sync_lock(helper_->mtx); 110 : 527 : } 111 : : 112 : 527 : helper_->connected_cv.notify_all(); 113 : : 114 [ + + ]: 527 : if (helper_->connected_callback) { 115 [ + - ]: 16 : auto callback_copy = helper_->connected_callback; 116 [ + - ]: 16 : lock.unlock(); 117 [ + - ]: 16 : callback_copy(has_subscribers_now); 118 : 16 : } 119 [ + + ]: 716 : } 120 : : 121 [ + - ]: 340 : PublisherImpl::PublisherImpl() : NodeImpl(kPublisher), helper_(std::make_unique<PublisherImplHelper>()) {} 122 : : 123 : : } // namespace vlink