mirror of
https://git.freebsd.org/src.git
synced 2026-01-16 23:02:24 +00:00
libutil++: Add freebsd::fd_up class to manage file descriptors
This class aims to provide a std::unique_ptr<>-like interface in that it assumes exclusive ownership of a file descriptor. The descriptor is closed when the object is destroyed. Sponsored by: Chelsio Communications Pull Request: https://github.com/freebsd/freebsd-src/pull/1794
This commit is contained in:
parent
1ee9931d6e
commit
937e92b5f7
3 changed files with 150 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ SRCS= stringf.cc
|
|||
|
||||
MAN+= freebsd::FILE_up.3 \
|
||||
freebsd::addrinfo_up.3 \
|
||||
freebsd::fd_up.3 \
|
||||
freebsd::malloc_up.3 \
|
||||
freebsd::stringf.3
|
||||
|
||||
|
|
|
|||
78
lib/libutil++/freebsd::fd_up.3
Normal file
78
lib/libutil++/freebsd::fd_up.3
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
.\"
|
||||
.\" SPDX-License-Identifier: BSD-2-Clause
|
||||
.\"
|
||||
.\" Copyright (c) 2025 Chelsio Communications, Inc.
|
||||
.\" Written by: John Baldwin <jhb@FreeBSD.org>
|
||||
.\"
|
||||
.Dd July 31, 2025
|
||||
.Dt FREEBSD::STRINGF 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm freebsd::fd_up
|
||||
.Nd own a file descriptor
|
||||
.Sh LIBRARY
|
||||
.Lb libutil++
|
||||
.Sh SYNOPSIS
|
||||
.In libutil++.hh
|
||||
.Pp
|
||||
.Vt class freebsd::fd_up
|
||||
{
|
||||
.Bd -ragged -offset indent
|
||||
.Fn fd_up
|
||||
.Fn fd_up "int fd"
|
||||
.Fn fd_up "fd_up &&other"
|
||||
.Fn ~fd_up
|
||||
.Ft int
|
||||
.Fn get
|
||||
.Ft int
|
||||
.Fn release
|
||||
.Ft void
|
||||
.Fn reset "int newfd = -1"
|
||||
.Ft "fd_up &"
|
||||
.Fn operator= "fd_up &&other"
|
||||
.Ft "fd_up &"
|
||||
.Fn operator= "int fd"
|
||||
.Fn "explicit operator bool"
|
||||
.Fn "operator int"
|
||||
.Ed
|
||||
};
|
||||
.Sh DESCRIPTION
|
||||
Each instance of this class owns a file descriptor.
|
||||
This class is patterned on std::unique_ptr,
|
||||
but instead of owning a pointer to an object,
|
||||
this class owns a file descriptor.
|
||||
The currently-owned file descriptor is disposed by invoking
|
||||
.Xr close 2
|
||||
when an instance of this class is destroyed.
|
||||
The currently-owned file descriptor is also disposed if it is replaced by the
|
||||
.Fn reset
|
||||
method or assignment operators.
|
||||
.Pp
|
||||
The
|
||||
.Fn get
|
||||
method returns the current file descriptor value while retaining ownership.
|
||||
.Pp
|
||||
The
|
||||
.Fn release
|
||||
method relinquishes ownership of the current file descriptor and returns the
|
||||
value of the previously-owned file descriptor.
|
||||
.Pp
|
||||
The explicit
|
||||
.Vt bool
|
||||
conversion operator permits testing the validity of an object.
|
||||
The operator returns true if the instance owns a valid file descriptor.
|
||||
.Pp
|
||||
The implicit
|
||||
.Vt int
|
||||
conversion operator permits passing an instance of this class directly as
|
||||
an argument to existing functions which expect a file descriptor.
|
||||
.Sh EXAMPLES
|
||||
.Bd -literal -offset indent
|
||||
freebsd::fd_up fd(open("/dev/null", O_RDWR));
|
||||
if (!fd)
|
||||
err(1, "open");
|
||||
write(fd, "test", 4);
|
||||
// `fd' is implicitly closed on destruction
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr close 2
|
||||
|
|
@ -9,6 +9,7 @@
|
|||
#define __LIBUTILPP_HH__
|
||||
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
|
@ -43,6 +44,76 @@ namespace freebsd {
|
|||
|
||||
using addrinfo_up = std::unique_ptr<addrinfo, freeaddrinfo_deleter>;
|
||||
|
||||
/*
|
||||
* This class is intended to function similar to unique_ptr<>,
|
||||
* but it contains a file descriptor rather than a pointer to
|
||||
* an object. On destruction the descriptor is closed via
|
||||
* close(2).
|
||||
*
|
||||
* Similar to unique_ptr<>, release() returns ownership of the
|
||||
* file descriptor to the caller. reset() closes the current
|
||||
* file descriptor and takes ownership of a new one. A move
|
||||
* constructor permits ownership to be transferred via
|
||||
* std::move(). An integer file descriptor can be assigned
|
||||
* directly which is equivalent to calling reset().
|
||||
*
|
||||
* An explicit bool conversion operator permits testing this
|
||||
* class in logical expressions. It returns true if it
|
||||
* contains a valid descriptor.
|
||||
*
|
||||
* An implicit int conversion operator returns the underlying
|
||||
* file descriptor allowing objects of this type to be passed
|
||||
* directly to APIs such as connect(), listen(), etc.
|
||||
*/
|
||||
class fd_up {
|
||||
public:
|
||||
fd_up() : fd(-1) {}
|
||||
fd_up(int fd) : fd(fd) {}
|
||||
fd_up(fd_up &&other) : fd(other.release()) {}
|
||||
fd_up(fd_up const &) = delete;
|
||||
|
||||
~fd_up() { reset(); }
|
||||
|
||||
int get() const { return (fd); }
|
||||
|
||||
int release()
|
||||
{
|
||||
int oldfd = fd;
|
||||
|
||||
fd = -1;
|
||||
return (oldfd);
|
||||
}
|
||||
|
||||
void reset(int newfd = -1)
|
||||
{
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
fd = newfd;
|
||||
}
|
||||
|
||||
fd_up &operator=(fd_up &&other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
|
||||
reset(other.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
fd_up &operator=(fd_up const &) = delete;
|
||||
|
||||
fd_up &operator=(int newfd)
|
||||
{
|
||||
reset(newfd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return fd >= 0; }
|
||||
operator int() const { return fd; }
|
||||
private:
|
||||
int fd;
|
||||
};
|
||||
|
||||
/*
|
||||
* malloc_up<T> is a std::unique_ptr<> which uses free() to
|
||||
* destroy the wrapped pointer. This can be used to wrap
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue