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