Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

208 lines
6.9 KiB

  1. #ifndef CRYPTOPP_WAIT_H
  2. #define CRYPTOPP_WAIT_H
  3. #include "config.h"
  4. #ifdef SOCKETS_AVAILABLE
  5. #include "misc.h"
  6. #include "cryptlib.h"
  7. #include <vector>
  8. #ifdef USE_WINDOWS_STYLE_SOCKETS
  9. #include <winsock2.h>
  10. #else
  11. #include <sys/types.h>
  12. #endif
  13. #include "hrtimer.h"
  14. NAMESPACE_BEGIN(CryptoPP)
  15. class Tracer
  16. {
  17. public:
  18. Tracer(unsigned int level) : m_level(level) {}
  19. virtual ~Tracer() {}
  20. protected:
  21. //! Override this in your most-derived tracer to do the actual tracing.
  22. virtual void Trace(unsigned int n, std::string const& s) = 0;
  23. /*! By default, tracers will decide which trace messages to trace according to a trace level
  24. mechanism. If your most-derived tracer uses a different mechanism, override this to
  25. return false. If this method returns false, the default TraceXxxx(void) methods will all
  26. return 0 and must be overridden explicitly by your tracer for trace messages you want. */
  27. virtual bool UsingDefaults() const { return true; }
  28. protected:
  29. unsigned int m_level;
  30. void TraceIf(unsigned int n, std::string const&s)
  31. { if (n) Trace(n, s); }
  32. /*! Returns nr if, according to the default log settings mechanism (using log levels),
  33. the message should be traced. Returns 0 if the default trace level mechanism is not
  34. in use, or if it is in use but the event should not be traced. Provided as a utility
  35. method for easier and shorter coding of default TraceXxxx(void) implementations. */
  36. unsigned int Tracing(unsigned int nr, unsigned int minLevel) const
  37. { return (UsingDefaults() && m_level >= minLevel) ? nr : 0; }
  38. };
  39. // Your Tracer-derived class should inherit as virtual public from Tracer or another
  40. // Tracer-derived class, and should pass the log level in its constructor. You can use the
  41. // following methods to begin and end your Tracer definition.
  42. // This constructor macro initializes Tracer directly even if not derived directly from it;
  43. // this is intended, virtual base classes are always initialized by the most derived class.
  44. #define CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED) \
  45. public: DERIVED(unsigned int level = 0) : Tracer(level) {}
  46. #define CRYPTOPP_BEGIN_TRACER_CLASS_1(DERIVED, BASE1) \
  47. class DERIVED : virtual public BASE1 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)
  48. #define CRYPTOPP_BEGIN_TRACER_CLASS_2(DERIVED, BASE1, BASE2) \
  49. class DERIVED : virtual public BASE1, virtual public BASE2 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED)
  50. #define CRYPTOPP_END_TRACER_CLASS };
  51. // In your Tracer-derived class, you should define a globally unique event number for each
  52. // new event defined. This can be done using the following macros.
  53. #define CRYPTOPP_BEGIN_TRACER_EVENTS(UNIQUENR) enum { EVENTBASE = UNIQUENR,
  54. #define CRYPTOPP_TRACER_EVENT(EVENTNAME) EventNr_##EVENTNAME,
  55. #define CRYPTOPP_END_TRACER_EVENTS };
  56. // In your own Tracer-derived class, you must define two methods per new trace event type:
  57. // - unsigned int TraceXxxx() const
  58. // Your default implementation of this method should return the event number if according
  59. // to the default trace level system the event should be traced, or 0 if it should not.
  60. // - void TraceXxxx(string const& s)
  61. // This method should call TraceIf(TraceXxxx(), s); to do the tracing.
  62. // For your convenience, a macro to define these two types of methods are defined below.
  63. // If you use this macro, you should also use the TRACER_EVENTS macros above to associate
  64. // event names with numbers.
  65. #define CRYPTOPP_TRACER_EVENT_METHODS(EVENTNAME, LOGLEVEL) \
  66. virtual unsigned int Trace##EVENTNAME() const { return Tracing(EventNr_##EVENTNAME, LOGLEVEL); } \
  67. virtual void Trace##EVENTNAME(std::string const& s) { TraceIf(Trace##EVENTNAME(), s); }
  68. /*! A simple unidirectional linked list with m_prev == 0 to indicate the final entry.
  69. The aim of this implementation is to provide a very lightweight and practical
  70. tracing mechanism with a low performance impact. Functions and methods supporting
  71. this call-stack mechanism would take a parameter of the form "CallStack const& callStack",
  72. and would pass this parameter to subsequent functions they call using the construct:
  73. SubFunc(arg1, arg2, CallStack("my func at place such and such", &callStack));
  74. The advantage of this approach is that it is easy to use and should be very efficient,
  75. involving no allocation from the heap, just a linked list of stack objects containing
  76. pointers to static ASCIIZ strings (or possibly additional but simple data if derived). */
  77. class CallStack
  78. {
  79. public:
  80. CallStack(char const* i, CallStack const* p) : m_info(i), m_prev(p) {}
  81. CallStack const* Prev() const { return m_prev; }
  82. virtual std::string Format() const;
  83. protected:
  84. char const* m_info;
  85. CallStack const* m_prev;
  86. };
  87. /*! An extended CallStack entry type with an additional numeric parameter. */
  88. class CallStackWithNr : public CallStack
  89. {
  90. public:
  91. CallStackWithNr(char const* i, word32 n, CallStack const* p) : CallStack(i, p), m_nr(n) {}
  92. std::string Format() const;
  93. protected:
  94. word32 m_nr;
  95. };
  96. /*! An extended CallStack entry type with an additional string parameter. */
  97. class CallStackWithStr : public CallStack
  98. {
  99. public:
  100. CallStackWithStr(char const* i, char const* z, CallStack const* p) : CallStack(i, p), m_z(z) {}
  101. std::string Format() const;
  102. protected:
  103. char const* m_z;
  104. };
  105. CRYPTOPP_BEGIN_TRACER_CLASS_1(WaitObjectsTracer, Tracer)
  106. CRYPTOPP_BEGIN_TRACER_EVENTS(0x48752841)
  107. CRYPTOPP_TRACER_EVENT(NoWaitLoop)
  108. CRYPTOPP_END_TRACER_EVENTS
  109. CRYPTOPP_TRACER_EVENT_METHODS(NoWaitLoop, 1)
  110. CRYPTOPP_END_TRACER_CLASS
  111. struct WaitingThreadData;
  112. //! container of wait objects
  113. class WaitObjectContainer : public NotCopyable
  114. {
  115. public:
  116. //! exception thrown by WaitObjectContainer
  117. class Err : public Exception
  118. {
  119. public:
  120. Err(const std::string& s) : Exception(IO_ERROR, s) {}
  121. };
  122. static unsigned int MaxWaitObjects();
  123. WaitObjectContainer(WaitObjectsTracer* tracer = 0);
  124. void Clear();
  125. void SetNoWait(CallStack const& callStack);
  126. void ScheduleEvent(double milliseconds, CallStack const& callStack);
  127. // returns false if timed out
  128. bool Wait(unsigned long milliseconds);
  129. #ifdef USE_WINDOWS_STYLE_SOCKETS
  130. ~WaitObjectContainer();
  131. void AddHandle(HANDLE handle, CallStack const& callStack);
  132. #else
  133. void AddReadFd(int fd, CallStack const& callStack);
  134. void AddWriteFd(int fd, CallStack const& callStack);
  135. #endif
  136. private:
  137. WaitObjectsTracer* m_tracer;
  138. #ifdef USE_WINDOWS_STYLE_SOCKETS
  139. void CreateThreads(unsigned int count);
  140. std::vector<HANDLE> m_handles;
  141. std::vector<WaitingThreadData *> m_threads;
  142. HANDLE m_startWaiting;
  143. HANDLE m_stopWaiting;
  144. #else
  145. fd_set m_readfds, m_writefds;
  146. int m_maxFd;
  147. #endif
  148. bool m_noWait;
  149. double m_firstEventTime;
  150. Timer m_eventTimer;
  151. #ifdef USE_WINDOWS_STYLE_SOCKETS
  152. typedef size_t LastResultType;
  153. #else
  154. typedef int LastResultType;
  155. #endif
  156. enum { LASTRESULT_NOWAIT = -1, LASTRESULT_SCHEDULED = -2, LASTRESULT_TIMEOUT = -3 };
  157. LastResultType m_lastResult;
  158. unsigned int m_sameResultCount;
  159. Timer m_noWaitTimer;
  160. void SetLastResult(LastResultType result);
  161. void DetectNoWait(LastResultType result, CallStack const& callStack);
  162. };
  163. NAMESPACE_END
  164. #endif
  165. #endif