112 lines
2.7 KiB
C++
112 lines
2.7 KiB
C++
/*
|
|
* Copyright (C) 2015, 2021 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 UNIQUEFD_H_
|
|
#define UNIQUEFD_H_
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <memory>
|
|
|
|
namespace android {
|
|
|
|
/*
|
|
* Using UniqueFd:
|
|
* 1. Create UniqueFd object:
|
|
* auto fd_obj = UniqueFd(open("SomeFile", xxx));
|
|
*
|
|
* 2. Check whether the fd_obj is empty:
|
|
* if (!fd_obj) { return -errno; }
|
|
*
|
|
* 3. Accessing the file descriptor:
|
|
* int ret = read(fd_obj.Get(), buf, buf_size);
|
|
*
|
|
* 4. Closing the file:
|
|
* FD will be closed once execution leaves fd_obj scope (on any return,
|
|
* exception, destruction of class/struct where object is member, etc.).
|
|
* User can also force closing the fd_obj by calling:
|
|
* fd_obj = UniqueFd();
|
|
* // fd is closed and fd_obj is empty now.
|
|
*
|
|
* 5. File descriptor may be transferred to the code, which will close it after
|
|
* using. This can be done in 2 ways:
|
|
* a. Duplicate the fd, in this case both fds should be closed separately:
|
|
* int out_fd = dup(fd_obj.Get();
|
|
* ...
|
|
* close(out_fd);
|
|
* b. Transfer ownership, use this method if you do not need the fd anymore.
|
|
* int out_fd = fd_obj.Release();
|
|
* // fd_obj is empty now.
|
|
* ...
|
|
* close(out_fd);
|
|
*
|
|
* 6. Transferring fd into another UniqueFD object:
|
|
* UniqueFd fd_obj_2 = std::move(fd_obj);
|
|
* // fd_obj empty now
|
|
*/
|
|
|
|
constexpr int kEmptyFd = -1;
|
|
|
|
class UniqueFd {
|
|
public:
|
|
UniqueFd() = default;
|
|
explicit UniqueFd(int fd) : fd_(fd){};
|
|
|
|
auto Release [[nodiscard]] () -> int {
|
|
return std::exchange(fd_, kEmptyFd);
|
|
}
|
|
|
|
auto Get [[nodiscard]] () const -> int {
|
|
return fd_;
|
|
}
|
|
|
|
explicit operator bool() const {
|
|
return fd_ != kEmptyFd;
|
|
}
|
|
|
|
~UniqueFd() {
|
|
Set(kEmptyFd);
|
|
}
|
|
|
|
/* Allow move semantics */
|
|
UniqueFd(UniqueFd &&rhs) noexcept {
|
|
Set(rhs.Release());
|
|
}
|
|
|
|
auto operator=(UniqueFd &&rhs) noexcept -> UniqueFd & {
|
|
Set(rhs.Release());
|
|
return *this;
|
|
}
|
|
|
|
/* Disable copy semantics */
|
|
UniqueFd(const UniqueFd &) = delete;
|
|
auto operator=(const UniqueFd &) = delete;
|
|
|
|
private:
|
|
void Set(int new_fd) {
|
|
if (fd_ != kEmptyFd) {
|
|
close(fd_);
|
|
}
|
|
fd_ = new_fd;
|
|
}
|
|
|
|
int fd_ = kEmptyFd;
|
|
};
|
|
|
|
} // namespace android
|
|
|
|
#endif
|