| @@ -1,6 +1,7 @@ | |||||
| #pragma once | #pragma once | ||||
| #include "cppcore/conversion.h" | #include "cppcore/conversion.h" | ||||
| #include "cppcore/define.h" | |||||
| #include "cppcore/defines.h" | |||||
| #include "cppcore/misc.h" | #include "cppcore/misc.h" | ||||
| #include "cppcore/platform.h" | |||||
| #include "cppcore/threading.h" | #include "cppcore/threading.h" | ||||
| @@ -4,5 +4,5 @@ | |||||
| #include "misc/flags.h" | #include "misc/flags.h" | ||||
| #include "misc/indent.h" | #include "misc/indent.h" | ||||
| #include "misc/stream.h" | #include "misc/stream.h" | ||||
| #include "misc/typehelper.h" | |||||
| #include "misc/type_helper.h" | |||||
| #include "misc/utils.h" | #include "misc/utils.h" | ||||
| @@ -57,7 +57,7 @@ namespace cppcore | |||||
| { | { | ||||
| if (_msg_cache_empty) | if (_msg_cache_empty) | ||||
| { | { | ||||
| _msg_cache = print(); | |||||
| _msg_cache = print(); | |||||
| _msg_cache_empty = false; | _msg_cache_empty = false; | ||||
| } | } | ||||
| return _msg_cache; | return _msg_cache; | ||||
| @@ -0,0 +1,4 @@ | |||||
| #pragma once | |||||
| #include "platform/fdset.h" | |||||
| #include "platform/select.h" | |||||
| @@ -0,0 +1,44 @@ | |||||
| #pragma once | |||||
| #include <sys/select.h> | |||||
| 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" | |||||
| @@ -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); } | |||||
| } | |||||
| @@ -0,0 +1,70 @@ | |||||
| #pragma once | |||||
| #include <chrono> | |||||
| #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<typename T_rep, typename T_period> | |||||
| inline uint select( | |||||
| int fd_count, | |||||
| fdset& read, | |||||
| fdset& write, | |||||
| fdset& except, | |||||
| std::chrono::duration<T_rep, T_period>& 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<typename T_rep, typename T_period> | |||||
| inline uint select( | |||||
| int fd_count, | |||||
| fdset& read, | |||||
| fdset& write, | |||||
| fdset& except, | |||||
| const std::chrono::duration<T_rep, T_period>& timeout); | |||||
| } | |||||
| #include "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<uint>(ret); | |||||
| } | |||||
| template<typename T_rep, typename T_period> | |||||
| uint select( | |||||
| int fd_count, | |||||
| fdset& read, | |||||
| fdset& write, | |||||
| fdset& except, | |||||
| std::chrono::duration<T_rep, T_period>& timeout) | |||||
| { | |||||
| using duration_type = std::chrono::duration<T_rep, T_period>; | |||||
| auto tmp = duration_cast<timespec>(timeout); | |||||
| auto ret = ::select(fd_count, &read, &write, &except, &tmp); | |||||
| if (ret < 0) | |||||
| return __impl::throw_select_error(errno); | |||||
| timeout = duration_cast<duration_type>(tmp); | |||||
| return static_cast<uint>(ret); | |||||
| } | |||||
| template<typename T_rep, typename T_period> | |||||
| uint select( | |||||
| int fd_count, | |||||
| fdset& read, | |||||
| fdset& write, | |||||
| fdset& except, | |||||
| const std::chrono::duration<T_rep, T_period>& timeout) | |||||
| { | |||||
| auto tmp = duration_cast<timeval>(timeout); | |||||
| auto ret = ::select(fd_count, &read, &write, &except, &tmp); | |||||
| if (ret < 0) | |||||
| return __impl::throw_select_error(errno); | |||||
| return static_cast<uint>(ret); | |||||
| } | |||||
| } | |||||