xref: /aosp_15_r20/external/libchrome/mojo/public/cpp/system/handle.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2014 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #ifndef MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_
6*635a8641SAndroid Build Coastguard Worker #define MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_
7*635a8641SAndroid Build Coastguard Worker 
8*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
9*635a8641SAndroid Build Coastguard Worker #include <limits>
10*635a8641SAndroid Build Coastguard Worker 
11*635a8641SAndroid Build Coastguard Worker #include "base/compiler_specific.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
14*635a8641SAndroid Build Coastguard Worker #include "mojo/public/c/system/functions.h"
15*635a8641SAndroid Build Coastguard Worker #include "mojo/public/c/system/types.h"
16*635a8641SAndroid Build Coastguard Worker #include "mojo/public/cpp/system/handle_signals_state.h"
17*635a8641SAndroid Build Coastguard Worker 
18*635a8641SAndroid Build Coastguard Worker namespace mojo {
19*635a8641SAndroid Build Coastguard Worker 
20*635a8641SAndroid Build Coastguard Worker // OVERVIEW
21*635a8641SAndroid Build Coastguard Worker //
22*635a8641SAndroid Build Coastguard Worker // |Handle| and |...Handle|:
23*635a8641SAndroid Build Coastguard Worker //
24*635a8641SAndroid Build Coastguard Worker // |Handle| is a simple, copyable wrapper for the C type |MojoHandle| (which is
25*635a8641SAndroid Build Coastguard Worker // just an integer). Its purpose is to increase type-safety, not provide
26*635a8641SAndroid Build Coastguard Worker // lifetime management. For the same purpose, we have trivial *subclasses* of
27*635a8641SAndroid Build Coastguard Worker // |Handle|, e.g., |MessagePipeHandle| and |DataPipeProducerHandle|. |Handle|
28*635a8641SAndroid Build Coastguard Worker // and its subclasses impose *no* extra overhead over using |MojoHandle|s
29*635a8641SAndroid Build Coastguard Worker // directly.
30*635a8641SAndroid Build Coastguard Worker //
31*635a8641SAndroid Build Coastguard Worker // Note that though we provide constructors for |Handle|/|...Handle| from a
32*635a8641SAndroid Build Coastguard Worker // |MojoHandle|, we do not provide, e.g., a constructor for |MessagePipeHandle|
33*635a8641SAndroid Build Coastguard Worker // from a |Handle|. This is for type safety: If we did, you'd then be able to
34*635a8641SAndroid Build Coastguard Worker // construct a |MessagePipeHandle| from, e.g., a |DataPipeProducerHandle| (since
35*635a8641SAndroid Build Coastguard Worker // it's a |Handle|).
36*635a8641SAndroid Build Coastguard Worker //
37*635a8641SAndroid Build Coastguard Worker // |ScopedHandleBase| and |Scoped...Handle|:
38*635a8641SAndroid Build Coastguard Worker //
39*635a8641SAndroid Build Coastguard Worker // |ScopedHandleBase<HandleType>| is a templated scoped wrapper, for the handle
40*635a8641SAndroid Build Coastguard Worker // types above (in the same sense that a C++11 |unique_ptr<T>| is a scoped
41*635a8641SAndroid Build Coastguard Worker // wrapper for a |T*|). It provides lifetime management, closing its owned
42*635a8641SAndroid Build Coastguard Worker // handle on destruction. It also provides move semantics, again along the lines
43*635a8641SAndroid Build Coastguard Worker // of C++11's |unique_ptr|. A moved-from |ScopedHandleBase<HandleType>| sets its
44*635a8641SAndroid Build Coastguard Worker // handle value to MOJO_HANDLE_INVALID.
45*635a8641SAndroid Build Coastguard Worker //
46*635a8641SAndroid Build Coastguard Worker // |ScopedHandle| is just (a typedef of) a |ScopedHandleBase<Handle>|.
47*635a8641SAndroid Build Coastguard Worker // Similarly, |ScopedMessagePipeHandle| is just a
48*635a8641SAndroid Build Coastguard Worker // |ScopedHandleBase<MessagePipeHandle>|. Etc. Note that a
49*635a8641SAndroid Build Coastguard Worker // |ScopedMessagePipeHandle| is *not* a (subclass of) |ScopedHandle|.
50*635a8641SAndroid Build Coastguard Worker //
51*635a8641SAndroid Build Coastguard Worker // Wrapper functions:
52*635a8641SAndroid Build Coastguard Worker //
53*635a8641SAndroid Build Coastguard Worker // We provide simple wrappers for the |Mojo...()| functions (in
54*635a8641SAndroid Build Coastguard Worker // mojo/public/c/system/core.h -- see that file for details on individual
55*635a8641SAndroid Build Coastguard Worker // functions).
56*635a8641SAndroid Build Coastguard Worker //
57*635a8641SAndroid Build Coastguard Worker // The general guideline is functions that imply ownership transfer of a handle
58*635a8641SAndroid Build Coastguard Worker // should take (or produce) an appropriate |Scoped...Handle|, while those that
59*635a8641SAndroid Build Coastguard Worker // don't take a |...Handle|. For example, |CreateMessagePipe()| has two
60*635a8641SAndroid Build Coastguard Worker // |ScopedMessagePipe| "out" parameters, whereas |Wait()| and |WaitMany()| take
61*635a8641SAndroid Build Coastguard Worker // |Handle| parameters. Some, have both: e.g., |DuplicatedBuffer()| takes a
62*635a8641SAndroid Build Coastguard Worker // suitable (unscoped) handle (e.g., |SharedBufferHandle|) "in" parameter and
63*635a8641SAndroid Build Coastguard Worker // produces a suitable scoped handle (e.g., |ScopedSharedBufferHandle| a.k.a.
64*635a8641SAndroid Build Coastguard Worker // |ScopedHandleBase<SharedBufferHandle>|) as an "out" parameter.
65*635a8641SAndroid Build Coastguard Worker //
66*635a8641SAndroid Build Coastguard Worker // An exception are some of the |...Raw()| functions. E.g., |CloseRaw()| takes a
67*635a8641SAndroid Build Coastguard Worker // |Handle|, leaving the user to discard the wrapper.
68*635a8641SAndroid Build Coastguard Worker //
69*635a8641SAndroid Build Coastguard Worker // ScopedHandleBase ------------------------------------------------------------
70*635a8641SAndroid Build Coastguard Worker 
71*635a8641SAndroid Build Coastguard Worker // Scoper for the actual handle types defined further below. It's move-only,
72*635a8641SAndroid Build Coastguard Worker // like the C++11 |unique_ptr|.
73*635a8641SAndroid Build Coastguard Worker template <class HandleType>
74*635a8641SAndroid Build Coastguard Worker class ScopedHandleBase {
75*635a8641SAndroid Build Coastguard Worker  public:
76*635a8641SAndroid Build Coastguard Worker   using RawHandleType = HandleType;
77*635a8641SAndroid Build Coastguard Worker 
ScopedHandleBase()78*635a8641SAndroid Build Coastguard Worker   ScopedHandleBase() {}
ScopedHandleBase(HandleType handle)79*635a8641SAndroid Build Coastguard Worker   explicit ScopedHandleBase(HandleType handle) : handle_(handle) {}
~ScopedHandleBase()80*635a8641SAndroid Build Coastguard Worker   ~ScopedHandleBase() { CloseIfNecessary(); }
81*635a8641SAndroid Build Coastguard Worker 
82*635a8641SAndroid Build Coastguard Worker   template <class CompatibleHandleType>
ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other)83*635a8641SAndroid Build Coastguard Worker   explicit ScopedHandleBase(ScopedHandleBase<CompatibleHandleType> other)
84*635a8641SAndroid Build Coastguard Worker       : handle_(other.release()) {}
85*635a8641SAndroid Build Coastguard Worker 
86*635a8641SAndroid Build Coastguard Worker   // Move-only constructor and operator=.
ScopedHandleBase(ScopedHandleBase && other)87*635a8641SAndroid Build Coastguard Worker   ScopedHandleBase(ScopedHandleBase&& other) noexcept
88*635a8641SAndroid Build Coastguard Worker       : handle_(other.release()) {}
89*635a8641SAndroid Build Coastguard Worker   ScopedHandleBase& operator=(ScopedHandleBase&& other) noexcept {
90*635a8641SAndroid Build Coastguard Worker     if (&other != this) {
91*635a8641SAndroid Build Coastguard Worker       CloseIfNecessary();
92*635a8641SAndroid Build Coastguard Worker       handle_ = other.release();
93*635a8641SAndroid Build Coastguard Worker     }
94*635a8641SAndroid Build Coastguard Worker     return *this;
95*635a8641SAndroid Build Coastguard Worker   }
96*635a8641SAndroid Build Coastguard Worker 
get()97*635a8641SAndroid Build Coastguard Worker   const HandleType& get() const { return handle_; }
98*635a8641SAndroid Build Coastguard Worker   const HandleType* operator->() const {
99*635a8641SAndroid Build Coastguard Worker     DCHECK(handle_.is_valid());
100*635a8641SAndroid Build Coastguard Worker     return &handle_;
101*635a8641SAndroid Build Coastguard Worker   }
102*635a8641SAndroid Build Coastguard Worker 
103*635a8641SAndroid Build Coastguard Worker   template <typename PassedHandleType>
From(ScopedHandleBase<PassedHandleType> other)104*635a8641SAndroid Build Coastguard Worker   static ScopedHandleBase<HandleType> From(
105*635a8641SAndroid Build Coastguard Worker       ScopedHandleBase<PassedHandleType> other) {
106*635a8641SAndroid Build Coastguard Worker     static_assert(
107*635a8641SAndroid Build Coastguard Worker         sizeof(static_cast<PassedHandleType*>(static_cast<HandleType*>(0))),
108*635a8641SAndroid Build Coastguard Worker         "HandleType is not a subtype of PassedHandleType");
109*635a8641SAndroid Build Coastguard Worker     return ScopedHandleBase<HandleType>(
110*635a8641SAndroid Build Coastguard Worker         static_cast<HandleType>(other.release().value()));
111*635a8641SAndroid Build Coastguard Worker   }
112*635a8641SAndroid Build Coastguard Worker 
swap(ScopedHandleBase & other)113*635a8641SAndroid Build Coastguard Worker   void swap(ScopedHandleBase& other) { handle_.swap(other.handle_); }
114*635a8641SAndroid Build Coastguard Worker 
release()115*635a8641SAndroid Build Coastguard Worker   HandleType release() WARN_UNUSED_RESULT {
116*635a8641SAndroid Build Coastguard Worker     HandleType rv;
117*635a8641SAndroid Build Coastguard Worker     rv.swap(handle_);
118*635a8641SAndroid Build Coastguard Worker     return rv;
119*635a8641SAndroid Build Coastguard Worker   }
120*635a8641SAndroid Build Coastguard Worker 
121*635a8641SAndroid Build Coastguard Worker   void reset(HandleType handle = HandleType()) {
122*635a8641SAndroid Build Coastguard Worker     CloseIfNecessary();
123*635a8641SAndroid Build Coastguard Worker     handle_ = handle;
124*635a8641SAndroid Build Coastguard Worker   }
125*635a8641SAndroid Build Coastguard Worker 
is_valid()126*635a8641SAndroid Build Coastguard Worker   bool is_valid() const { return handle_.is_valid(); }
127*635a8641SAndroid Build Coastguard Worker 
128*635a8641SAndroid Build Coastguard Worker   explicit operator bool() const { return handle_; }
129*635a8641SAndroid Build Coastguard Worker 
130*635a8641SAndroid Build Coastguard Worker   bool operator==(const ScopedHandleBase& other) const {
131*635a8641SAndroid Build Coastguard Worker     return handle_.value() == other.get().value();
132*635a8641SAndroid Build Coastguard Worker   }
133*635a8641SAndroid Build Coastguard Worker 
134*635a8641SAndroid Build Coastguard Worker  private:
CloseIfNecessary()135*635a8641SAndroid Build Coastguard Worker   void CloseIfNecessary() {
136*635a8641SAndroid Build Coastguard Worker     if (handle_.is_valid())
137*635a8641SAndroid Build Coastguard Worker       handle_.Close();
138*635a8641SAndroid Build Coastguard Worker   }
139*635a8641SAndroid Build Coastguard Worker 
140*635a8641SAndroid Build Coastguard Worker   HandleType handle_;
141*635a8641SAndroid Build Coastguard Worker 
142*635a8641SAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedHandleBase);
143*635a8641SAndroid Build Coastguard Worker };
144*635a8641SAndroid Build Coastguard Worker 
145*635a8641SAndroid Build Coastguard Worker template <typename HandleType>
MakeScopedHandle(HandleType handle)146*635a8641SAndroid Build Coastguard Worker inline ScopedHandleBase<HandleType> MakeScopedHandle(HandleType handle) {
147*635a8641SAndroid Build Coastguard Worker   return ScopedHandleBase<HandleType>(handle);
148*635a8641SAndroid Build Coastguard Worker }
149*635a8641SAndroid Build Coastguard Worker 
150*635a8641SAndroid Build Coastguard Worker // Handle ----------------------------------------------------------------------
151*635a8641SAndroid Build Coastguard Worker 
152*635a8641SAndroid Build Coastguard Worker const MojoHandle kInvalidHandleValue = MOJO_HANDLE_INVALID;
153*635a8641SAndroid Build Coastguard Worker 
154*635a8641SAndroid Build Coastguard Worker // Wrapper base class for |MojoHandle|.
155*635a8641SAndroid Build Coastguard Worker class Handle {
156*635a8641SAndroid Build Coastguard Worker  public:
Handle()157*635a8641SAndroid Build Coastguard Worker   Handle() : value_(kInvalidHandleValue) {}
Handle(MojoHandle value)158*635a8641SAndroid Build Coastguard Worker   explicit Handle(MojoHandle value) : value_(value) {}
~Handle()159*635a8641SAndroid Build Coastguard Worker   ~Handle() {}
160*635a8641SAndroid Build Coastguard Worker 
swap(Handle & other)161*635a8641SAndroid Build Coastguard Worker   void swap(Handle& other) {
162*635a8641SAndroid Build Coastguard Worker     MojoHandle temp = value_;
163*635a8641SAndroid Build Coastguard Worker     value_ = other.value_;
164*635a8641SAndroid Build Coastguard Worker     other.value_ = temp;
165*635a8641SAndroid Build Coastguard Worker   }
166*635a8641SAndroid Build Coastguard Worker 
is_valid()167*635a8641SAndroid Build Coastguard Worker   bool is_valid() const { return value_ != kInvalidHandleValue; }
168*635a8641SAndroid Build Coastguard Worker 
169*635a8641SAndroid Build Coastguard Worker   explicit operator bool() const { return value_ != kInvalidHandleValue; }
170*635a8641SAndroid Build Coastguard Worker 
value()171*635a8641SAndroid Build Coastguard Worker   const MojoHandle& value() const { return value_; }
mutable_value()172*635a8641SAndroid Build Coastguard Worker   MojoHandle* mutable_value() { return &value_; }
set_value(MojoHandle value)173*635a8641SAndroid Build Coastguard Worker   void set_value(MojoHandle value) { value_ = value; }
174*635a8641SAndroid Build Coastguard Worker 
Close()175*635a8641SAndroid Build Coastguard Worker   void Close() {
176*635a8641SAndroid Build Coastguard Worker     DCHECK(is_valid());
177*635a8641SAndroid Build Coastguard Worker     MojoResult result = MojoClose(value_);
178*635a8641SAndroid Build Coastguard Worker     ALLOW_UNUSED_LOCAL(result);
179*635a8641SAndroid Build Coastguard Worker     DCHECK_EQ(MOJO_RESULT_OK, result);
180*635a8641SAndroid Build Coastguard Worker   }
181*635a8641SAndroid Build Coastguard Worker 
QuerySignalsState()182*635a8641SAndroid Build Coastguard Worker   HandleSignalsState QuerySignalsState() const {
183*635a8641SAndroid Build Coastguard Worker     HandleSignalsState signals_state;
184*635a8641SAndroid Build Coastguard Worker     MojoResult result = MojoQueryHandleSignalsState(
185*635a8641SAndroid Build Coastguard Worker         value_, static_cast<MojoHandleSignalsState*>(&signals_state));
186*635a8641SAndroid Build Coastguard Worker     DCHECK_EQ(MOJO_RESULT_OK, result);
187*635a8641SAndroid Build Coastguard Worker     return signals_state;
188*635a8641SAndroid Build Coastguard Worker   }
189*635a8641SAndroid Build Coastguard Worker 
190*635a8641SAndroid Build Coastguard Worker  private:
191*635a8641SAndroid Build Coastguard Worker   MojoHandle value_;
192*635a8641SAndroid Build Coastguard Worker 
193*635a8641SAndroid Build Coastguard Worker   // Copying and assignment allowed.
194*635a8641SAndroid Build Coastguard Worker };
195*635a8641SAndroid Build Coastguard Worker 
196*635a8641SAndroid Build Coastguard Worker // Should have zero overhead.
197*635a8641SAndroid Build Coastguard Worker static_assert(sizeof(Handle) == sizeof(MojoHandle), "Bad size for C++ Handle");
198*635a8641SAndroid Build Coastguard Worker 
199*635a8641SAndroid Build Coastguard Worker // The scoper should also impose no more overhead.
200*635a8641SAndroid Build Coastguard Worker typedef ScopedHandleBase<Handle> ScopedHandle;
201*635a8641SAndroid Build Coastguard Worker static_assert(sizeof(ScopedHandle) == sizeof(Handle),
202*635a8641SAndroid Build Coastguard Worker               "Bad size for C++ ScopedHandle");
203*635a8641SAndroid Build Coastguard Worker 
204*635a8641SAndroid Build Coastguard Worker // |Close()| takes ownership of the handle, since it'll invalidate it.
205*635a8641SAndroid Build Coastguard Worker // Note: There's nothing to do, since the argument will be destroyed when it
206*635a8641SAndroid Build Coastguard Worker // goes out of scope.
207*635a8641SAndroid Build Coastguard Worker template <class HandleType>
Close(ScopedHandleBase<HandleType>)208*635a8641SAndroid Build Coastguard Worker inline void Close(ScopedHandleBase<HandleType> /*handle*/) {
209*635a8641SAndroid Build Coastguard Worker }
210*635a8641SAndroid Build Coastguard Worker 
211*635a8641SAndroid Build Coastguard Worker // Most users should typically use |Close()| (above) instead.
CloseRaw(Handle handle)212*635a8641SAndroid Build Coastguard Worker inline MojoResult CloseRaw(Handle handle) {
213*635a8641SAndroid Build Coastguard Worker   return MojoClose(handle.value());
214*635a8641SAndroid Build Coastguard Worker }
215*635a8641SAndroid Build Coastguard Worker 
216*635a8641SAndroid Build Coastguard Worker // Strict weak ordering, so that |Handle|s can be used as keys in |std::map|s,
217*635a8641SAndroid Build Coastguard Worker inline bool operator<(const Handle a, const Handle b) {
218*635a8641SAndroid Build Coastguard Worker   return a.value() < b.value();
219*635a8641SAndroid Build Coastguard Worker }
220*635a8641SAndroid Build Coastguard Worker 
221*635a8641SAndroid Build Coastguard Worker // Comparison, so that |Handle|s can be used as keys in hash maps.
222*635a8641SAndroid Build Coastguard Worker inline bool operator==(const Handle a, const Handle b) {
223*635a8641SAndroid Build Coastguard Worker   return a.value() == b.value();
224*635a8641SAndroid Build Coastguard Worker }
225*635a8641SAndroid Build Coastguard Worker 
226*635a8641SAndroid Build Coastguard Worker }  // namespace mojo
227*635a8641SAndroid Build Coastguard Worker 
228*635a8641SAndroid Build Coastguard Worker #endif  // MOJO_PUBLIC_CPP_SYSTEM_HANDLE_H_
229