OpenThreads库介绍——Block

1. 简介


Block 是OpenThreads中的阻塞器类。顾名思义,这个类的作用就是阻塞线程的执行,使用block()阻塞执行它的线程(注意,不一定是定义它的Thread 线程,而是当前执行了block 函数的线程,包括系统主进程),并使用release()释放之前被阻塞的线程。

2. 实现


OpenThreads库中的Block文件中包括两个类的实现:Block和BlockCount,后者添加了一个计数器,控制多次操作之后释放阻塞的线程。 它与阻塞器类的使用方法基本相同:block()阻塞线程,release()释放线程;不过除此之外,BlockCount 的构造函数还可以设置一个阻塞计数值。计数的作用是:每当阻塞器对象的completed()函数被执行一次,计数器就减一,直至减到零
就释放被阻塞的线程。

2.1 Block

Block类是使用OpenThreads中的Condition来实现的,在传统的线程概念(比如C++11中)并没有一个与之对应的类,Block的成员中包括

        Mutex _mut;
        Condition _cond;
        bool _released;

在Block的Block方法实现如下:

        inline bool block()
        {
            ScopedLock<OpenThreads::Mutex> mutlock(_mut);
            if( !_released )
            {
                return _cond.wait(&_mut)==0;
            }
            else
            {
                return true;
            }
        }

可以看到它是通过一个Condition来阻塞运行这个函数的线程,并等待其他线程唤醒这个运行它的线程。唤醒的操作在release函数中实现:

        inline void release()
        {
            ScopedLock<OpenThreads::Mutex> mutlock(_mut);
            if (!_released)
            {
                _released = true;
                _cond.broadcast();
            }
        }

这里使用的是Condition中的broadcast方法(没有使用signal),也就是同时释放多个阻塞的线程。

由此可以知道这个类的使用方式:在A线程中调用它的block方法,导致A线程被阻塞。然后在B线程中调用它的release方法,释放被阻塞的A线程。(也可以在多个线程中调用block方法,导致多个线程被阻塞,然后B线程可以调用release方法一次性释放多个被阻塞的线程)

2.2 BlockCount

它的block和release实现和Block完全几乎一样,但是它里面有一个计数器,实现如下:

        inline void block()
        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
            if (_currentCount)
                _cond.wait(&_mut);
        }

如果_currentCount是0,那么不会进入阻塞。

        inline void release()
        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
            if (_currentCount)
            {
                _currentCount = 0;
                _cond.broadcast();
            }
        }

在realse中同样是会根据_currentCount值来释放所有的线程。假设想使用一个BlockCount来实现和Block一样的功能,那么必须这样做:

//首先声明一个BlockCount
BlockCount bc;
//设置它的Count不是0,设置任何非零的正整数都可以
bc.setBlockCount(1);
//然后就可以和Block一样在一个线程中调用阻塞它
bc.block();
//另一个线程中唤醒
bc.release();

除此之外,这个类提供了一个completed的函数,用来递减技术,当计数为0,释放被阻塞的线程

        inline void completed()
        {
            OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
            if (_currentCount>0)
            {
                --_currentCount;

                if (_currentCount==0)
                {
                    // osg::notify(osg::NOTICE)<<"Released"<<std::endl;
                    _cond.broadcast();
                }
            }
        }

也就是这个类可以让释放被阻塞线程的那个线程(上文示例中的B线程)可以有一个计数器,通过这个计数器到0,决定释放所有其他线程。

3. 示例


#include <OpenThreads/Thread>
#include <OpenThreads/Condition>
#include <OpenThreads/Mutex>
#include <OpenThreads/ScopedLock>
#include <OpenThreads/Block>
#include <iostream>



class TestThread : public OpenThreads::Thread
{
public:
    TestThread() : _done(false), _count(0){ }
    ~TestThread() {  cancel();  }

    void block(){ _block.block(); }

    virtual int cancel()
    {
        _block.release();
        _done = true;
        while (isRunning())
        {
            OpenThreads::Thread::YieldCurrentThread();
        }
        return 0;
    }

    virtual void run()
    {
        do 
        {
            std::cout << "(" << _count << ")";
            ++_count;

            if (_count == 10)
            {
                _block.release();
                _block.reset();
                _block.block();
            }
            microSleep(150000);

        } while (!_done);
    }



protected:
    bool                    _done;
    unsigned long       _count;
    OpenThreads::Block  _block;
};



int main()
{
    TestThread t;
    t.start();
    t.block();
    std::cout << "(Main)" << std::endl;
    getchar();
    t.cancel();

    return 0;
}

运行程序的结果:

Thread

可以发现,Block::block()函数将首先阻塞主进程,被释放后再次阻塞的是TestThread 线程,这与它是谁的成员变量并无关系。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值