diff --git a/Makefile.am b/Makefile.am index f30e3fafa..bd7852830 100644 --- a/Makefile.am +++ b/Makefile.am @@ -493,6 +493,7 @@ libsystem_a_SOURCES = \ src/system/Error.hxx \ src/system/FatalError.cxx src/system/FatalError.hxx \ src/system/FileDescriptor.cxx src/system/FileDescriptor.hxx \ + src/system/UniqueFileDescriptor.hxx \ src/system/fd_util.c src/system/fd_util.h \ src/system/EventPipe.cxx src/system/EventPipe.hxx \ src/system/EventFD.cxx src/system/EventFD.hxx \ diff --git a/src/system/UniqueFileDescriptor.hxx b/src/system/UniqueFileDescriptor.hxx new file mode 100644 index 000000000..d1827d3bb --- /dev/null +++ b/src/system/UniqueFileDescriptor.hxx @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2012-2017 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef UNIQUE_FILE_DESCRIPTOR_HXX +#define UNIQUE_FILE_DESCRIPTOR_HXX + +#include "FileDescriptor.hxx" + +#include + +/** + * An OO wrapper for a UNIX file descriptor. + */ +class UniqueFileDescriptor : protected FileDescriptor { +public: + UniqueFileDescriptor():FileDescriptor(FileDescriptor::Undefined()) {} + +protected: + explicit UniqueFileDescriptor(int _fd):FileDescriptor(_fd) { + assert(IsDefined()); + } + +public: + explicit UniqueFileDescriptor(FileDescriptor _fd) + :FileDescriptor(_fd) {} + + UniqueFileDescriptor(UniqueFileDescriptor &&other) + :FileDescriptor(other.Steal()) {} + + ~UniqueFileDescriptor() { + Close(); + } + + UniqueFileDescriptor &operator=(UniqueFileDescriptor &&other) { + std::swap(fd, other.fd); + return *this; + } + + /** + * Convert this object to its #FileDescriptor base type. + */ + const FileDescriptor &ToFileDescriptor() const { + return *this; + } + + using FileDescriptor::IsDefined; +#ifndef _WIN32 + using FileDescriptor::IsValid; +#endif + using FileDescriptor::Get; + using FileDescriptor::Steal; + +protected: + void Set(int _fd) { + assert(!IsDefined()); + assert(_fd >= 0); + + FileDescriptor::Set(_fd); + } + +public: + using FileDescriptor::Open; + using FileDescriptor::OpenReadOnly; + +#ifndef _WIN32 + using FileDescriptor::OpenNonBlocking; + + static bool CreatePipe(UniqueFileDescriptor &r, UniqueFileDescriptor &w) { + return FileDescriptor::CreatePipe(r, w); + } + + using FileDescriptor::SetNonBlocking; + using FileDescriptor::SetBlocking; + using FileDescriptor::EnableCloseOnExec; + using FileDescriptor::DisableCloseOnExec; + using FileDescriptor::Duplicate; + + static bool CreatePipe(FileDescriptor &r, FileDescriptor &w); +#endif + +#ifdef USE_EVENTFD + using FileDescriptor::CreateEventFD; +#endif + +#ifdef USE_SIGNALFD + using FileDescriptor::CreateSignalFD; +#endif + +#ifdef HAVE_INOTIFY_INIT + using FileDescriptor::CreateInotify; +#endif + +#ifdef HAVE_EVENTFD + using FileDescriptor::CreateEventFD; +#endif + +#ifdef HAVE_SIGNALFD + using FileDescriptor::CreateSignalFD; +#endif + +#ifdef HAVE_INOTIFY + using FileDescriptor::CreateInotify; +#endif + + bool Close() { + return IsDefined() && FileDescriptor::Close(); + } + + using FileDescriptor::Rewind; + using FileDescriptor::Seek; + using FileDescriptor::Skip; + using FileDescriptor::Tell; + using FileDescriptor::GetSize; + using FileDescriptor::Read; + using FileDescriptor::Write; + +#ifndef _WIN32 + using FileDescriptor::Poll; + using FileDescriptor::WaitReadable; + using FileDescriptor::WaitWritable; + using FileDescriptor::IsReadyForWriting; +#endif +}; + +#endif