LCOV - code coverage report
Current view: top level - wirestead/interface - channel.hpp (source / functions) Coverage Total Hit
Test: Wirestead Coverage Report Lines: 66.7 % 6 4
Test Date: 2026-08-30 10:35:09 Functions: 80.0 % 10 8
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 100.0 % 2 2

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * Copyright 2025 Jinwoo Sung
       3                 :             :  *
       4                 :             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5                 :             :  * you may not use this file except in compliance with the License.
       6                 :             :  * You may obtain a copy of the License at
       7                 :             :  *
       8                 :             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9                 :             :  *
      10                 :             :  * Unless required by applicable law or agreed to in writing, software
      11                 :             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12                 :             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13                 :             :  * See the License for the specific language governing permissions and
      14                 :             :  * limitations under the License.
      15                 :             :  */
      16                 :             : 
      17                 :             : #pragma once
      18                 :             : #include <boost/asio/any_io_executor.hpp>
      19                 :             : #include <functional>
      20                 :             : #include <memory>
      21                 :             : #include <optional>
      22                 :             : #include <utility>
      23                 :             : #include <vector>
      24                 :             : 
      25                 :             : #include "wirestead/base/common.hpp"
      26                 :             : #include "wirestead/base/visibility.hpp"
      27                 :             : #include "wirestead/diagnostics/error_types.hpp"
      28                 :             : #include "wirestead/memory/safe_span.hpp"
      29                 :             : #include "wirestead/wrapper/runtime_stats.hpp"
      30                 :             : 
      31                 :             : namespace wirestead {
      32                 :             : namespace interface {
      33                 :             : class WIRESTEAD_API Channel {
      34                 :             :  public:
      35                 :             :   using OnBytes = std::function<void(memory::ConstByteSpan)>;
      36                 :             :   using OnState = std::function<void(base::LinkState)>;
      37                 :             :   using OnBackpressure = std::function<void(size_t /*queued_bytes*/)>;
      38                 :             : 
      39                 :             :   virtual ~Channel();
      40                 :             : 
      41                 :             :   virtual void start() = 0;
      42                 :             :   virtual void stop() = 0;
      43                 :             :   virtual bool is_connected() const = 0;
      44                 :             :   virtual bool is_backpressure_active() const = 0;
      45                 :           0 :   virtual wrapper::RuntimeStats stats() const { return {}; }
      46                 :           0 :   virtual void reset_stats() {}
      47                 :             : 
      48                 :             :   // Most recent error recorded by this channel, if any. Default no-op
      49                 :             :   // override (std::nullopt) so any transport not yet wired up to the
      50                 :             :   // shared ErrorInfoHolder plumbing (#445) just reports "no detail
      51                 :             :   // available" instead of failing to compile or requiring a stub
      52                 :             :   // override everywhere.
      53                 :          10 :   virtual std::optional<diagnostics::ErrorInfo> last_error_info() const { return std::nullopt; }
      54                 :             : 
      55                 :             :   virtual boost::asio::any_io_executor get_executor() = 0;
      56                 :             : 
      57                 :             :   // Single send API (copies into internal queue)
      58                 :             :   virtual bool async_write_copy(memory::ConstByteSpan data) = 0;
      59                 :             :   // Zero-copy APIs (ownership transfer or shared ownership)
      60                 :             :   virtual bool async_write_move(std::vector<uint8_t>&& data) = 0;
      61                 :             :   virtual bool async_write_shared(std::shared_ptr<const std::vector<uint8_t>> data) = 0;
      62                 :             : 
      63                 :             :   // Explicit non-blocking drop-if-full send APIs. These must not enqueue into
      64                 :             :   // Reliable pending queues when backpressure is already active.
      65                 :             :   virtual bool async_try_write_copy(memory::ConstByteSpan data) = 0;
      66                 :             :   virtual bool async_try_write_move(std::vector<uint8_t>&& data) = 0;
      67                 :             :   virtual bool async_try_write_shared(std::shared_ptr<const std::vector<uint8_t>> data) = 0;
      68                 :             : 
      69                 :             :   // Callbacks. Thread-safe: may be called at any time, including after
      70                 :             :   // start(), from any thread. Replacing a callback is synchronized against
      71                 :             :   // concurrent invocation on the io thread - the implementation either
      72                 :             :   // guards storage with a mutex (copy-under-lock, invoke outside the lock)
      73                 :             :   // or dispatches the assignment onto the same strand the io thread runs
      74                 :             :   // on. Re-registering a callback takes effect for subsequent events; it
      75                 :             :   // does not retroactively affect an invocation already in progress (#436).
      76                 :             :   virtual void on_bytes(OnBytes cb) = 0;
      77                 :             :   virtual void on_state(OnState cb) = 0;
      78                 :             :   virtual void on_backpressure(OnBackpressure cb) = 0;
      79                 :             : };
      80                 :             : 
      81                 :             : // Snapshot type for a callback an implementation hands out to its io thread.
      82                 :             : //
      83                 :             : // The storage discipline above is unchanged - the mutex still guards the
      84                 :             : // member, and the callback is still invoked outside the lock. What changes is
      85                 :             : // the cost of the snapshot: copying a std::function heap-allocates whenever
      86                 :             : // the target does not fit its small-object buffer, and the receive path takes
      87                 :             : // one such copy per received chunk. Sharing an immutable copy turns that into
      88                 :             : // a refcount bump. The pointed-to callback is const, so a snapshot taken by
      89                 :             : // the io thread stays valid and unchanged even while a setter installs a
      90                 :             : // replacement, which is the same guarantee the copy provided (#436).
      91                 :             : template <typename Callback>
      92                 :             : using SharedCallback = std::shared_ptr<const Callback>;
      93                 :             : 
      94                 :             : // Returns null for an empty callback, so a non-null SharedCallback always
      95                 :             : // holds something invocable and callers need only the pointer check.
      96                 :             : // Call this outside the lock - it allocates.
      97                 :             : template <typename Callback>
      98                 :     1229731 : SharedCallback<Callback> share_callback(Callback cb) {
      99         [ +  + ]:     1229731 :   if (!cb) return {};
     100                 :     1228808 :   return std::make_shared<const Callback>(std::move(cb));
     101                 :             : }
     102                 :             : }  // namespace interface
     103                 :             : }  // namespace wirestead
        

Generated by: LCOV version 2.0-1