| /* | |
| * Copyright (C) 2015 The Android Open Source Project | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| #ifndef ANDROID_BASE_UNIQUE_FD_H | |
| #define ANDROID_BASE_UNIQUE_FD_H | |
| #include <unistd.h> | |
| // DO NOT INCLUDE OTHER LIBBASE HEADERS! | |
| // This file gets used in libbinder, and libbinder is used everywhere. | |
| // Including other headers from libbase frequently results in inclusion of | |
| // android-base/macros.h, which causes macro collisions. | |
| // Container for a file descriptor that automatically closes the descriptor as | |
| // it goes out of scope. | |
| // | |
| // unique_fd ufd(open("/some/path", "r")); | |
| // if (ufd.get() == -1) return error; | |
| // | |
| // // Do something useful, possibly including 'return'. | |
| // | |
| // return 0; // Descriptor is closed for you. | |
| // | |
| // unique_fd is also known as ScopedFd/ScopedFD/scoped_fd; mentioned here to help | |
| // you find this class if you're searching for one of those names. | |
| namespace android { | |
| namespace base { | |
| struct DefaultCloser { | |
| static void Close(int fd) { | |
| // Even if close(2) fails with EINTR, the fd will have been closed. | |
| // Using TEMP_FAILURE_RETRY will either lead to EBADF or closing someone | |
| // else's fd. | |
| // http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html | |
| ::close(fd); | |
| } | |
| }; | |
| template <typename Closer> | |
| class unique_fd_impl final { | |
| public: | |
| unique_fd_impl() : value_(-1) {} | |
| explicit unique_fd_impl(int value) : value_(value) {} | |
| ~unique_fd_impl() { clear(); } | |
| unique_fd_impl(unique_fd_impl&& other) : value_(other.release()) {} | |
| unique_fd_impl& operator=(unique_fd_impl&& s) { | |
| reset(s.release()); | |
| return *this; | |
| } | |
| void reset(int new_value) { | |
| if (value_ != -1) { | |
| Closer::Close(value_); | |
| } | |
| value_ = new_value; | |
| } | |
| void clear() { | |
| reset(-1); | |
| } | |
| int get() const { return value_; } | |
| operator int() const { return get(); } | |
| int release() __attribute__((warn_unused_result)) { | |
| int ret = value_; | |
| value_ = -1; | |
| return ret; | |
| } | |
| private: | |
| int value_; | |
| unique_fd_impl(const unique_fd_impl&); | |
| void operator=(const unique_fd_impl&); | |
| }; | |
| using unique_fd = unique_fd_impl<DefaultCloser>; | |
| } // namespace base | |
| } // namespace android | |
| #endif // ANDROID_BASE_UNIQUE_FD_H |