105 lines
2.2 KiB
C++
105 lines
2.2 KiB
C++
#ifndef TILE_BASE_HANDLE_H
|
|
#define TILE_BASE_HANDLE_H
|
|
|
|
#pragma once
|
|
|
|
#include "tile/base/logging.h"
|
|
|
|
#include <unistd.h>
|
|
|
|
namespace tile {
|
|
namespace detail {
|
|
struct HandleDeleter {
|
|
void operator()(int fd) const noexcept
|
|
{
|
|
if (fd == 0 || fd == -1) { return; }
|
|
TILE_PCHECK(::close(fd) == 0);
|
|
}
|
|
};
|
|
|
|
namespace handle {
|
|
template<typename T, typename... Args>
|
|
constexpr T
|
|
GetFirstArg(T first, Args...)
|
|
{
|
|
return first;
|
|
}
|
|
|
|
template<typename T>
|
|
constexpr bool
|
|
NotEqualToAnd(T val, T first)
|
|
{
|
|
return val != first;
|
|
}
|
|
|
|
template<typename T, typename... Args>
|
|
constexpr bool
|
|
NotEqualToAnd(T val, T first, Args... args)
|
|
{
|
|
return val != first && NotEqualToAnd(val, std::forward<Args>(args)...);
|
|
}
|
|
|
|
}// namespace handle
|
|
|
|
template<typename T, typename Deleter, T... kInvalidHandles>
|
|
class GenericHandle : private Deleter {
|
|
static constexpr T kDefaultInvalid = ::tile::detail::handle::GetFirstArg(kInvalidHandles...);
|
|
|
|
public:
|
|
GenericHandle() = default;
|
|
|
|
constexpr explicit GenericHandle(T handle) noexcept : handle_(handle) {}
|
|
|
|
~GenericHandle() { Reset(); }
|
|
|
|
GenericHandle(GenericHandle &&h) noexcept
|
|
{
|
|
handle_ = h.handle_;
|
|
h.handle_ = kDefaultInvalid;
|
|
}
|
|
|
|
GenericHandle &operator=(GenericHandle &&h) noexcept
|
|
{
|
|
if (&h == this) { return *this; }
|
|
|
|
handle_ = h.handle_;
|
|
h.handle_ = kDefaultInvalid;
|
|
return *this;
|
|
}
|
|
|
|
GenericHandle(const GenericHandle &) = delete;
|
|
GenericHandle &operator=(const GenericHandle &) = delete;
|
|
|
|
T *Retrieve() noexcept { return &handle_; }
|
|
|
|
constexpr T Get() const noexcept { return handle_; }
|
|
|
|
constexpr explicit operator bool() const noexcept
|
|
{
|
|
return ::tile::detail::handle::NotEqualToAnd(handle_, kInvalidHandles...);
|
|
}
|
|
|
|
TILE_NODISCARD T Leak() noexcept
|
|
{
|
|
int rc = handle_;
|
|
handle_ = kDefaultInvalid;
|
|
return rc;
|
|
}
|
|
|
|
void Reset(T new_value = kDefaultInvalid) noexcept
|
|
{
|
|
if (operator bool()) { Deleter::operator()(handle_); }
|
|
handle_ = new_value;
|
|
}
|
|
|
|
private:
|
|
T handle_ = kDefaultInvalid;
|
|
};
|
|
|
|
}// namespace detail
|
|
|
|
using Handle = detail::GenericHandle<int, detail::HandleDeleter, -1, 0>;
|
|
}// namespace tile
|
|
|
|
#endif// TILE_BASE_HANDLE_H
|