1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79

mojo / core / scoped_ipcz_handle.h [blame]

// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef MOJO_CORE_SCOPED_IPCZ_HANDLE_H_
#define MOJO_CORE_SCOPED_IPCZ_HANDLE_H_

#include <utility>

#include "base/check.h"
#include "base/memory/raw_ref.h"
#include "mojo/core/system_impl_export.h"
#include "third_party/ipcz/include/ipcz/ipcz.h"

namespace mojo::core {

// ScopedIpczHandle implements unique ownership of an IpczHandle. This object
// closes the underlying handle value on destruction if it hasn't been closed
// yet.
class MOJO_SYSTEM_IMPL_EXPORT ScopedIpczHandle {
 public:
  // Receiver is an adapter which can be used to pass a ScopedIpczHandle as an
  // IpczHandle*, for interfacing with C APIs that return handles through
  // output parameters. For some function like:
  //
  //     Foo(IpczHandle* out_handle)
  //
  // We can receive Foo's output into a ScopedIpczHandles with something like:
  //
  //     ScopedIpczHandle foo;
  //     Foo(ScopedIpczHandle::Receiver(foo))
  //
  class Receiver {
   public:
    explicit Receiver(ScopedIpczHandle& target) : target_(target) {}

    ~Receiver() {
      if (received_handle_ != IPCZ_INVALID_HANDLE) {
        (*target_) = ScopedIpczHandle(received_handle_);
      }
    }

    operator IpczHandle*() { return &received_handle_; }

   private:
    const raw_ref<ScopedIpczHandle> target_;
    IpczHandle received_handle_ = IPCZ_INVALID_HANDLE;
  };

  ScopedIpczHandle();
  explicit ScopedIpczHandle(IpczHandle handle);
  ScopedIpczHandle(ScopedIpczHandle&&);
  ScopedIpczHandle(const ScopedIpczHandle&) = delete;
  ScopedIpczHandle& operator=(ScopedIpczHandle&&);
  ScopedIpczHandle& operator=(const ScopedIpczHandle&) = delete;
  ~ScopedIpczHandle();

  bool is_valid() const { return handle_ != IPCZ_INVALID_HANDLE; }
  const IpczHandle& get() const { return handle_; }

  // Resets this object to an invalid handle, closing the previously held handle
  // if it was valid.
  void reset();

  // Releases ownership of the underlying IpczHandle and returns its value.
  [[nodiscard]] IpczHandle release() {
    return std::exchange(handle_, IPCZ_INVALID_HANDLE);
  }

 private:
  IpczHandle handle_ = IPCZ_INVALID_HANDLE;
};

static_assert(sizeof(IpczHandle) == sizeof(ScopedIpczHandle),
              "ScopedIpczHandle must be the same size as IpczHandle.");

}  // namespace mojo::core

#endif  // MOJO_CORE_SCOPED_IPCZ_HANDLE_H_