64 lines
1.6 KiB
C++
64 lines
1.6 KiB
C++
|
/**
|
||
|
* \file misc/sys-wrapper.hh
|
||
|
* \brief SysWrapper declaration.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#include <functional>
|
||
|
#include <system_error>
|
||
|
#include <utility>
|
||
|
|
||
|
namespace sys
|
||
|
{
|
||
|
/**
|
||
|
* \class SysWrapper
|
||
|
* \brief Wrapping around syscalls to convert failure into exceptions.
|
||
|
*
|
||
|
* Wrapping syscalls this way helps to insure the RAII idiom.
|
||
|
*/
|
||
|
template <typename RetType, typename SysRetType, typename... Args>
|
||
|
class SysWrapper
|
||
|
{
|
||
|
public:
|
||
|
SysWrapper(SysRetType syscall(Args...))
|
||
|
: syscall_{syscall}
|
||
|
{}
|
||
|
|
||
|
/* Needs template to enable universal referencing.
|
||
|
Template deduction should be done automatically. */
|
||
|
template <typename... UniversalArgs>
|
||
|
RetType operator()(UniversalArgs&&... args)
|
||
|
{
|
||
|
SysRetType ret;
|
||
|
|
||
|
do
|
||
|
{
|
||
|
errno = 0;
|
||
|
ret = syscall_(std::forward<UniversalArgs>(args)...);
|
||
|
} while (errno == EINTR);
|
||
|
|
||
|
if (ret == SysRetType(-1) && errno != EWOULDBLOCK
|
||
|
&& errno != EAGAIN)
|
||
|
{
|
||
|
throw std::system_error(errno, std::system_category());
|
||
|
}
|
||
|
|
||
|
return RetType(ret);
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
std::function<SysRetType(Args...)> syscall_;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* \brief Helper function to build SysWrapper.
|
||
|
*/
|
||
|
template <typename RetType, typename SysRetType, typename... Args>
|
||
|
SysWrapper<RetType, SysRetType, Args...>
|
||
|
make_wrapper(SysRetType syscall(Args...))
|
||
|
{
|
||
|
return SysWrapper<RetType, SysRetType, Args...>(syscall);
|
||
|
}
|
||
|
} // namespace sys
|