Sane C++ Libraries
C++ Platform Abstraction Libraries
Loading...
Searching...
No Matches
SC::UniqueHandle< Definition > Struct Template Reference

Move only handle that has a special tag value flagging its invalid state. More...

#include <UniqueHandle.h>

Public Types

using Handle = typename Definition::Handle
 

Public Member Functions

 UniqueHandle (const UniqueHandle &v)=delete
 
UniqueHandleoperator= (const UniqueHandle &other)=delete
 
 UniqueHandle (UniqueHandle &&v)
 
 UniqueHandle (const Handle &externalHandle)
 
Result assign (UniqueHandle &&other)
 Move assigns another UniqueHandle to this object, eventually closing existing handle.
 
Result assign (const Handle &externalHandle)
 Copy assigns another UniqueHandle to this object, eventually closing existing handle.
 
UniqueHandleoperator= (UniqueHandle &&other)
 
bool isValid () const
 Check if current handle is valid.
 
void detach ()
 Detaches (sets to invalid) current handle, without closing it.
 
Result get (Handle &outHandle, Result invalidReturnType) const
 Extracts the native operating system handle out.
 
Result close ()
 Closes the handle by calling its OS specific close function.
 

Static Public Attributes

static constexpr Handle Invalid = Definition::Invalid
 

Protected Attributes

Handle handle = Invalid
 

Detailed Description

template<typename Definition>
struct SC::UniqueHandle< Definition >

Move only handle that has a special tag value flagging its invalid state.


Typically used to wrap Operating System specific handles.

Template Parameters
DefinitionA struct declaring handle type, release function and invalid handle value.

Example:

... definition in header

struct SC_FILE_EXPORT FileDescriptorDefinition
{
using Handle = int; // fd
static Result releaseHandle(Handle& handle);
static constexpr Handle Invalid = -1; // invalid fd
};

... derive from it

