xref: /aosp_15_r20/external/pigweed/pw_rpc/public/pw_rpc/internal/call_context.h (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2020 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 #pragma once
15 
16 #include <cstddef>
17 #include <cstdint>
18 
19 #include "pw_rpc/channel.h"
20 #include "pw_rpc/internal/lock.h"
21 
22 namespace pw::rpc {
23 
24 class Service;
25 
26 namespace internal {
27 
28 class Endpoint;
29 class LockedCallContext;
30 class LockedEndpoint;
31 class Method;
32 
33 // The Server creates a CallContext object to represent a method invocation. The
34 // CallContext is used to initialize a call object for the RPC.
35 class CallContext {
36  public:
CallContext(Endpoint & server,uint32_t channel_id,Service & service,const internal::Method & method,uint32_t call_id)37   constexpr CallContext(Endpoint& server,
38                         uint32_t channel_id,
39                         Service& service,
40                         const internal::Method& method,
41                         uint32_t call_id)
42       : server_(server),
43         channel_id_(channel_id),
44         service_(service),
45         method_(method),
46         call_id_(call_id) {}
47 
48   // Claims that `rpc_lock()` is held, returning a wrapped context.
49   //
50   // This function should only be called in contexts in which it is clear that
51   // `rpc_lock()` is held. When calling this function from a constructor, the
52   // lock annotation will not result in errors, so care should be taken to
53   // ensure that `rpc_lock()` is held.
54   const LockedCallContext& ClaimLocked() const
55       PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock());
56 
57   LockedCallContext& ClaimLocked() PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock());
58 
server()59   constexpr Endpoint& server() const { return server_; }
60 
channel_id()61   constexpr const uint32_t& channel_id() const { return channel_id_; }
62 
service()63   constexpr Service& service() const { return service_; }
64 
method()65   constexpr const internal::Method& method() const { return method_; }
66 
call_id()67   constexpr const uint32_t& call_id() const { return call_id_; }
68 
69   // For testing use only
set_channel_id(uint32_t channel_id)70   void set_channel_id(uint32_t channel_id) { channel_id_ = channel_id; }
71 
72  private:
73   Endpoint& server_;
74   uint32_t channel_id_;
75   Service& service_;
76   const internal::Method& method_;
77   uint32_t call_id_;
78 };
79 
80 // A `CallContext` indicating that `rpc_lock()` is held.
81 //
82 // This is used as a constructor argument to supplement
83 // `PW_EXCLUSIVE_LOCKS_REQUIRED(rpc_lock())`. Current compilers do not enforce
84 // lock annotations on constructors; no warnings or errors are produced when
85 // calling an annotated constructor without holding `rpc_lock()`.
86 class LockedCallContext : public CallContext {
87  public:
88   friend class CallContext;
89   // No public constructor: this is created only via the `ClaimLocked` method on
90   // `CallContext`.
91   constexpr LockedCallContext() = delete;
92 };
93 
ClaimLocked()94 inline const LockedCallContext& CallContext::ClaimLocked() const {
95   return *static_cast<const LockedCallContext*>(this);
96 }
97 
ClaimLocked()98 inline LockedCallContext& CallContext::ClaimLocked() {
99   return *static_cast<LockedCallContext*>(this);
100 }
101 
102 }  // namespace internal
103 }  // namespace pw::rpc
104