- Main Page
- Namespaces
- Classes
- Files

# wait.h

    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