struct SC_FILE_EXPORT FileDescriptor : public UniqueHandle<detail::FileDescriptorDefinition>
{
using UniqueHandle::UniqueHandle;

...declaration in .cpp file

#include <errno.h> // errno
#include <fcntl.h> // fcntl
#include <sys/socket.h> // socket/connect/accept
#include <sys/stat.h> // fstat
#include <sys/un.h> // sockaddr_un
#include <unistd.h> // close
namespace
{
static SC::TimeMs fileDescriptorPosixTimespecToTimeMs(const timespec& timespecValue)
{
return SC::TimeMs{static_cast<SC::int64_t>(timespecValue.tv_sec) * 1000 +
static_cast<SC::int64_t>(timespecValue.tv_nsec / (1000 * 1000))};
}
static SC::FileDescriptorEntryType fileDescriptorPosixEntryTypeFromMode(mode_t mode)
{
if (S_ISREG(mode))
return SC::FileDescriptorEntryType::File;
if (S_ISDIR(mode))
return SC::FileDescriptorEntryType::Directory;
if (S_ISLNK(mode))
return SC::FileDescriptorEntryType::SymbolicLink;
return SC::FileDescriptorEntryType::Other;
}
static SC::Result fillFileDescriptorPosixStat(const struct stat& pathStat, SC::FileDescriptorStat& fileStat)
{
fileStat = {};
fileStat.entryType = fileDescriptorPosixEntryTypeFromMode(pathStat.st_mode);
fileStat.fileSize = static_cast<SC::size_t>(pathStat.st_size);
fileStat.hardLinkCount = static_cast<SC::size_t>(pathStat.st_nlink);
fileStat.accessedTime = fileDescriptorPosixTimespecToTimeMs(
#if __APPLE__
pathStat.st_atimespec
#else
pathStat.st_atim
#endif
);
fileStat.modifiedTime = fileDescriptorPosixTimespecToTimeMs(
#if __APPLE__
pathStat.st_mtimespec
#else
pathStat.st_mtim
#endif
);
#if __APPLE__
fileStat.creationTime = fileDescriptorPosixTimespecToTimeMs(pathStat.st_birthtimespec);
#endif
fileStat.posix.mode = static_cast<SC::uint32_t>(pathStat.st_mode);
fileStat.posix.uid = static_cast<SC::uint32_t>(pathStat.st_uid);
fileStat.posix.gid = static_cast<SC::uint32_t>(pathStat.st_gid);
fileStat.posix.inode = static_cast<SC::uint64_t>(pathStat.st_ino);
fileStat.posix.device = static_cast<SC::uint64_t>(pathStat.st_dev);
fileStat.posix.specialDevice = static_cast<SC::uint64_t>(pathStat.st_rdev);
fileStat.posix.blocks = static_cast<SC::uint64_t>(pathStat.st_blocks);
fileStat.posix.blockSize = static_cast<SC::uint64_t>(pathStat.st_blksize);
return SC::Result(true);
}
} // namespace
//-------------------------------------------------------------------------------------------------------
// FileDescriptorDefinition
//-------------------------------------------------------------------------------------------------------
SC::Result SC::detail::FileDescriptorDefinition::releaseHandle(Handle& handle)
{
if (::close(handle) != 0)
{
return Result::Error("FileDescriptorDefinition::releaseHandle - close failed");
}
return Result(true);
}

...usage

#include <fcntl.h> // for open
SC::Result SC::FileTest::snippetForUniqueHandle()
{
StringPath filePath;
SC_TRY(filePath.assign("someFile.txt"));
const int flags = O_RDWR | O_CREAT | O_TRUNC; // Open for read/write, create if not exists, truncate if exists
const int access = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; // Read/write for owner, read for group and others
FileDescriptor myDescriptor;
const int nativeFd = ::open(filePath.view().bytesIncludingTerminator(), flags, access);
// Assign the native handle to UniqueHandle (will release the existing one, if any)
SC_TRY(myDescriptor.assign(nativeFd));
// UniqueHandle can only be moved, but not copied
FileDescriptor otherDescriptor = move(myDescriptor);
// FileDescriptor otherDescriptor = myDescriptor; // <- Doesn't compile
// Explicitly close (or it will be automatically released on scope close / destructor)
SC_TRY(otherDescriptor.close());
// If detach() is called, the handle will be made invalid without releasing it
otherDescriptor.detach();
// Check handle for validity
if (otherDescriptor.isValid())
{
// ... do something
}
return Result(true);
}

Member Function Documentation

◆ assign() [1/2]

template<typename Definition >
Result SC::UniqueHandle< Definition >::assign ( const Handle & externalHandle)
inline

Copy assigns another UniqueHandle to this object, eventually closing existing handle.

Parameters
externalHandleThe handle to be copy assigned
Returns
Returns invalid result if close failed

◆ assign() [2/2]

template<typename Definition >
Result SC::UniqueHandle< Definition >::assign ( UniqueHandle< Definition > && other)
inline

Move assigns another UniqueHandle to this object, eventually closing existing handle.

Parameters
otherThe handle to be move-assigned
Returns
Returns invalid result if close failed

◆ close()

template<typename Definition >
Result SC::UniqueHandle< Definition >::close ( )
inline

Closes the handle by calling its OS specific close function.

Returns
true if the handle was closed correctly

◆ detach()

template<typename Definition >
void SC::UniqueHandle< Definition >::detach ( )
inline

Detaches (sets to invalid) current handle, without closing it.

◆ get()

template<typename Definition >
Result SC::UniqueHandle< Definition >::get ( Handle & outHandle,
Result invalidReturnType ) const
inline

Extracts the native operating system handle out.

Parameters
outHandleOutput native OS handle
invalidReturnTypethe value to be returned if this function fails
Returns
invalidReturnType if isValid() == false

◆ isValid()

template<typename Definition >
bool SC::UniqueHandle< Definition >::isValid ( ) const
inlinenodiscard

Check if current handle is valid.

Returns
true if handle is valid

The documentation for this struct was generated from the following file: