Pins
Pin
s are building blocks of Ports. Pins can be thought of gates of components as they are the most primitive type for data transfer inside and outside the components. There are two types of pins: Outpin
and Inpin
. The data flows from inside of the components to its outside through Outpin
while data flow from outside of the components to its inside through Inpin
.
Connection and Disconnection of Pins
In Causal, signal flow modelling approach is adopted(see Modeling and Simulation for more information on modelling approach in Causal). In this approach, the components drive each other and data flow is unidirectional. The unidirectional data movement is carried out though the Link
s. A Link
connects Outpin
s to Inpin
s, and the data flow is from Outpin
to Inpin
.
As the data movement is from Outpin
to Inpin
, connection of an Inpin
to an Outpin
gives a MethodError
.
For example, let us construct and Outpin
and Inpin
s and connect the together.
julia> using Causal # hide
julia> op = Outpin()
Outpin(eltype:Float64, isbound:false)
julia> ip = Inpin()
Inpin(eltype:Float64, isbound:false)
julia> link = connect!(op, ip)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
Note connect!(op, ip)
connects op
and ip
through a Link
can return the constructed link. The connection of pins can be monitored.
julia> isconnected(op, ip)
true
The constructed link
can be accessed though the pins.
julia> op.links[1] === link
true
julia> ip.link === link
true
The connected links Outpin
and Inpin
can be disconnected using disconnect!
function. When disconnected, the data transfer from the Outpin
to Inpin
is not possible.
Data Flow Through Pins
The data flow from an Outpin
to an Inpin
. However for data flow through a pin, a running task must be bound the channel of the link of the pin. See the example below.
julia> t = @async while true
take!(ip) === NaN && break
end
Task (runnable) @0x00007f1fcfd52bf0
As the task t
is bound the channel of the link
data can flow through op
and ip
.
julia> put!(op, 1.)
julia> put!(op, 2.)
julia> put!(op, 3.)
Note that t
is a taker job. As the taker job t
takes data from op
, we were able to put values into op
. The converse is also possible.
julia> op2, ip2 = Outpin(), Inpin()
(Outpin(eltype:Float64, isbound:false), Inpin(eltype:Float64, isbound:false))
julia> link2 = connect!(op2, ip2)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> t2 = @async for item in 1 : 5
put!(op2, item)
end
Task (runnable) @0x00007f1fd477a980
julia> take!(ip2)
1.0
julia> take!(ip2)
2.0
Note that in both of the cases given above the data flow is always from an Outpin
to an Inpin
.
It is not possible to take data from an Outpin
and put into Inpin
. Thus, take!(pin::Outpoin)
and put!(pin::Inpin)
throws a method error.
Full API
Causal.AbstractPin
— TypeCausal.Inpin
— Typemutable struct Inpin{T} <: AbstractPin{T}
Constructs and InPut
pin. The data flow from Inpin
is inwards to the pin i.e., data is read from links of InPort
.
Fields
link::Union{Missing, Link{T}} where T
Links bound to the inpin. The data read from input is read from the links
id::Base.UUID
Unique identifier
Causal.Outpin
— Typemutable struct Outpin{T} <: AbstractPin{T}
Constructs and OutPut
pin. The data flow from Outpin
is outwards from the pin i.e., data is written from OutPort
to its links.
Fields
links::Union{Missing, Array{Link{T},1}} where T
Links bound to the outpin. The data written to pin is transfered to all the links
id::Base.UUID
Unique identifier
Base.bind
— Methodbind(link, inpin)
Binds link
to pin
. When bound, data written into or read from pin
is written into or read from link
.
Base.eltype
— MethodReturns element typef of pin.
Base.put!
— Methodput!(pin, val)
Puts val
to pin
. val
is put into the links of pin
.
!!! warning To take data from pin
, a running task that puts data must be bound to link
of pin
.
Example
julia> op = Outpin();
julia> l = Link();
julia> bind(l, op);
julia> t = @async while true
val = take!(l)
val === NaN && break
println("Took " * string(val))
end;
julia> put!(op, 1.)
Took 1.0
julia> put!(op, 3.)
Took 3.0
julia> put!(op, NaN)
Base.take!
— Methodtake!(pin)
Takes data from pin
. The data is taken from the links of pin
.
To take data from pin
, a running task that puts data must be bound to link
of pin
.
Example
julia> ip = Inpin();
julia> l = Link();
julia> bind(l, ip);
julia> t = @async for item in 1 : 5
put!(l, item)
end;
julia> take!(ip)
1.0
julia> take!(ip)
2.0
Causal.connect!
— Methodconnect!(outpin, inpin)
Connects outpin
to inpin
. When connected, any element that is put into outpin
is also put into inpin
.
Example
julia> op, ip = Outpin(), Inpin();
julia> l = connect!(op, ip)
Link(state:open, eltype:Float64, isreadable:false, iswritable:false)
julia> l in op.links
true
julia> ip.link === l
true
Causal.disconnect!
— Methoddisconnect!(outpin, inpin)
Disconnects link1
and link2
. The order of arguments is not important. See also: connect!
Causal.isbound
— Methodisbound(outpin)
Returns true
if pin
is bound to other pins.
Causal.isconnected
— Methodisconnected(outpin, inpin)
Returns true
if link1
is connected to link2
. The order of the arguments are not important. See also connect!
, disconnect!