netpoll.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. //
  2. // Copyright (c) 2017-2026, Manticore Software LTD (https://manticoresearch.com)
  3. // Copyright (c) 2001-2016, Andrew Aksyonoff
  4. // Copyright (c) 2008-2016, Sphinx Technologies Inc
  5. // All rights reserved
  6. //
  7. // This program is free software; you can redistribute it and/or modify
  8. // it under the terms of the GNU General Public License. You should have
  9. // received a copy of the GPL license along with this program; if you
  10. // did not, you can find it at http://www.gnu.org/
  11. //
  12. #pragma once
  13. #include "config.h"
  14. #include "searchdaemon.h"
  15. #include "std/ints.h"
  16. #include "std/refcounted_mt.h"
  17. #include "std/threadrole.h"
  18. #include "timeout_queue.h"
  19. #include <boost/intrusive/slist.hpp>
  20. #include <functional>
  21. #include <memory>
  22. //////////////////////////////////////////////////////////////////////////
  23. // Universal work with select/poll/epoll/kqueue
  24. //////////////////////////////////////////////////////////////////////////
  25. // wrapper around epoll/kqueue/poll
  26. extern ThreadRole NetPoollingThread;
  27. using netlist_hook_t = boost::intrusive::slist_member_hook<>;
  28. struct NetPollEvent_t : public EnqueuedTimeout_t, public ISphRefcountedMT
  29. {
  30. netlist_hook_t m_tBackHook; // opaque hook for intrusive list linkage
  31. int m_iBackIdx = -1; // or opaque index to internals of poller
  32. int m_iSock = -1;
  33. BYTE m_uIOChange = SET_NONE;
  34. BYTE m_uIOActive = SET_NONE;
  35. BYTE m_uGotEvents = IS_NONE;
  36. explicit NetPollEvent_t ( int iSock )
  37. : m_iSock ( iSock ) {}
  38. enum SetMask_e : BYTE
  39. {
  40. SET_NONE = 0,
  41. SET_READ = 1 << 0, // 1 - poll read events
  42. SET_WRITE = 1 << 1, // 2 - poll write events
  43. SET_RW = SET_READ | SET_WRITE, // 3 - poll read and write events
  44. SET_ONESHOT = 1 << 2, // 4 - will be deactivated/removed once shot
  45. SET_ON_EDGE = 1 << 3, // 8 - edge-triggered (if non set - level-triggered)
  46. SET_EDGEONESHOT = SET_ONESHOT | SET_ON_EDGE,
  47. SET_CLOSED = 1 << 4, // 16 - socket is closed, remove the event from timeout/task queues
  48. };
  49. enum GotMask_e : BYTE {
  50. IS_NONE = 0,
  51. IS_READ = 1 << 0, // 1 - ready for reading
  52. IS_WRITE = 1 << 1, // 2 - ready for writing
  53. IS_RW = SET_READ | SET_WRITE, // 3 - ready for reading and writing
  54. IS_HUP = 1 << 2, // 4 - has HUP
  55. IS_ERR = 1 << 3, // 8 - has ERR
  56. IS_ERRHUP = IS_ERR | IS_HUP, // 12 - has HUP & ERR
  57. IS_TIMEOUT = 1 << 4, // 16 - timed out
  58. };
  59. inline bool IsLinked() const
  60. {
  61. return m_tBackHook.is_linked() || m_iBackIdx!=-1;
  62. }
  63. inline bool CheckSocketError () const
  64. {
  65. bool bReadError = ( ( m_uGotEvents & IS_READ ) && ( m_uGotEvents & IS_ERRHUP ) );
  66. bool bWriteError = ( ( m_uGotEvents & IS_WRITE ) && ( m_uGotEvents & IS_ERR ) );
  67. if ( bReadError && ( ( m_uGotEvents & IS_ERRHUP ) == IS_HUP ) )
  68. sphSockSetErrno ( ECONNRESET );
  69. return bReadError || bWriteError;
  70. }
  71. };
  72. using NetPoolEventRefPtr_c = CSphRefcountedPtr<NetPollEvent_t>;
  73. constexpr static int64_t WAIT_UNTIL_TIMEOUT = -1LL;
  74. class NetPooller_c;
  75. class NetPollReadyIterator_c
  76. {
  77. int m_iIterEv = -1;
  78. NetPooller_c * m_pOwner = nullptr;
  79. public:
  80. explicit NetPollReadyIterator_c ( NetPooller_c* pOwner ) : m_pOwner ( pOwner )
  81. {
  82. if ( pOwner )
  83. operator++();
  84. }
  85. NetPollEvent_t & operator* () REQUIRES ( NetPoollingThread );
  86. NetPollReadyIterator_c & operator++ () REQUIRES ( NetPoollingThread );
  87. bool operator!= ( const NetPollReadyIterator_c & rhs ) const REQUIRES ( NetPoollingThread );
  88. };
  89. class NetPooller_c : public ISphNoncopyable
  90. {
  91. class Impl_c;
  92. std::unique_ptr<Impl_c> m_pImpl;
  93. friend class NetPollReadyIterator_c;
  94. public:
  95. explicit NetPooller_c ( int iSizeHint, int iMaxReady=0 );
  96. ~NetPooller_c();
  97. void SetupEvent ( NetPollEvent_t * pEvent ) REQUIRES ( NetPoollingThread );
  98. void Wait ( int64_t iUS ) REQUIRES ( NetPoollingThread );
  99. int GetNumOfReady () const;
  100. void ProcessAll ( std::function<void (NetPollEvent_t*)>&& fnAction ) REQUIRES ( NetPoollingThread );
  101. void RemoveTimeout ( NetPollEvent_t * pEvent ) REQUIRES ( NetPoollingThread );
  102. void RemoveEvent ( NetPollEvent_t * pEvent ) REQUIRES ( NetPoollingThread );
  103. int64_t TickGranularity() const;
  104. NetPollReadyIterator_c begin () { return NetPollReadyIterator_c ( this ); }
  105. static NetPollReadyIterator_c end () { return NetPollReadyIterator_c ( nullptr ); }
  106. };
  107. // determine which branch will be used
  108. // defs placed here for easy switch between/debug
  109. #define NETPOLL_EPOLL 1
  110. #define NETPOLL_KQUEUE 2
  111. #define NETPOLL_POLL 3
  112. #if HAVE_EPOLL
  113. #define POLLING_EPOLL 1
  114. #define NETPOLL_TYPE NETPOLL_EPOLL
  115. #elif HAVE_KQUEUE
  116. #define POLLING_KQUEUE 1
  117. #define NETPOLL_TYPE NETPOLL_KQUEUE
  118. #elif HAVE_POLL
  119. #define POLLING_POLL 1
  120. #define NETPOLL_TYPE NETPOLL_POLL
  121. #endif
  122. // #define NETPOLL_TYPE NETPOLL_POLL