|
Thread-safetyThread-safty of the classes is provided by the template argument of ltmm::loader, ltmm::handle, and ltmm::backend.The argument should implement a thread policy of locking shared resources, and storage of thread-specific data. For single-threaded applications, the thread policy ltmm::single_thread provided should suffice. A thread-policy should have the following interface: class thread_policy { public: thread_policy() void lock(); void unlock(); void set_error(const char*); const char* get_error() const; };
For example, in a POSIX environment, an implementation, like the following would be appropriate: class posix_policy { private: // Mutex to lock access pthread_mutex_t _mutex; // Thread-specific key pthread_key_t _key; // For once intialisation of the key volatile bool _once; // How may locks have we got so far. int _count; // Get the thread specific data. std::string* specific() volatile { if (!_once) { lock(); if (!_once) { pthread_key_create(&_key, 0); _once = true; } unlock(); } std::string* s = static_cast<std::string*>(pthread_getspecific(_key)); if (!s) { s = new std::string(); pthread_setspecific(_key, (void*)s); } return s; } public: // Constructor posix_policy() : _once(false), _count(0) { pthread_mutex_init(&_mutex, 0); } // Recursive lock of mutex void lock() { if (_count == 0) pthread_mutex_lock(&_mutex); _count++; } // Recursive unlock of mutex void unlock() { _count-- if (_count == 0) pthread_mutex_unlock(&_mutex); } // Set the error in thread-specific data void set_error(const char* msg) { std::string s = specific(); *s = msg; } // Get the error from thread specific data. const char get_error() const { std::string s = specific(); return s->c_str(); } }; Notice the use of double-checked locking, to avoid race conditions on initialising the key. Strictly speaking, it may not be needed, but rather safe than sorry :-) With a class like that, it's easy to make the ltmm classes thread-safe: typedef ltmm::loader<posix_policy> loader; typedef ltmm::handle<posix_policy> handle; typedef ltmm::backend<posix_policy> backend; typedef ltmm::symbol symbol int main () { try { loader& l = loader::instance(); handle& h = l.load("libm.so"); symbol* s = h.find_symbol("cos"); ((double(*)(double))(s->ptr()))(0); } catch (...) { return 1; } return 0; } Last update Mon Jun 27 13:25:17 2005 Christian Holm Created by DoxyGen 1.4.3-20050530 |