通过例子学TLA+(四)-- Send & Rev & Print

Send & Rev

稍微复杂点的程序中都会涉及数据的发送与接收,本例子基于发送器Sender与接收器Receiver来实现数据的变更。假设Sender发送一个数据给Receiver,Receiver接收后将确认信息发送给Sender,增加两个状态rdy,ack来表示发送者状态和确认状态,当rdy等于ack时允许sender发送数据,当rdy与ack不一致时则意味着Receiver有数据需要接收,用val来缓存sender发送的数据,Receiver用data来存储缓存的val数据。

创建Module,引入Naturals,定义变量

----------------------------- MODULE Interface ------------------------------ 
EXTENDS Naturals
CONSTANT Data        
VARIABLE rdy,ack,data,val

\* 限制上述变量的范围
TypeInvariant == rdy \in {0,1} /\ ack \in {0,1} /\ data \in Data /\ val \in Data 
=============================================================================

初始状态

Init == TypeInvariant /\ rdy = ack /\ data = val

发送与接收条件

CanSend == rdy = ack
CanAck == rdy # ack

发送数据

\* 用UNCHANGED ack替代 ack'=ack,用UNCHANGED data表示 data'=data
\* Send 数据时修改rdy的状态,保证rdy与ack是不一致的以便Ack来接收数据
Send(d) == CanSend /\ val' = d /\ rdy' = 1 - rdy /\ UNCHANGED ack /\ UNCHANGED data 

接收数据

\* 接收数据时修改ack与rdy保持一致,以便后续进行send
Ack == CanAck /\ data' = val /\ ack' = 1 - ack /\ UNCHANGED rdy /\ UNCHANGED val

下一步动作

\* 这里 Send与Ack是或的关系,根据发送与接收条件,Send与Ack只有一个动作能执行
\* \E d \in Data:Send(d) 表示Send任意存在于Data中的d
Next == (\E d \in Data:Send(d)) \/ Ack  

Print

在程序调试或者执行的过程中,通常需要打印出中间状态来查看代码是否正确。在TLA+中,可以通过引入TLC Module来实现打印功能。

EXTENDS TLC
Print(out,val) 
\* Print 会同时将out,val的值打印出来,同时返回val的值。当用在表达式中时,val的值通常为TRUE

可以通过自定义打印动作来打印出更多的参数,例如

\* 下面PrintVal可以打印id,exp,TRUE三个参数,同时返回TRUE。
PrintVal(id, exp)  ==  Print(<<id, exp>>, TRUE)
\* 添加更多打印参数,直接添加即可,如
PrintVal(id,exp,res) == Print(<<id,exp,res>>,TRUE)

Interface完整实现

EXTENDS Naturals,TLC
CONSTANT Data
VARIABLE rdy,ack,data,val

PrintVal(id, exp)  ==  Print(<<id, exp>>, TRUE)

TypeInvariant == rdy \in {0,1} /\ ack \in {0,1} /\ data \in Data /\ val \in Data 

CanSend == rdy = ack
CanAck == rdy # ack

Init == TypeInvariant /\  rdy = ack /\ data = val

Send(d) == CanSend /\ val' = d /\ rdy' = 1 - rdy /\ UNCHANGED ack /\ UNCHANGED data /\ PrintVal("Send",d)  

Ack == CanAck /\ data' = val /\ ack' = 1 - ack /\ UNCHANGED rdy /\ UNCHANGED val /\ PrintVal("Ack",val)

Next == (\E d \in Data:Send(d)) \/ Ack

输出

设置Init,Next以及Data的配置,设置Data输入集为{1,2,3,4}如下:
在这里插入图片描述

由于上述TLA+代码中添加量Print打印,可以在执行后的User Output中查看输出结果:
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值