1

以下のコードについて知りたいのは、次のとおりです。メソッド呼び出しの周りにtrycatchブロックを使用することは良い習慣です。以下のコードの愚行は何ですか?

#ifndef TIMER_H
#define TIMER_H

#include <boost/bind/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/function.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

#include <stdint.h>
#include <iostream>
#include <vector>

template <uint32_t tMilliSeconds>
class Timer {
private:
    static Timer *_instance;
    uint32_t mMilliSeconds;
    boost::mutex mListMutex;
    boost::thread mTimerThread;
    std::vector<boost::function<void()> > mHandlerList;

    Timer();
    Timer(const Timer &other);
    Timer &operator=(const Timer &other);
    void Run();

public:
    ~Timer();
    static boost::shared_ptr<Timer<tMilliSeconds> > Instance();
    void AddHandler(boost::function<void()> tmpBoostFunction);
};

template <uint32_t tMilliSeconds>
Timer<tMilliSeconds>::Timer() :
    mListMutex() {
    mMilliSeconds = tMilliSeconds;

    mTimerThread = boost::thread(
        boost::bind(&Timer<tMilliSeconds>::Run, this));
}

template <uint32_t tMilliSeconds>
Timer<tMilliSeconds>::~Timer()  {
    mListMutex.lock();
    try {
        mTimerThread.detach();
    } catch (...) {
        mListMutex.unlock();
    }
    mListMutex.unlock();
}

template <uint32_t tMilliSeconds>
boost::shared_ptr<Timer<tMilliSeconds> >
Timer<tMilliSeconds>::Instance() {
    if (!_instance) {
        _instance = new Timer<tMilliSeconds>();
    }
    return boost::shared_ptr<Timer<tMilliSeconds> >(_instance);
}

template <uint32_t tMilliSeconds>
void Timer<tMilliSeconds>::Run() {
    while(true) {
        boost::this_thread::sleep(
            boost::posix_time::milliseconds(mMilliSeconds));
        mListMutex.lock();
        for (std::vector<boost::function<void()> >::iterator vect_it =
            mHandlerList.begin(); vect_it != mHandlerList.end();
            ++vect_it) {
            try {
                (*vect_it)();
            } catch (...) {
                mListMutex.unlock();
            }
        }
        mListMutex.unlock();
    }
}

template <uint32_t tMilliSeconds>
void Timer<tMilliSeconds>::AddHandler(
    boost::function<void()> tmpBoostFunction) {

    mListMutex.lock();
    try {
        mHandlerList.push_back(tmpBoostFunction);
    } catch (...) {
        mListMutex.unlock();
    }
    mListMutex.unlock();
}
#endif // TIMER_H
4

2 に答える 2

3

Boostを使用しているので、ミューテックスをと組み合わせて使用​​することを検討します。boost::scoped_lockこれにより、scoped_lockオブジェクトがスコープ外になると、デストラクタ呼び出しによってミューテックスが「自動的に」ロック解除されます。例外を介してスタックを巻き戻すと、オブジェクトを介してミューテックスのロックが解除されるため、ミューテックスのロック解除tryをブロックとインターリーブすることを心配する必要はありません。catchscoped_lock

于 2012-09-25T21:56:26.497 に答える
0

いいえ、キャッチブロックの使用は間違っています。例外が発生した場合は、ロックを解除する必要があります。成功した場合は、一度だけlock()呼び出します。unlock()ロック解除を管理するロックラッパーを使用する必要があります。例:

class mutex_lock
{
private:
    boost::mutex &mListMutex; 
public:
    mutex_lock(boost::mutex &aListMutex) : mListMutex(aListMutex) { mListMutex.lock(); }
    ~mutex_lock() { mListMutex.unlock(); }
};

次に、これを行うことができます:

template <uint32_t tMilliSeconds> 
Timer<tMilliSeconds>::~Timer()
{ 
    mutex_lock lock(mListMutex); 
    mTimerThread.detach(); 
} 

template <uint32_t tMilliSeconds> 
void Timer<tMilliSeconds>::Run()
{ 
    while(true) { 
        boost::this_thread::sleep(
            boost::posix_time::milliseconds(mMilliSeconds)); 
        mutex_lock lock(mListMutex); 
        for (std::vector<boost::function<void()> >::iterator vect_it = mHandlerList.begin(); vect_it != mHandlerList.end(); ++vect_it) { 
            (*vect_it)(); 
        } 
    } 
} 

template <uint32_t tMilliSeconds> 
void Timer<tMilliSeconds>::AddHandler( 
    boost::function<void()> tmpBoostFunction)
{ 
    mutex_lock lock(mListMutex); 
    mHandlerList.push_back(tmpBoostFunction); 
} 

更新:scoped_lock boostには、これとまったく同じ目的のための独自のクラスがあります。

#include <boost/interprocess/sync/scoped_lock.hpp>

template <uint32_t tMilliSeconds> 
Timer<tMilliSeconds>::~Timer()
{ 
    boost::interprocess::scoped_lock<boost::mutex> lock(mListMutex); 
    mTimerThread.detach(); 
} 

template <uint32_t tMilliSeconds> 
void Timer<tMilliSeconds>::Run()
{ 
    while(true) { 
        boost::this_thread::sleep(
            boost::posix_time::milliseconds(mMilliSeconds)); 
        boost::interprocess::scoped_lock<boost::mutex> lock(mListMutex); 
        for (std::vector<boost::function<void()> >::iterator vect_it = mHandlerList.begin(); vect_it != mHandlerList.end(); ++vect_it) { 
            (*vect_it)(); 
        } 
    } 
} 

template <uint32_t tMilliSeconds> 
void Timer<tMilliSeconds>::AddHandler( 
    boost::function<void()> tmpBoostFunction)
{ 
    boost::interprocess::scoped_lock<boost::mutex> lock(mListMutex); 
    mHandlerList.push_back(tmpBoostFunction); 
} 
于 2012-09-25T21:56:48.280 に答える