|
Thread-safety of the classesThe thread-safety level of the classes depends greatly on the thread-safty of the underlying parser and scanner generators (Yacc and Lex).If they produce thread-safe code, then the classes are thread-safe.
For example, Bison allows you to specify the parser to be reentrant (does not depend on global variables or static data) via the definition
That said, it is actually easy to make the client code thread-safe using a little disciplin. If the client code derives classes from ylmm::basic_parser and ylmm::basic_scanner and implment locking in these classes, the client code is for all pratical purposes thread safe. The only caveat, is that all access to the parser and scanner should go through that derived layer - client code must not manipulate the global variable
That said, there is one point where the multi-threaded programmer
To protect against that, ylmm::basic_messenger accepts a template argument
All classes that manipulates, directly or indirectly, a ylmm::basic_messenger has a similar argument, which is passed on to the ylmm::basic_messenger class. So, for a multi-threaded application on a platform that provides a POSIX interface, this could spell out to be #ifndef _PTHREAD_H #include <pthread.h> #endif class thread_lock { private: pthread_mutex_t _mutex; public: thread_lock() { pthread_mutex_init(&_mutex); } ~thread_lock() { pthread_mutex_destroy(&_mutex); } void lock() pthread_mutex_lock(&_mutex); } void unlock() pthread_mutex_lock(&_mutex); } }; class thread_guard { private: thread_lock& _lock; public: thread_guard(thread_lock& l) : _lock(l) { _lock.lock(); } ~thread_guard() { _lock.unlock(); } }; The client can then use that class as an argument to the parser and scanner classes:
class node; class scanner : public ylmm::basic_scanner<node,ylmm::location, 0, thread_lock>; class parser : public ylmm::basic_parser<node,ylmm::location, 0, thread_lock>;
Both ylmm::basic_parser and ylmm::basic_scanner defines the nested type class parser : public ylmm::basic_parser<node,ylmm::location, 0, thread_lock> { private: lock_type _lock; ylmm::basic_parser<node,ylmm::location,0, thread_lock> _scanner; public: int scan(void* arg) { thread_guard g(_lock); return _scanner->next(&token()); } ... } Christian Holm (home page) Last update Fri Jul 8 12:58:03 2005 Created by DoxyGen 1.4.3-20050530 |