PageRenderTime 47ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/src/SFML/Network/SocketSelector.cpp

http://github.com/LaurentGomila/SFML
C++ | 205 lines | 113 code | 51 blank | 41 comment | 14 complexity | d59fef8b85bb5cb1b3902ccdbdfadea0 MD5 | raw file
  1. ////////////////////////////////////////////////////////////
  2. //
  3. // SFML - Simple and Fast Multimedia Library
  4. // Copyright (C) 2007-2019 Laurent Gomila (laurent@sfml-dev.org)
  5. //
  6. // This software is provided 'as-is', without any express or implied warranty.
  7. // In no event will the authors be held liable for any damages arising from the use of this software.
  8. //
  9. // Permission is granted to anyone to use this software for any purpose,
  10. // including commercial applications, and to alter it and redistribute it freely,
  11. // subject to the following restrictions:
  12. //
  13. // 1. The origin of this software must not be misrepresented;
  14. // you must not claim that you wrote the original software.
  15. // If you use this software in a product, an acknowledgment
  16. // in the product documentation would be appreciated but is not required.
  17. //
  18. // 2. Altered source versions must be plainly marked as such,
  19. // and must not be misrepresented as being the original software.
  20. //
  21. // 3. This notice may not be removed or altered from any source distribution.
  22. //
  23. ////////////////////////////////////////////////////////////
  24. ////////////////////////////////////////////////////////////
  25. // Headers
  26. ////////////////////////////////////////////////////////////
  27. #include <SFML/Network/SocketSelector.hpp>
  28. #include <SFML/Network/Socket.hpp>
  29. #include <SFML/Network/SocketImpl.hpp>
  30. #include <SFML/System/Err.hpp>
  31. #include <algorithm>
  32. #include <utility>
  33. #ifdef _MSC_VER
  34. #pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
  35. #endif
  36. namespace sf
  37. {
  38. ////////////////////////////////////////////////////////////
  39. struct SocketSelector::SocketSelectorImpl
  40. {
  41. fd_set allSockets; //!< Set containing all the sockets handles
  42. fd_set socketsReady; //!< Set containing handles of the sockets that are ready
  43. int maxSocket; //!< Maximum socket handle
  44. int socketCount; //!< Number of socket handles
  45. };
  46. ////////////////////////////////////////////////////////////
  47. SocketSelector::SocketSelector() :
  48. m_impl(new SocketSelectorImpl)
  49. {
  50. clear();
  51. }
  52. ////////////////////////////////////////////////////////////
  53. SocketSelector::SocketSelector(const SocketSelector& copy) :
  54. m_impl(new SocketSelectorImpl(*copy.m_impl))
  55. {
  56. }
  57. ////////////////////////////////////////////////////////////
  58. SocketSelector::~SocketSelector()
  59. {
  60. delete m_impl;
  61. }
  62. ////////////////////////////////////////////////////////////
  63. void SocketSelector::add(Socket& socket)
  64. {
  65. SocketHandle handle = socket.getHandle();
  66. if (handle != priv::SocketImpl::invalidSocket())
  67. {
  68. #if defined(SFML_SYSTEM_WINDOWS)
  69. if (m_impl->socketCount >= FD_SETSIZE)
  70. {
  71. err() << "The socket can't be added to the selector because the "
  72. << "selector is full. This is a limitation of your operating "
  73. << "system's FD_SETSIZE setting.";
  74. return;
  75. }
  76. if (FD_ISSET(handle, &m_impl->allSockets))
  77. return;
  78. m_impl->socketCount++;
  79. #else
  80. if (handle >= FD_SETSIZE)
  81. {
  82. err() << "The socket can't be added to the selector because its "
  83. << "ID is too high. This is a limitation of your operating "
  84. << "system's FD_SETSIZE setting.";
  85. return;
  86. }
  87. // SocketHandle is an int in POSIX
  88. m_impl->maxSocket = std::max(m_impl->maxSocket, handle);
  89. #endif
  90. FD_SET(handle, &m_impl->allSockets);
  91. }
  92. }
  93. ////////////////////////////////////////////////////////////
  94. void SocketSelector::remove(Socket& socket)
  95. {
  96. SocketHandle handle = socket.getHandle();
  97. if (handle != priv::SocketImpl::invalidSocket())
  98. {
  99. #if defined(SFML_SYSTEM_WINDOWS)
  100. if (!FD_ISSET(handle, &m_impl->allSockets))
  101. return;
  102. m_impl->socketCount--;
  103. #else
  104. if (handle >= FD_SETSIZE)
  105. return;
  106. #endif
  107. FD_CLR(handle, &m_impl->allSockets);
  108. FD_CLR(handle, &m_impl->socketsReady);
  109. }
  110. }
  111. ////////////////////////////////////////////////////////////
  112. void SocketSelector::clear()
  113. {
  114. FD_ZERO(&m_impl->allSockets);
  115. FD_ZERO(&m_impl->socketsReady);
  116. m_impl->maxSocket = 0;
  117. m_impl->socketCount = 0;
  118. }
  119. ////////////////////////////////////////////////////////////
  120. bool SocketSelector::wait(Time timeout)
  121. {
  122. // Setup the timeout
  123. timeval time;
  124. time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
  125. time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
  126. // Initialize the set that will contain the sockets that are ready
  127. m_impl->socketsReady = m_impl->allSockets;
  128. // Wait until one of the sockets is ready for reading, or timeout is reached
  129. // The first parameter is ignored on Windows
  130. int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
  131. return count > 0;
  132. }
  133. ////////////////////////////////////////////////////////////
  134. bool SocketSelector::isReady(Socket& socket) const
  135. {
  136. SocketHandle handle = socket.getHandle();
  137. if (handle != priv::SocketImpl::invalidSocket())
  138. {
  139. #if !defined(SFML_SYSTEM_WINDOWS)
  140. if (handle >= FD_SETSIZE)
  141. return false;
  142. #endif
  143. return FD_ISSET(handle, &m_impl->socketsReady) != 0;
  144. }
  145. return false;
  146. }
  147. ////////////////////////////////////////////////////////////
  148. SocketSelector& SocketSelector::operator =(const SocketSelector& right)
  149. {
  150. SocketSelector temp(right);
  151. std::swap(m_impl, temp.m_impl);
  152. return *this;
  153. }
  154. } // namespace sf