skyline/app/src/main/cpp/skyline/common/file_descriptor.h
PixelyIon 344c5f2a62 Implement RAII wrapper over file descriptors
The `FileDescriptor` class is a RAII wrapper over FDs which handles their lifetimes alongside other C++ semantics such as moving and copying. It has been used in `skyline::kernel::MemoryManager` to handle the lifetime of the ashmem FD correctly, it wasn't being destroyed earlier which can result in leaking FDs across runs.
2022-04-14 14:14:52 +05:30

70 lines
1.8 KiB
C++

// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#pragma once
#include <unistd.h>
#include "base.h"
namespace skyline {
/**
* @brief A RAII wrapper around Linux file descriptors which automatically closes the file descriptor when it goes out of scope and duplicates them on copies
* @note This class should **always** be moved rather than copied where possible to avoid a system call for duplicating file descriptors
*/
class FileDescriptor {
private:
int fd;
public:
FileDescriptor() : fd(-1) {}
FileDescriptor(int fd) : fd(fd) {}
FileDescriptor &operator=(int newFd) {
if (fd != -1)
close(fd);
fd = newFd;
return *this;
}
FileDescriptor(const FileDescriptor &other) : fd(dup(other.fd)) {
if (fd == -1)
throw exception("Failed to duplicate file descriptor: {}", strerror(errno));
}
FileDescriptor &operator=(const FileDescriptor &other) {
if (fd != -1)
close(fd);
fd = dup(other.fd);
if (fd == -1)
throw exception("Failed to duplicate file descriptor: {}", strerror(errno));
return *this;
}
FileDescriptor(FileDescriptor &&other) : fd(other.fd) {
other.fd = -1;
}
FileDescriptor &operator=(FileDescriptor &&other) {
if (fd != -1)
close(fd);
fd = other.fd;
other.fd = -1;
return *this;
}
~FileDescriptor() {
if (fd != -1)
close(fd);
}
operator int() const {
return fd;
}
int operator*() const {
return fd;
}
};
}