Index: base/files/scoped_platform_handle.cc |
diff --git a/base/files/scoped_platform_handle.cc b/base/files/scoped_platform_handle.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a6528732ba7b9040f3a397fd2eb1b78b7bc31407 |
--- /dev/null |
+++ b/base/files/scoped_platform_handle.cc |
@@ -0,0 +1,241 @@ |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/files/scoped_platform_handle.h" |
+ |
+#include "base/logging.h" |
+ |
+namespace base { |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle() : ScopedPlatformHandle(nullptr) {} |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(std::nullptr_t) |
+ : type_(Type::INVALID) {} |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(ScopedPlatformHandle&& other) { |
+ *this = std::move(other); |
+} |
+ |
+#if defined(OS_WIN) |
+ScopedPlatformHandle::ScopedPlatformHandle(HANDLE handle) |
+ : type_(Type::WINDOWS_HANDLE), windows_handle_(handle) {} |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(win::ScopedHandle handle) |
+ : type_(Type::WINDOWS_HANDLE), windows_handle_(std::move(handle)) {} |
+ |
+#elif defined(OS_POSIX) |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(int fd) |
+ : type_(Type::FILE_DESCRIPTOR), file_descriptor_(fd) {} |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(ScopedFD fd) |
+ : type_(Type::FILE_DESCRIPTOR), file_descriptor_(std::move(fd)) {} |
+ |
+#endif // defined(OS_WIN) |
+ |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(mach_port_t port) |
+ : type_(Type::MACH_PORT_SEND), mach_port_send_(port) {} |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(mac::ScopedMachSendRight port) |
+ : type_(Type::MACH_PORT_SEND), mach_port_send_(std::move(port)) {} |
+ |
+ScopedPlatformHandle::ScopedPlatformHandle(mac::ScopedMachReceiveRight port) |
+ : type_(Type::MACH_PORT_RECEIVE), mach_port_receive_(std::move(port)) {} |
+ |
+#endif // defined(OS_MACOSX) && !defined(OS_IOS) |
+ |
+ScopedPlatformHandle::~ScopedPlatformHandle() { |
+ reset(); |
+} |
+ |
+ScopedPlatformHandle& ScopedPlatformHandle::operator=( |
+ ScopedPlatformHandle&& other) { |
+ // NOTE: It's important that we invoke the appropriate destructor here if |
+ // necessary, since we may be transitioning from one handle type to another. |
+ reset(); |
+ |
+ std::swap(type_, other.type_); |
+ |
+ switch (type_) { |
+ case Type::INVALID: |
+ break; |
+#if defined(OS_WIN) |
+ case Type::WINDOWS_HANDLE: |
+ new (&windows_handle_) |
+ win::ScopedHandle(std::move(other.windows_handle_)); |
+ break; |
+#elif defined(OS_POSIX) |
+ case Type::FILE_DESCRIPTOR: |
+ new (&file_descriptor_) ScopedFD(std::move(other.file_descriptor_)); |
+ break; |
+#endif |
+ |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+ case Type::MACH_PORT_SEND: |
+ new (&mach_port_send_) |
+ mac::ScopedMachSendRight(std::move(mach_port_send_)); |
+ break; |
+ case Type::MACH_PORT_RECEIVE: |
+ new (&mach_port_receive_) |
+ mac::ScopedMachReceiveRight(std::move(mach_port_receive_)); |
+ break; |
+#endif |
+ } |
+ |
+ return *this; |
+} |
+ |
+bool ScopedPlatformHandle::is_valid() const { |
+ switch (type_) { |
+ case Type::INVALID: |
+ return false; |
+ |
+#if defined(OS_WIN) |
+ case Type::WINDOWS_HANDLE: |
+ return windows_handle_.IsValid(); |
+#elif defined(OS_POSIX) |
+ case Type::FILE_DESCRIPTOR: |
+ return file_descriptor_.is_valid(); |
+#endif |
+ |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+ case Type::MACH_PORT_SEND: |
+ return mach_port_send_.is_valid(); |
+ case Type::MACH_PORT_RECEIVE: |
+ return mach_port_receive_.is_valid(); |
+#endif |
+ } |
+ |
+ NOTREACHED(); |
+ return false; |
+} |
+ |
+void ScopedPlatformHandle::reset() { |
+ switch (type_) { |
+ case Type::INVALID: |
+ break; |
+#if defined(OS_WIN) |
+ case Type::WINDOWS_HANDLE: |
+ windows_handle_.~GenericScopedHandle(); |
+ break; |
+#elif defined(OS_POSIX) |
+ case Type::FILE_DESCRIPTOR: |
+ file_descriptor_.~ScopedGeneric(); |
+ break; |
+#endif |
+ |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+ case Type::MACH_PORT_SEND: |
+ mach_port_send_.~ScopedGeneric(); |
+ break; |
+ case Type::MACH_PORT_RECEIVE: |
+ mach_port_receive_.~ScopedGeneric(); |
+ break; |
+#endif |
+ } |
+ |
+ type_ = Type::INVALID; |
+} |
+ |
+#if defined(OS_WIN) |
+ |
+bool ScopedPlatformHandle::GetAsWindowsHandle(HANDLE* handle) const { |
+ if (type_ != Type::WINDOWS_HANDLE) |
+ return false; |
+ *handle = windows_handle_.Get(); |
+ return true; |
+} |
+ |
+bool ScopedPlatformHandle::TakeWindowsHandle(win::ScopedHandle* handle) { |
+ if (type_ != Type::WINDOWS_HANDLE) |
+ return false; |
+ *handle = std::move(windows_handle_); |
+ type_ = Type::INVALID; |
+ return true; |
+} |
+ |
+bool ScopedPlatformHandle::ReleaseAsWindowsHandle(HANDLE* handle) { |
+ if (type_ != Type::WINDOWS_HANDLE) |
+ return false; |
+ *handle = windows_handle_.Take(); |
+ type_ = Type::INVALID; |
+ return true; |
+} |
+ |
+#elif defined(OS_POSIX) |
+ |
+bool ScopedPlatformHandle::GetAsFileDescriptor(int* fd) const { |
+ if (type_ != Type::FILE_DESCRIPTOR) |
+ return false; |
+ *fd = file_descriptor_.get(); |
+ return true; |
+} |
+ |
+bool ScopedPlatformHandle::TakeFileDescriptor(ScopedFD* fd) { |
+ if (type_ != Type::FILE_DESCRIPTOR) |
+ return false; |
+ *fd = std::move(file_descriptor_); |
+ type_ = Type::INVALID; |
+ return true; |
+} |
+ |
+bool ScopedPlatformHandle::ReleaseAsFileDescriptor(int* fd) { |
+ if (type_ != Type::FILE_DESCRIPTOR) |
+ return false; |
+ *fd = file_descriptor_.release(); |
+ type_ = Type::INVALID; |
+ return true; |
+} |
+ |
+#endif // defined(OS_WIN) |
+ |
+#if defined(OS_MACOSX) && !defined(OS_IOS) |
+ |
+bool ScopedPlatformHandle::GetAsMachPort(mach_port_t* port) const { |
+ if (type_ == Type::MACH_PORT_SEND) { |
+ *port = mach_port_send_.get(); |
+ return true; |
+ } else if (type_ == Type::MACH_PORT_RECEIVE) { |
+ *port = mach_port_receive_.get(); |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+bool ScopedPlatformHandle::TakeMachPortSendRight( |
+ mac::ScopedMachSendRight* port) { |
+ if (type_ != Type::MACH_PORT_SEND) |
+ return false; |
+ *port = std::move(mach_port_send_); |
+ type_ = Type::INVALID; |
+ return true; |
+} |
+ |
+bool ScopedPlatformHandle::TakeMachPortReceiveRight( |
+ mac::ScopedMachReceiveRight* port) { |
+ if (type_ != Type::MACH_PORT_RECEIVE) |
+ return false; |
+ *port = std::move(mach_port_receive_); |
+ type_ = Type::INVALID; |
+ return true; |
+} |
+ |
+bool ScopedPlatformHandle::ReleaseAsMachPort(mach_port_t* port) { |
+ if (type_ == Type::MACH_PORT_SEND) { |
+ *port = mach_port_send_.release(); |
+ type_ = Type::INVALID; |
+ return true; |
+ } else if (type_ == Type::MACH_PORT_RECEIVE) { |
+ *port = mach_port_receive_.release(); |
+ type_ = Type::INVALID; |
+ return true; |
+ } |
+ return false; |
+} |
+ |
+#endif // defined(OS_MACOSX) && !defined(OS_IOS) |
+ |
+} // namespace base |