信箱mailbox
线程通信的三个类型:
- event
- semaphore
- mailbox
mailbox信箱,顾名思义,可以用来收发信息。
在SV中,mailbox可以用来存放任何数据类型,也可以从信箱中读取这些数据
信箱可以设置尺寸大小,防止存储数据过多,或者占用过多资源
信箱存放数据的方式,是同FIFO一致的,即先存放进来的数据,也会被先读出
信箱mailbox的内建方法
//创建信箱:
new ()
//将信息写入信箱:
put ()
//试着写入信箱但不会阻塞:
try_put ()
//获取信息:
get()//同时会取出数据,
peek()//不会取出数据
//试着从信箱取出数据但不会阻塞:
try_get ()
try_peek ()
//获取信箱信息的数目:
num ()
mailbox::new()
可以在创建信箱的时候限定或者不限定其大小。
function new(int bound = 0) ;
//默认情况下,如果不传入参数,bound默认值为0,表示不限定信箱大小,
//如果bound传入的数值大于0,那么表示信箱的最大容量。
//bound应为正数,如果为负数的话,系统会提示警告和出现无法预期的行为。
mailbox::num()
num()会返回信箱目前的消息数目。
可以结合num()与get()或者put(),防止get()/put()方法在信箱为空或者为满的时候被阻塞。
例子
如果发现信箱的消息数目为0,就可以不调用阻塞方法get()(不取出数据);
或者消息数目已经到达最大容量时,就可以不调用阻塞方法put()(不写入数据)。
存储数据
mai lbox: : {put (), try put ()}
task put ( singular message) ;
function int try_put ( singular message) ;
put()
put()会将信息按照FIFO的顺序写入到信箱。
如果信箱此时已满,则put()任务会挂起,直到信箱有新的空间可以容纳消息。
try_put()
try_put()也会按照FIFO顺序写入信箱,不会发生阻塞。
如果信箱已满,则写入失败,返回0;如果信箱未满,则写入成功,返回1。
取出数据
mailbox:: { get(), try get () }
会将读取到的消息从信箱中移除
task get ( ref singular message ) ;
function int try_get ( ref singular message ) ;
//get()会将信息从信箱中取出,如果信箱此时为空,则get()任务会挂起,
//直到信箱中有消息可以读取,任务才会返回。该方法会将读取到的消息从信箱中移除。
try_get()也会将信息从信箱中取出,只是该函数不会发生阻塞。
//如果信箱为空,则读取失败,返回0;如果信箱不为空,则读取成功,返回1。
//该方法也会将读取到的消息从信箱中移除。
mailbox::{peek(), try peek()}
不会将读取到的消息从信箱中移除
task peek( ref singular message ) ;
function int try_peek( ref singular message );
//peek()会将信息从信箱中拷贝,如果信箱此时为空,则peek()任务会挂起,
//直到信箱中有消息可以拷贝,任务才会返回。
//该方法不会将读取到的消息从信箱中移除。
//try_peek()也会将信息从信箱中拷贝,只是该函数不会发生阻塞。
//如果信箱为空,则拷贝失败,返回0;如果信箱不为空,则拷贝成功,返回1。
//该方法也不会将拷贝到的消息从信箱中移除。
参数化信箱
默认的信箱,在没有指定存储类型的情况下,可以存储任何类型的数据,这是一个强大的功能(程序也可能会为此受伤)。
默认信箱的问题:
如果将各种形式的数据都存放到信箱,看起来轻松,但是对接下来的从信箱中获得数据带来了麻烦
为了避免运行时错误和类型不匹配,我们建议在声明信箱的时候,为其指定存储的类型。
这种参数化信箱的方式可以使得在编译时就能够检查出类型不匹配的情况。
示例:
typedef mailbox #(string) s_mbox;
s_mbox sm = new;
string s;
sm. put ( "hello”) ;
...
sm. get( s ); // s <- "hello"
信箱和队列的差别
- 信箱必须通过new()例化,而队列只需要声明即可。
- 信箱的存取方法put()和get()是阻塞方法,即使用它们时,方法不一定会立即返回,而队列所对应的存取方式,push_back()和pop_front ()方法是非阻塞的,会立即返回。
- 在传递形式参数时,如果是input方向,那么信箱类型传递的是句柄,而队列类型则完成的是队列内容的拷贝。
通信要素的比较和应用
event:
最小信息量的触发,即单一的通知功能。可以用来做事件的触发,也可以多个事件组合起来用来做线程之间的同步。
semaphore:
共享资源的安全卫士。如果多线程间要对某一公共资源做访问,即可以使用这个要素。
mail box:
精小的SV原生FIFO。在线程之间做数据通信或者内部数据缓存时可以考虑使用此元素。