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 "./ddsc_getter_impl.hpp" 25 : : 26 : : #include <memory> 27 : : #include <utility> 28 : : 29 : : #include "./base/elapsed_timer.h" 30 : : #include "./base/message_loop.h" 31 : : 32 : : namespace vlink { 33 : : 34 : : // ReaderListener 35 : 22 : DdscGetterImpl::ReaderListener::ReaderListener(NodeImpl* impl) : DdscReaderListener(impl) {} 36 : : 37 : 25 : void DdscGetterImpl::ReaderListener::on_data_available(NodeImpl* impl, dds_entity_t reader) { 38 : 25 : auto* instance = static_cast<DdscGetterImpl*>(impl); 39 : 25 : auto* message_loop = instance->get_message_loop(); 40 : : 41 [ + + ]: 25 : if VUNLIKELY (instance->has_suspend.load(std::memory_order_acquire)) { 42 : 1 : DdscFactory::ReadMessage msg; 43 : : 44 [ + - + + ]: 2 : while (DdscFactory::take_data(reader, msg)) { 45 [ + - ]: 1 : DdscFactory::release_data(reader, msg); 46 : : 47 [ - + ]: 1 : if VUNLIKELY (instance->quit_flag_.load(std::memory_order_acquire)) { 48 : 0 : break; 49 : : } 50 : : } 51 : : 52 : 1 : return; 53 : 1 : } 54 : : 55 [ - + ]: 24 : if VUNLIKELY (!instance->callback_) { 56 : 0 : return; 57 : : } 58 : : 59 [ + + ]: 24 : if (message_loop) { 60 [ + - + - ]: 1 : message_loop->post_task([instance, reader]() { 61 [ - + ]: 1 : if VUNLIKELY (!instance->get_message_loop()) { 62 : 0 : return; 63 : : } 64 : : 65 : 1 : instance->process_message(reader); 66 : : }); 67 : : } else { 68 : 23 : instance->process_message(reader); 69 : : } 70 : : } 71 : : 72 : : // DdscGetterImpl 73 [ + - + - ]: 25 : DdscGetterImpl::DdscGetterImpl(const DdscConf& conf) : conf_(conf) {} 74 : : 75 : 24 : void DdscGetterImpl::process_message(dds_entity_t reader) { 76 : 24 : DdscFactory::ReadMessage msg; 77 : : 78 [ + - + + ]: 48 : while (DdscFactory::take_data(reader, msg)) { 79 [ - + ]: 24 : if VUNLIKELY (quit_flag_.load(std::memory_order_acquire)) { 80 [ # # ]: 0 : DdscFactory::release_data(reader, msg); 81 : 0 : break; 82 : : } 83 : : 84 [ - + ]: 24 : if VUNLIKELY (!msg.info.valid_data) { 85 [ # # ]: 0 : DdscFactory::release_data(reader, msg); 86 : 0 : continue; 87 : : } 88 : : 89 [ + + ]: 24 : if VUNLIKELY (is_latency_and_lost_enabled_.load(std::memory_order_acquire)) { 90 : 10 : last_latency_.store(ElapsedTimer::get_sys_timestamp(ElapsedTimer::kNano, false) - msg.timestamp, 91 : : std::memory_order_relaxed); 92 : : 93 : 10 : calc_sample_.update(msg.id, msg.guid); 94 : : } 95 : : 96 [ + - ]: 24 : callback_(msg.bytes); 97 : : 98 [ + - ]: 24 : DdscFactory::release_data(reader, msg); 99 : : } 100 : 24 : } 101 : : 102 : 22 : void DdscGetterImpl::init() { 103 [ + - ]: 22 : participant_ = DdscFactory::create_participant(kPublisher | kSubscriber, conf_, get_all_properties()); 104 : : 105 [ + - + - ]: 22 : topic_ = DdscFactory::create_topic(kPublisher | kSubscriber, conf_, participant_.get()); 106 : : 107 : 22 : subscriber_ = DdscFactory::create_subscriber(kSubscriber, conf_, participant_.get()); 108 : : 109 [ + - - + : 22 : if VUNLIKELY (!participant_ || !topic_) { - + ] 110 [ # # # # ]: 0 : VLOG_E("DdscGetterImpl::init(): participant/topic creation failed; getter left uninitialised."); 111 : : 112 : 0 : return; 113 : : } 114 : : 115 : 22 : quit_flag_.store(false, std::memory_order_release); 116 : : } 117 : : 118 : 22 : void DdscGetterImpl::deinit() { 119 : 22 : quit_flag_.store(true, std::memory_order_release); 120 : : 121 : 22 : detach(); 122 : : 123 : 22 : reader_.reset(); 124 : 22 : listener_.reset(); 125 : 22 : subscriber_.reset(); 126 : 22 : topic_.reset(); 127 : 22 : participant_.reset(); 128 : 22 : } 129 : : 130 : 2 : bool DdscGetterImpl::suspend() { 131 : 2 : has_suspend.store(true, std::memory_order_release); 132 : : 133 : 2 : return true; 134 : : } 135 : : 136 : 2 : bool DdscGetterImpl::resume() { 137 : 2 : has_suspend.store(false, std::memory_order_release); 138 : : 139 : 2 : return true; 140 : : } 141 : : 142 : 3 : bool DdscGetterImpl::is_suspend() const { return has_suspend.load(std::memory_order_acquire); } 143 : : 144 : 0 : const Conf* DdscGetterImpl::get_conf() const { return &conf_; } 145 : : 146 : 2 : const AbstractNode* DdscGetterImpl::get_abstract_node() const { return this; } 147 : : 148 : 4 : Status::BasePtr DdscGetterImpl::get_status(Status::Type type) const { 149 [ + + ]: 4 : if VUNLIKELY (!reader_) { 150 : 1 : return std::make_shared<Status::Unknown>(); 151 : : } 152 : : 153 : 3 : return ReaderListener::get_status(reader_->entity, type); 154 : : } 155 : : 156 : 1 : std::any DdscGetterImpl::get_native_handle() const { return subscriber_; } 157 : : 158 : 22 : bool DdscGetterImpl::listen(MsgCallback&& callback) { 159 [ - + ]: 22 : if VUNLIKELY (callback_) { 160 : 0 : return false; 161 : : } 162 : : 163 : 22 : callback_ = std::move(callback); 164 : : 165 [ + - ]: 22 : listener_.emplace(this); 166 : : 167 : 22 : reader_ = DdscFactory::create_datareader(kGetter, conf_, subscriber_.get(), topic_.get(), listener_->get_ptr()); 168 : : 169 : 22 : return true; 170 : : } 171 : : 172 : 4 : void DdscGetterImpl::set_latency_and_lost_enabled(bool enable) { 173 : 4 : is_latency_and_lost_enabled_.store(enable, std::memory_order_release); 174 : 4 : } 175 : : 176 : 4 : bool DdscGetterImpl::is_latency_and_lost_enabled() const { 177 : 4 : return is_latency_and_lost_enabled_.load(std::memory_order_acquire); 178 : : } 179 : : 180 : 2 : int64_t DdscGetterImpl::get_latency() const { 181 [ + + ]: 2 : if (!is_latency_and_lost_enabled_.load(std::memory_order_acquire)) { 182 : 1 : return 0; 183 : : } 184 : : 185 : 2 : return last_latency_.load(std::memory_order_relaxed); 186 : : } 187 : : 188 : 3 : SampleLostInfo DdscGetterImpl::get_lost() const { 189 [ + + ]: 3 : if (!is_latency_and_lost_enabled_.load(std::memory_order_acquire)) { 190 : 1 : return SampleLostInfo(); 191 : : } 192 : : 193 : 2 : return SampleLostInfo{calc_sample_.get_total(), calc_sample_.get_lost()}; 194 : : } 195 : : 196 : : } // namespace vlink