Crypto++
|
00001 #ifndef CRYPTOPP_WAIT_H 00002 #define CRYPTOPP_WAIT_H 00003 00004 #include "config.h" 00005 00006 #ifdef SOCKETS_AVAILABLE 00007 00008 #include "misc.h" 00009 #include "cryptlib.h" 00010 #include <vector> 00011 00012 #ifdef USE_WINDOWS_STYLE_SOCKETS 00013 #include <winsock2.h> 00014 #else 00015 #include <sys/types.h> 00016 #endif 00017 00018 #include "hrtimer.h" 00019 00020 NAMESPACE_BEGIN(CryptoPP) 00021 00022 class Tracer 00023 { 00024 public: 00025 Tracer(unsigned int level) : m_level(level) {} 00026 virtual ~Tracer() {} 00027 00028 protected: 00029 //! Override this in your most-derived tracer to do the actual tracing. 00030 virtual void Trace(unsigned int n, std::string const& s) = 0; 00031 00032 /*! By default, tracers will decide which trace messages to trace according to a trace level 00033 mechanism. If your most-derived tracer uses a different mechanism, override this to 00034 return false. If this method returns false, the default TraceXxxx(void) methods will all 00035 return 0 and must be overridden explicitly by your tracer for trace messages you want. */ 00036 virtual bool UsingDefaults() const { return true; } 00037 00038 protected: 00039 unsigned int m_level; 00040 00041 void TraceIf(unsigned int n, std::string const&s) 00042 { if (n) Trace(n, s); } 00043 00044 /*! Returns nr if, according to the default log settings mechanism (using log levels), 00045 the message should be traced. Returns 0 if the default trace level mechanism is not 00046 in use, or if it is in use but the event should not be traced. Provided as a utility 00047 method for easier and shorter coding of default TraceXxxx(void) implementations. */ 00048 unsigned int Tracing(unsigned int nr, unsigned int minLevel) const 00049 { return (UsingDefaults() && m_level >= minLevel) ? nr : 0; } 00050 }; 00051 00052 // Your Tracer-derived class should inherit as virtual public from Tracer or another 00053 // Tracer-derived class, and should pass the log level in its constructor. You can use the 00054 // following methods to begin and end your Tracer definition. 00055 00056 // This constructor macro initializes Tracer directly even if not derived directly from it; 00057 // this is intended, virtual base classes are always initialized by the most derived class. 00058 #define CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED) \ 00059 public: DERIVED(unsigned int level = 0) : Tracer(level) {} 00060 00061 #define CRYPTOPP_BEGIN_TRACER_CLASS_1(DERIVED, BASE1) \ 00062 class DERIVED : virtual public BASE1 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED) 00063 00064 #define CRYPTOPP_BEGIN_TRACER_CLASS_2(DERIVED, BASE1, BASE2) \ 00065 class DERIVED : virtual public BASE1, virtual public BASE2 { CRYPTOPP_TRACER_CONSTRUCTOR(DERIVED) 00066 00067 #define CRYPTOPP_END_TRACER_CLASS }; 00068 00069 // In your Tracer-derived class, you should define a globally unique event number for each 00070 // new event defined. This can be done using the following macros. 00071 00072 #define CRYPTOPP_BEGIN_TRACER_EVENTS(UNIQUENR) enum { EVENTBASE = UNIQUENR, 00073 #define CRYPTOPP_TRACER_EVENT(EVENTNAME) EventNr_##EVENTNAME, 00074 #define CRYPTOPP_END_TRACER_EVENTS }; 00075 00076 // In your own Tracer-derived class, you must define two methods per new trace event type: 00077 // - unsigned int TraceXxxx() const 00078 // Your default implementation of this method should return the event number if according 00079 // to the default trace level system the event should be traced, or 0 if it should not. 00080 // - void TraceXxxx(string const& s) 00081 // This method should call TraceIf(TraceXxxx(), s); to do the tracing. 00082 // For your convenience, a macro to define these two types of methods are defined below. 00083 // If you use this macro, you should also use the TRACER_EVENTS macros above to associate 00084 // event names with numbers. 00085 00086 #define CRYPTOPP_TRACER_EVENT_METHODS(EVENTNAME, LOGLEVEL) \ 00087 virtual unsigned int Trace##EVENTNAME() const { return Tracing(EventNr_##EVENTNAME, LOGLEVEL); } \ 00088 virtual void Trace##EVENTNAME(std::string const& s) { TraceIf(Trace##EVENTNAME(), s); } 00089 00090 00091 /*! A simple unidirectional linked list with m_prev == 0 to indicate the final entry. 00092 The aim of this implementation is to provide a very lightweight and practical 00093 tracing mechanism with a low performance impact. Functions and methods supporting 00094 this call-stack mechanism would take a parameter of the form "CallStack const& callStack", 00095 and would pass this parameter to subsequent functions they call using the construct: 00096 00097 SubFunc(arg1, arg2, CallStack("my func at place such and such", &callStack)); 00098 00099 The advantage of this approach is that it is easy to use and should be very efficient, 00100 involving no allocation from the heap, just a linked list of stack objects containing 00101 pointers to static ASCIIZ strings (or possibly additional but simple data if derived). */ 00102 class CallStack 00103 { 00104 public: 00105 CallStack(char const* i, CallStack const* p) : m_info(i), m_prev(p) {} 00106 CallStack const* Prev() const { return m_prev; } 00107 virtual std::string Format() const; 00108 00109 protected: 00110 char const* m_info; 00111 CallStack const* m_prev; 00112 }; 00113 00114 /*! An extended CallStack entry type with an additional numeric parameter. */ 00115 class CallStackWithNr : public CallStack 00116 { 00117 public: 00118 CallStackWithNr(char const* i, word32 n, CallStack const* p) : CallStack(i, p), m_nr(n) {} 00119 std::string Format() const; 00120 00121 protected: 00122 word32 m_nr; 00123 }; 00124 00125 /*! An extended CallStack entry type with an additional string parameter. */ 00126 class CallStackWithStr : public CallStack 00127 { 00128 public: 00129 CallStackWithStr(char const* i, char const* z, CallStack const* p) : CallStack(i, p), m_z(z) {} 00130 std::string Format() const; 00131 00132 protected: 00133 char const* m_z; 00134 }; 00135 00136 CRYPTOPP_BEGIN_TRACER_CLASS_1(WaitObjectsTracer, Tracer) 00137 CRYPTOPP_BEGIN_TRACER_EVENTS(0x48752841) 00138 CRYPTOPP_TRACER_EVENT(NoWaitLoop) 00139 CRYPTOPP_END_TRACER_EVENTS 00140 CRYPTOPP_TRACER_EVENT_METHODS(NoWaitLoop, 1) 00141 CRYPTOPP_END_TRACER_CLASS 00142 00143 struct WaitingThreadData; 00144 00145 //! container of wait objects 00146 class WaitObjectContainer : public NotCopyable 00147 { 00148 public: 00149 //! exception thrown by WaitObjectContainer 00150 class Err : public Exception 00151 { 00152 public: 00153 Err(const std::string& s) : Exception(IO_ERROR, s) {} 00154 }; 00155 00156 static unsigned int MaxWaitObjects(); 00157 00158 WaitObjectContainer(WaitObjectsTracer* tracer = 0); 00159 00160 void Clear(); 00161 void SetNoWait(CallStack const& callStack); 00162 void ScheduleEvent(double milliseconds, CallStack const& callStack); 00163 // returns false if timed out 00164 bool Wait(unsigned long milliseconds); 00165 00166 #ifdef USE_WINDOWS_STYLE_SOCKETS 00167 ~WaitObjectContainer(); 00168 void AddHandle(HANDLE handle, CallStack const& callStack); 00169 #else 00170 void AddReadFd(int fd, CallStack const& callStack); 00171 void AddWriteFd(int fd, CallStack const& callStack); 00172 #endif 00173 00174 private: 00175 WaitObjectsTracer* m_tracer; 00176 00177 #ifdef USE_WINDOWS_STYLE_SOCKETS 00178 void CreateThreads(unsigned int count); 00179 std::vector<HANDLE> m_handles; 00180 std::vector<WaitingThreadData *> m_threads; 00181 HANDLE m_startWaiting; 00182 HANDLE m_stopWaiting; 00183 #else 00184 fd_set m_readfds, m_writefds; 00185 int m_maxFd; 00186 #endif 00187 bool m_noWait; 00188 double m_firstEventTime; 00189 Timer m_eventTimer; 00190 00191 #ifdef USE_WINDOWS_STYLE_SOCKETS 00192 typedef size_t LastResultType; 00193 #else 00194 typedef int LastResultType; 00195 #endif 00196 enum { LASTRESULT_NOWAIT = -1, LASTRESULT_SCHEDULED = -2, LASTRESULT_TIMEOUT = -3 }; 00197 LastResultType m_lastResult; 00198 unsigned int m_sameResultCount; 00199 Timer m_noWaitTimer; 00200 void SetLastResult(LastResultType result); 00201 void DetectNoWait(LastResultType result, CallStack const& callStack); 00202 }; 00203 00204 NAMESPACE_END 00205 00206 #endif 00207 00208 #endif