两个宏分别定义如下:
// MyException.h #include "Poco/Exception.h" POCO_DECLARE_EXCEPTION(MyLib_API, MyException, Poco::Exception)
// MyException.cpp #include "MyException.h"POCO_IMPLEMENT_EXCEPTION(MyException, Poco::Exception,"Something really bad happened...")
// MyException.h #include "Poco/Exception.h" POCO_DECLARE_EXCEPTION(MyLib_API, MyException, Poco::Exception) class MyLib_API MyException: public Poco::Exception { public: MyException(); MyException(const std::string& msg); MyException(const std::string& msg, const std::string& arg); MyException(const std::string& msg, const Poco::Exception& nested); MyException(const MyException& exc); ~MyException(); MyException& operator = (const MyException& exc); const char* name() const; ... };
// MyException.cpp #include "MyException.h" POCO_IMPLEMENT_EXCEPTION(MyException, Poco::Exception, "Something really bad happened...") ... const char* MyException::name() const throw() { return "Something really bad happened..."; } ...
#include "Poco/Exception.h" #include <iostream> int main(int argc, char** argv) { Poco::Exception* pExc = 0; try { throw Poco::ApplicationException("just testing"); } catch (Poco::Exception& exc) { pExc = exc.clone(); } try { pExc->rethrow(); } catch (Poco::Exception& exc) { std::cerr << exc.displayText() << std::endl; } delete pExc; return 0; }
void foo(Bar* pBar) { poco_check_ptr (pBar); ... } void baz(int i) { poco_assert (i >= 1 && i < 3); switch (i) { case 1: ... break; case 2: ... break; default: poco_bugcheck_msg("i has invalid value"); } }
BOOL WINAPI IsDebuggerPresent(VOID); VOID WINAPI DebugBreak(VOID);
#include "Poco/NestedDiagnosticContext.h" #include <iostream> void f1() { poco_ndc(f1); Poco::NDC::current().dump(std::cout); } void f2() { poco_ndc(f2); f1(); } int main(int argc, char** argv) { f2(); return 0; }
使用了TLS技术后,调用Thread的静态函数current可以获取到每个线程对象Thread的指针,然后再通过这个Thread对象的指针,可以获取到ThreadLocalStorage对象,并最终获取或保存数据于TLSSlot中。
通过类的静态函数获取类实例的指针,在C++中是不存在的,这需要操作系统支持,只有Thread对象才能做到这一点。
#define poco_ndc(func) \ Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__) #if defined(_DEBUG) #define poco_ndc_dbg(func) \ Poco::NDCScope _theNdcScope(#func, __LINE__, __FILE__) #else #define poco_ndc_dbg(func) #endif
inline NDCScope::NDCScope(const std::string& info) { NestedDiagnosticContext::current().push(info); } inline NDCScope::NDCScope(const std::string& info, int line, const char* filename) { NestedDiagnosticContext::current().push(info, line, filename); } inline NDCScope::~NDCScope() { NestedDiagnosticContext::current().pop(); }
namespace { static ThreadLocal<NestedDiagnosticContext> ndc; } NestedDiagnosticContext& NestedDiagnosticContext::current() { return ndc.get(); }
template <class C> class ThreadLocal /// This template is used to declare type safe thread /// local variables. It can basically be used like /// a smart pointer class with the special feature /// that it references a different object /// in every thread. The underlying object will /// be created when it is referenced for the first /// time. /// See the NestedDiagnosticContext class for an /// example how to use this template. /// Every thread only has access to its own /// thread local data. There is no way for a thread /// to access another thread's local data. { typedef TLSSlot<C> Slot; public: ThreadLocal() { } ~ThreadLocal() { } C* operator -> () { return &get(); } C& operator * () /// "Dereferences" the smart pointer and returns a reference /// to the underlying data object. The reference can be used /// to modify the object. { return get(); } C& get() /// Returns a reference to the underlying data object. /// The reference can be used to modify the object. { TLSAbstractSlot*& p = ThreadLocalStorage::current().get(this); if (!p) p = new Slot; return static_cast<Slot*>(p)->value(); } private: ThreadLocal(const ThreadLocal&); ThreadLocal& operator = (const ThreadLocal&); };
到这里Poco中所有的NDC流程都被打通了,用户终于可以实现按线程打印日志信息了。
(版权所有,转载时请注明作者和出处 http://blog.csdn.net/arau_sh/article/details/8698353)