diff --git a/include/cppcore.h b/include/cppcore.h index 12bafec..a4343e5 100644 --- a/include/cppcore.h +++ b/include/cppcore.h @@ -1,6 +1,7 @@ #pragma once #include "cppcore/conversion.h" -#include "cppcore/define.h" +#include "cppcore/defines.h" #include "cppcore/misc.h" +#include "cppcore/platform.h" #include "cppcore/threading.h" diff --git a/include/cppcore/misc.h b/include/cppcore/misc.h index d872b42..27c62de 100644 --- a/include/cppcore/misc.h +++ b/include/cppcore/misc.h @@ -4,5 +4,5 @@ #include "misc/flags.h" #include "misc/indent.h" #include "misc/stream.h" -#include "misc/typehelper.h" +#include "misc/type_helper.h" #include "misc/utils.h" diff --git a/include/cppcore/misc/exception.inl b/include/cppcore/misc/exception.inl index 84607a9..75cccca 100644 --- a/include/cppcore/misc/exception.inl +++ b/include/cppcore/misc/exception.inl @@ -57,7 +57,7 @@ namespace cppcore { if (_msg_cache_empty) { - _msg_cache = print(); + _msg_cache = print(); _msg_cache_empty = false; } return _msg_cache; diff --git a/include/cppcore/platform.h b/include/cppcore/platform.h new file mode 100644 index 0000000..026c331 --- /dev/null +++ b/include/cppcore/platform.h @@ -0,0 +1,4 @@ +#pragma once + +#include "platform/fdset.h" +#include "platform/select.h" diff --git a/include/cppcore/platform/fdset.h b/include/cppcore/platform/fdset.h new file mode 100644 index 0000000..1e82ed7 --- /dev/null +++ b/include/cppcore/platform/fdset.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +namespace cppcore +{ + + struct fdset + : public fd_set + { + public: + /** + * @brief Check if the passed file descriptor is set in this set. + * + * @param[in] fd File descriptor to check for. + * + * @retval true If the passed file descriptor is set. + * @retval false If the passed file descriptor is not set. + */ + inline bool is_set(int fd) const; + + /** + * @brief Set the passed file descriptor in the set. + * + * @param[in] fd File descriptor to set. + */ + inline void set(int fd); + + /** + * @brief Clear the passed file descriptor in the set. + * + * @param[in] fd File descriptor to clear. + */ + inline void clear(int fd); + + /** + * @brief Clear the complete file descriptor set. + */ + inline void reset(); + }; + +} + +#include "fdset.inl" diff --git a/include/cppcore/platform/fdset.inl b/include/cppcore/platform/fdset.inl new file mode 100644 index 0000000..909094e --- /dev/null +++ b/include/cppcore/platform/fdset.inl @@ -0,0 +1,26 @@ +#pragma once + +#include "fdset.h" + +namespace cppcore +{ + + /* fdset */ + + static_assert( + sizeof(fd_set) == sizeof(fdset), + "Size of fd set implementation does not match."); + + bool fdset::is_set(int fd) const + { return FD_ISSET(fd, this); } + + void fdset::set(int fd) + { FD_SET(fd, this); } + + void fdset::clear(int fd) + { FD_CLR(fd, this); } + + void fdset::reset() + { FD_ZERO(this); } + +} diff --git a/include/cppcore/platform/select.h b/include/cppcore/platform/select.h new file mode 100644 index 0000000..39f5719 --- /dev/null +++ b/include/cppcore/platform/select.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +#include "fdset.h" + +namespace cppcore +{ + + /** + * @brief Wait for the file descriptors passed in the file descriptor sets until + * any file descriptor is read. + * + * @param[in] fd_count Number of file descriptor stored in the file descriptor sets. + * @param[in] read File descriptor set to wait for read operations. + * @param[in] write File descriptor set to wait for write operations. + * @param[in] except File descriptor set to wait for a exceptional state. + * + * @return Number of active file descriptors. + */ + inline uint select( + int fd_count, + fdset& read, + fdset& write, + fdset& except); + + /** + * @brief Wait for the file descriptors passed in the file descriptor sets until + * any file descriptor is read, or the timeout has occured. + * + * @param[in] fd_count Number of file descriptor stored in the file descriptor sets. + * @param[in] read File descriptor set to wait for read operations. + * @param[in] write File descriptor set to wait for write operations. + * @param[in] except File descriptor set to wait for a exceptional state. + * @param[in] timeout Relative timeout to wait for te file descriptors. + * May be updated to the time left after select returned. + * + * @return Number of active file descriptors. + */ + template + inline uint select( + int fd_count, + fdset& read, + fdset& write, + fdset& except, + std::chrono::duration& timeout); + + /** + * @brief Wait for the file descriptors passed in the file descriptor sets until + * any file descriptor is read, or the timeout has occured. + * + * @param[in] fd_count Number of file descriptor stored in the file descriptor sets. + * @param[in] read File descriptor set to wait for read operations. + * @param[in] write File descriptor set to wait for write operations. + * @param[in] except File descriptor set to wait for a exceptional state. + * @param[in] timeout Relative timeout to wait for te file descriptors. + * + * @return Number of active file descriptors. + */ + template + inline uint select( + int fd_count, + fdset& read, + fdset& write, + fdset& except, + const std::chrono::duration& timeout); + +} + +#include "select.inl" diff --git a/include/cppcore/platform/select.inl b/include/cppcore/platform/select.inl new file mode 100644 index 0000000..ee351e6 --- /dev/null +++ b/include/cppcore/platform/select.inl @@ -0,0 +1,65 @@ +#pragma once + +#include "select.h" +#include "../misc/exception.h" +#include "../conversion/time.h" + +namespace cppcore +{ + + namespace __impl + { + inline uint throw_select_error(int err) + { + if (err == EINTR) + return 0; + throw error_exception("Error while waiting for select operation", err); + } + } + + uint select( + int fd_count, + fdset& read, + fdset& write, + fdset& except) + { + auto ret = ::select(fd_count, &read, &write, &except, nullptr); + if (ret < 0) + return __impl::throw_select_error(errno); + return static_cast(ret); + } + + template + uint select( + int fd_count, + fdset& read, + fdset& write, + fdset& except, + std::chrono::duration& timeout) + { + using duration_type = std::chrono::duration; + + auto tmp = duration_cast(timeout); + auto ret = ::select(fd_count, &read, &write, &except, &tmp); + if (ret < 0) + return __impl::throw_select_error(errno); + timeout = duration_cast(tmp); + return static_cast(ret); + } + + template + uint select( + int fd_count, + fdset& read, + fdset& write, + fdset& except, + const std::chrono::duration& timeout) + { + auto tmp = duration_cast(timeout); + auto ret = ::select(fd_count, &read, &write, &except, &tmp); + if (ret < 0) + return __impl::throw_select_error(errno); + return static_cast(ret); + } + +}