Pins
Pins 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 Links. A Link connects Outpins to Inpins, 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 Inpins 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)
trueThe constructed link can be accessed though the pins.
julia> op.links[1] === link
true
julia> ip.link === link
trueThe 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) @0x00007fe0d3008010As 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) @0x00007fe0d444f340
julia> take!(ip2)
1.0
julia> take!(ip2)
2.0Note 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 — TypeInpin{T}()Constructs and InPut pin. The data flow from Inpin is inwards to the pin i.e., data is read from links of InPort.
Causal.Outpin — TypeOutpin{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.
Base.bind — Methodbind(link::Link, pin)Binds link to pin. When bound, data written into or read from pin is written into or read from link.
Base.eltype — Methodeltype(pin::AbstractPin)Returns element typef of pin.
Base.put! — Methodput!(pin::Outpin, val)Puts val to pin. val is put into the links of pin.
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::Inpin)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.0Causal.connect! — Methodconnect!(outpin::Link, inpin::Link)Connects outpin to inpin. When connected, any element that is put into outpin is also put into inpin.
connect!(outpin::AbstractVector{<:Link}, inpin::AbstractVector{<:Link})Connects each link in outpin to each link in inpin one by one. See also: disconnect!
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
trueCausal.disconnect! — Methoddisconnect!(link1::Link, link2::Link)Disconnects link1 and link2. The order of arguments is not important. See also: connect!
Causal.isbound — Methodisbound(pin::AbstractPin)Returns true if pin is bound to other pins.
Causal.isconnected — Methodisconnected(link1, link2)Returns true if link1 is connected to link2. The order of the arguments are not important. See also connect!, disconnect!