Policy benutzen, um Threading-Verhalten in Klasse zu geben
-
Das Problem ist, dass ich boost komplett wegkapseln muss, da der single-threaded teil des projekts kein boost zur verfügung hat.
Daher darf in der Klasse kein boost-Code drinstehen, der muß über die Policy reinkommen. Das ging vorher halt über ein #ifdef.
-
Dann schreib halt eben deinen eigenen Lock-Guard. Ist ja auch nicht weiters wild:
template<typename MutexT> class scoped_lock { private: MutexT& m_mutex; public: scoped_lock(Mutex& mutex) : m_mutex(mutex) { m_mutex.lock(); } ~scoped_lock() { m_mutex.unlock(); } private: scoped_lock(scoped_lock const&) { } scoped_lock& operator =(scoped_lock const&) { } };Statt
boost::lock_guardverwendest du halt nunscoped_lock.Grüssli
-
Das scheint genau das zu leisten, was ich brauche:
#include <iostream> #include <boost/thread.hpp> #include <QMutexLocker> using namespace std; class BoostThreaded { public: typedef boost::mutex Mutex; typedef boost::mutex::scoped_lock ScopedLock; protected: Mutex lock_; }; class QThreaded { public: typedef QMutex Mutex; typedef QMutexLocker ScopedLock; QThreaded():lock_(new QMutex) {}; ~QThreaded() { delete lock_; } protected: Mutex* lock_; }; class SingleThreaded { public: typedef void* Mutex; typedef void* ScopedLock; protected: Mutex lock_; }; template <class ThreadingPolicy> class Foo: public ThreadingPolicy { public: typedef typename ThreadingPolicy::ScopedLock ScopedLock; using ThreadingPolicy::lock_; void bar() { ScopedLock lock(lock_); cout << "Bar!" << endl; } }; int main(int argc, char *argv[]) { Foo<BoostThreaded> my_threaded_foo; my_threaded_foo.bar(); Foo<QThreaded> my_qthreaded_foo; my_qthreaded_foo.bar(); Foo<SingleThreaded> my_singlethreaded_foo; my_singlethreaded_foo.bar(); return 0; }Meinungen ?
-
Wieso erbst du von der Policy?
Grüssli
-
Ähm, weil ich das so gelernt habe?!
Laut Alexandrescu ist policy-based design die Kombination von Mehrfachvererbung mit Templates durch das Erben von seinen Templateparametern. Wikipedia sieht das genauso.Philipp
EDIT: Und so klappts auch mit der Nachbarin, ähh, der Wait-Condition:
#include <iostream> #include <boost/thread.hpp> #include <QMutexLocker> #include <QWaitCondition> using namespace std; class BoostThreaded { public: typedef boost::mutex Mutex; typedef boost::mutex::scoped_lock ScopedLock; typedef boost::condition_variable WaitCondition; void wait(ScopedLock& lock) { condition_.wait(lock); } void notify() { condition_.notify_one(); } protected: Mutex lock_; WaitCondition condition_; }; class QThreaded { public: typedef QMutex Mutex; typedef QMutexLocker ScopedLock; typedef QWaitCondition WaitCondition; void wait(ScopedLock&) { condition_.wait(lock_); } void notify() { condition_.wakeOne(); } QThreaded():lock_(new QMutex) {}; ~QThreaded() { delete lock_; } protected: Mutex* lock_; WaitCondition condition_; }; class SingleThreaded { public: typedef void* Mutex; typedef void* ScopedLock; void wait(ScopedLock&) {} void notify() {} protected: Mutex lock_; }; template <class ThreadingPolicy> class Foo: public ThreadingPolicy { public: typedef typename ThreadingPolicy::ScopedLock ScopedLock; using ThreadingPolicy::lock_; using ThreadingPolicy::wait; using ThreadingPolicy::notify; void bar() { ScopedLock lock(lock_); cout << "Bar!" << endl; wait(lock); notify(); } }; int main(int argc, char *argv[]) { Foo<BoostThreaded> my_threaded_foo; my_threaded_foo.bar(); Foo<QThreaded> my_qthreaded_foo; my_qthreaded_foo.bar(); Foo<SingleThreaded> my_singlethreaded_foo; my_singlethreaded_foo.bar(); return 0; }
-
Dravere schrieb:
Wieso erbst du von der Policy?
Erben muß nicht sein, und eigentlich denke ich, daß es hier böse ist.
Aber die "Empty Member" Optimization http://www.cantrip.org/emptyopt.html greift da so schön.
-
Aber wie soll ich sonst an die mutex-membervariable drankommen? Dann müsste ich ja Foo zum friend jeder Policy machen, bzw die Policy selbst wieder zum template, damit T ihr friend sein kann, damit er auf mutex_ zugreifen kann.
-
PhilippM schrieb:
Aber wie soll ich sonst an die mutex-membervariable drankommen? Dann müsste ich ja Foo zum friend jeder Policy machen, bzw die Policy selbst wieder zum template, damit T ihr friend sein kann, damit er auf mutex_ zugreifen kann.
Policies sind so klein und simpel, da dard ein Attribut auch mal pubnlic sein.
-
na dann

