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)==;
}
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 = ;
_cond.broadcast();
}
}
在realse中同樣是會根據_currentCount值來釋放所有的線程。假設想使用一個BlockCount來實作和Block一樣的功能,那麼必須這樣做:
//首先聲明一個BlockCount
BlockCount bc;
//設定它的Count不是0,設定任何非零的正整數都可以
bc.setBlockCount();
//然後就可以和Block一樣在一個線程中調用阻塞它
bc.block();
//另一個線程中喚醒
bc.release();
除此之外,這個類提供了一個completed的函數,用來遞減技術,當計數為0,釋放被阻塞的線程
inline void completed()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> mutlock(_mut);
if (_currentCount>)
{
--_currentCount;
if (_currentCount==)
{
// 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(){ }
~TestThread() { cancel(); }
void block(){ _block.block(); }
virtual int cancel()
{
_block.release();
_done = true;
while (isRunning())
{
OpenThreads::Thread::YieldCurrentThread();
}
return ;
}
virtual void run()
{
do
{
std::cout << "(" << _count << ")";
++_count;
if (_count == )
{
_block.release();
_block.reset();
_block.block();
}
microSleep();
} 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 ;
}
運作程式的結果:

可以發現,Block::block()函數将首先阻塞主程序,被釋放後再次阻塞的是TestThread 線程,這與它是誰的成員變量并無關系。