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 "./shm_client_impl.h" 25 : : 26 : : #include <utility> 27 : : 28 : : #include "./base/elapsed_timer.h" 29 : : #include "./base/helpers.h" 30 : : 31 : : namespace vlink { 32 : : 33 : : // ShmClientImpl 34 [ + - + - ]: 17 : ShmClientImpl::ShmClientImpl(const ShmConf& conf) : conf_(conf) {} 35 : : 36 : 17 : void ShmClientImpl::init() { 37 [ + + + - : 17 : static auto& factory = ShmFactory::get(); + - - - ] 38 : : 39 : 17 : conf_.hash_code = Helpers::get_hash_code(conf_.event); 40 : : 41 : : object_ = 42 [ + - ]: 17 : factory.get_object<Object>({kImplType, conf_.address, conf_.domain, conf_.depth, conf_.history, conf_.wait}); 43 : : 44 : 17 : object_->add_impl(this); 45 : : 46 [ + - + - ]: 17 : object_->register_server_connect_callback(this, [this](bool) { 47 : 15 : auto* message_loop = get_message_loop(); 48 : : 49 [ + + ]: 15 : if (message_loop) { 50 [ + - + - ]: 2 : message_loop->post_task([this]() { ClientImpl::update_connected(); }); 51 : : } else { 52 : 14 : ClientImpl::update_connected(); 53 : : } 54 : 15 : }); 55 : : 56 : 17 : ClientImpl::update_connected(); 57 : 17 : } 58 : : 59 : 17 : void ShmClientImpl::deinit() { 60 : 17 : object_->remove_impl(this); 61 : : 62 : 17 : detach(); 63 : 17 : } 64 : : 65 : 17 : void ShmClientImpl::interrupt() { 66 : 17 : ClientImpl::interrupt(); 67 : : 68 : 17 : ack_manager_.clear(); 69 : 17 : } 70 : : 71 : 18 : bool ShmClientImpl::is_support_loan() const { return true; } 72 : : 73 : 19 : Bytes ShmClientImpl::loan(int64_t size) { return object_->loan(static_cast<uint64_t>(conf_.hash_code), size); } 74 : : 75 : 1 : bool ShmClientImpl::return_loan(const Bytes& bytes) { return object_->release(bytes); } 76 : : 77 : 0 : const Conf* ShmClientImpl::get_conf() const { return &conf_; } 78 : : 79 : 2 : const AbstractNode* ShmClientImpl::get_abstract_node() const { return object_.get(); } 80 : : 81 : 140 : bool ShmClientImpl::is_connected() const { return object_->is_connected(); } 82 : : 83 : 2 : void ShmClientImpl::detect_connected(ConnectCallback&& callback) { 84 : 2 : object_->enable_detect_timer(); 85 : : 86 : 2 : ClientImpl::detect_connected(std::move(callback)); 87 : 2 : } 88 : : 89 : 26 : bool ShmClientImpl::wait_for_connected(std::chrono::milliseconds timeout) { 90 : 26 : object_->enable_detect_timer(); 91 : : 92 : 26 : return ClientImpl::wait_for_connected(timeout); 93 : : } 94 : : 95 : 19 : bool ShmClientImpl::call(const Bytes& req_data, MsgCallback&& callback, std::chrono::milliseconds timeout) { 96 [ + + ]: 19 : if VUNLIKELY (!callback) { 97 [ + - ]: 3 : return object_->call(static_cast<uint64_t>(conf_.hash_code), req_data); 98 : : } 99 : : 100 [ + + ]: 16 : if (timeout.count() != 0) { 101 : 13 : ack_manager_.reset_interrupted(); 102 : : 103 : 13 : ElapsedTimer timer; 104 : 13 : timer.start(); 105 : : 106 [ + - + + ]: 13 : if (!wait_for_connected(timeout)) { 107 : 1 : return false; 108 : : } 109 : : 110 : 12 : auto elapsed = timer.get(); 111 : : 112 [ + - - + : 12 : if (timeout.count() > 0 && elapsed >= timeout.count()) { - + ] 113 : 0 : return false; 114 : : } 115 : : 116 : 12 : auto ack_request = ack_manager_.create_request(); 117 : : 118 : 12 : auto ack_function = [this, ack_request, callback = std::move(callback)](const Bytes& resp_data) mutable { 119 [ + - ]: 22 : ack_manager_.notify(ack_request, [&callback, &resp_data]() { callback(resp_data); }); 120 : 35 : }; 121 : : 122 : 12 : uint64_t response_seq = 0; 123 : 12 : bool has_response_seq = false; 124 : : 125 [ + - ]: 24 : bool ret = ack_manager_.process( 126 : 12 : ack_request, timeout.count() - elapsed, 127 : 12 : [this, &req_data, &response_seq, &has_response_seq, ack_function = std::move(ack_function)]() mutable { 128 : 12 : has_response_seq = 129 [ + - ]: 12 : object_->call(static_cast<uint64_t>(conf_.hash_code), req_data, std::move(ack_function), &response_seq); 130 : 12 : return has_response_seq; 131 : : }); 132 : : 133 [ + + + - : 12 : if VUNLIKELY (!ret && has_response_seq) { + + ] 134 [ + - ]: 1 : object_->remove_response_callback(response_seq); 135 : : } 136 : : 137 : 12 : return ret; 138 : 13 : } 139 : : 140 : 3 : return object_->call(static_cast<uint64_t>(conf_.hash_code), req_data, std::move(callback)); 141 : : } 142 : : 143 : : } // namespace vlink