910e62b5创建于 1月15日历史提交
// 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_