C++ 中的 CountDownLatch使用 Boost 互斥体和条件

发布于 2024-11-03 19:38:35 字数 4345 浏览 5 评论 0原文

我尝试使用 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;           
    };

I tried to implement CountDownLatch using boost mutexes and condition variable. Below is the code and would like to know if I need to add anything else.

How can I unit test this code as well?

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;           
    };

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

叹梦 2024-11-10 19:38:35

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

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

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

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

For unit testing, you can try stress-testing. For example, for CountDownLatch, create 25 test threads that simultaneously call CountDownLatch::countDown(), 25 other threads that simultaneously call CountDownLatch::getCount(), and 25 others threads that call CountDownLatch::wait(). To make things more simultaneous, use a barrier, or make the threads sleep until the same absolute time. Make sure that all threads terminate properly (no deadlocks) by joining all of them. Make sure that CountDownLatch::m_cdlCount ends up at zero.

Run the same test many times (for a reasonable amount of time).

You can use the same basic idea for AtomicCounter.

There are probably other techniques for testing multitheaded code, but this is the one I'm most familiar with.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文