-
Dann präsentiere ich hier die parametrierbare concurrent-queue:
#include <iostream> #include <queue> #include <boost/thread.hpp> #include <QMutexLocker> #include <QWaitCondition> using namespace std; class BoostThreaded { public: typedef boost::mutex Mutex; typedef boost::mutex::scoped_lock ScopedLock; typedef boost::condition_variable WaitCondition; void wait(ScopedLock& lock) { condition_.wait(lock); } void notify() { condition_.notify_one(); } Mutex mutex_; WaitCondition condition_; }; class QThreaded { public: typedef QMutex Mutex; typedef QMutexLocker ScopedLock; typedef QWaitCondition WaitCondition; void wait(ScopedLock&) { condition_.wait(mutex_); } void notify() { condition_.wakeOne(); } QThreaded():mutex_(new QMutex) {}; ~QThreaded() { delete mutex_; } Mutex* mutex_; WaitCondition condition_; }; class SingleThreaded { public: typedef void* Mutex; typedef void* ScopedLock; void wait(ScopedLock&) {} void notify() {} Mutex mutex_; }; template <class ThreadingPolicy> class Foo { public: typedef typename ThreadingPolicy::ScopedLock ScopedLock; void bar() { ScopedLock lock(tp.mutex_); cout << "Bar!" << endl; } private: ThreadingPolicy tp; }; template<typename Data, class ThreadingPolicy> class concurrent_queue { public: void push(Data const& data) { { ScopedLock lock(tp.mutex_); the_queue.push(data); } tp.notify(); } bool empty() const { ScopedLock lock(tp.mutex_); return the_queue.empty(); } bool try_pop(Data& popped_value) { ScopedLock lock(tp.mutex_); if(the_queue.empty()) { return false; } popped_value = the_queue.front(); the_queue.pop(); return true; } void wait_and_pop(Data& popped_value) { ScopedLock lock(tp.mutex_); while(the_queue.empty()) { wait(mutex_); } popped_value=the_queue.front(); the_queue.pop(); } private: typedef typename ThreadingPolicy::ScopedLock ScopedLock; std::queue<Data> the_queue; ThreadingPolicy tp; }; int main(int, char **) { Foo<BoostThreaded> my_threaded_foo; my_threaded_foo.bar(); Foo<QThreaded> my_qthreaded_foo; my_qthreaded_foo.bar(); Foo<SingleThreaded> my_singlethreaded_foo; my_singlethreaded_foo.bar(); concurrent_queue<float, BoostThreaded> my_concurrent_float_queue; my_concurrent_float_queue.push(23.42f); float f; my_concurrent_float_queue.wait_and_pop(f); cout << f << endl; return 0; }