| @@ -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" | |||
| @@ -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" | |||
| @@ -57,7 +57,7 @@ namespace cppcore | |||
| { | |||
| if (_msg_cache_empty) | |||
| { | |||
| _msg_cache = print(); | |||
| _msg_cache = print(); | |||
| _msg_cache_empty = false; | |||
| } | |||
| 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); | |||
| } | |||
| } | |||