1

我尝试使用 boost 互斥锁和条件变量来实现 CountDownLatch。下面是代码,想知道我是否需要添加任何其他内容。

我如何也可以对这段代码进行单元测试?

template< class TypeVal >
    class AtomicCounter
    {
    public:
        AtomicCounter( TypeVal val ) : m_typeVal( val ) 
        {
        }

        AtomicCounter() : m_typeVal(0)
        {
        }

        AtomicCounter(const AtomicCounter& cpy) : m_typeVal(cpy.m_typeVal)
        {   
            boost::mutex::scoped_lock scoped_lock(cpy.m_atomicMutex);
            m_typeVal = cpy.m_typeVal;
        }

        const AtomicCounter& operator=(const AtomicCounter& other)
        {
           if (this == &other)
              return *this;
           boost::mutex::scoped_lock lock1(&m_atomicMutex < &other.m_atomicMutex ? m_atomicMutex : other.m_atomicMutex);
           boost::mutex::scoped_lock lock2(&m_atomicMutex > &other.m_atomicMutex ? m_atomicMutex : other.m_atomicMutex);
           m_typeVal = other.m_typeVal;
           return *this;
        }

        virtual ~AtomicCounter() 
        {
        }

        const TypeVal& getCount() const
        { 
            boost::mutex::scoped_lock lock( m_atomicMutex ); 
            return m_typeVal; 
        }

        const TypeVal& setCount( const TypeVal &val ) 
        { 
            boost::mutex::scoped_lock lock( m_atomicMutex ); 
            m_typeVal = val; 
            return m_typeVal; 
        }

        const TypeVal& increment() 
        { 
            boost::mutex::scoped_lock lock( m_atomicMutex ); 
            m_typeVal++ ; 
            return m_typeVal; 
        }

        const TypeVal& decrement() 
        { 
            boost::mutex::scoped_lock lock( m_atomicMutex ); 
            m_typeVal-- ; 
            return m_typeVal; 
        }

        const TypeVal& increment(const TypeVal& t) 
        { 
            boost::mutex::scoped_lock lock( m_atomicMutex ); 
            m_typeVal+=t ; 
            return m_typeVal; 
        }

        const TypeVal& decrement(const TypeVal& t) 
        { 
            boost::mutex::scoped_lock lock( m_atomicMutex ); 
            m_typeVal-=t ; 
            return m_typeVal; 
        }


    private:
        mutable boost::mutex m_atomicMutex;
        TypeVal m_typeVal;
    };

           class CountDownLatch
    {
    public:
        CountDownLatch( int count ): m_cdlCount( count ) 
        {
        }

        CountDownLatch(const CountDownLatch& cpy)
        {
             boost::unique_lock<boost::mutex>::unique_lock(const_cast<boost::mutex&>(cpy.m_cdlMutex));
            m_cdlCount = cpy.m_cdlCount;
        }

        const CountDownLatch& operator=(const CountDownLatch& other)
        {
           if (this == &other)
              return *this;
           boost::mutex::scoped_lock lock1(const_cast<boost::mutex&>(&m_cdlMutex < &other.m_cdlMutex ? m_cdlMutex : other.m_cdlMutex));
           boost::mutex::scoped_lock lock2(const_cast<boost::mutex&>(&m_cdlMutex > &other.m_cdlMutex ? m_cdlMutex : other.m_cdlMutex));
           m_cdlCount = other.m_cdlCount;
           return *this;
        }

        virtual ~CountDownLatch() 
        {
        }
        void wait() 
        { 
            boost::mutex::scoped_lock lock( m_cdlMutex ); 
            if( m_cdlCount.getCount() > 0 ) 
            { 
                m_cdlCondition.wait( lock ); 
            } 
        }
        void wait( uint64_t timeoutMicros ) 
        { 
            boost::mutex::scoped_lock lock( m_cdlMutex ); 
            if( m_cdlCount.getCount() > 0 ) 
            {
                boost::posix_time::time_duration td = boost::posix_time::milliseconds( timeoutMicros ); 
                m_cdlCondition.timed_wait( lock, td ); 
            } 
        }
        void countDown() 
        {  
            boost::mutex::scoped_lock lock( m_cdlMutex ); 
            if( m_cdlCount.decrement() == 0 ) 
            { 
                m_cdlCondition.notify_all(); 
            } 
        }

        int getCount()
        {
            return m_cdlCount.getCount();
        }


    private:
        boost::mutex m_cdlMutex;
        boost::condition_variable m_cdlCondition;
        AtomicCounter< int >  m_cdlCount;           
    };
4

1 回答 1

1

对于单元测试,您可以尝试压力测试。例如,对于 CountDownLatch,创建 25 个同时调用的测试线程CountDownLatch::countDown()、25 个同时调用的其他线程CountDownLatch::getCount()和 25 个其他调用的线程CountDownLatch::wait()。要使事情更加同步,请使用屏障,或使线程休眠直到相同的绝对时间。通过加入所有线程,确保所有线程正确终止(没有死锁)。确保CountDownLatch::m_cdlCount最终为零。

多次运行相同的测试(在合理的时间内)。

您可以对 AtomicCounter 使用相同的基本思想。

可能还有其他测试多头代码的技术,但这是我最熟悉的一种。

于 2011-04-28T23:50:20.740 回答