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.

Note

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)
true

The constructed link can be accessed though the pins.

julia> op.links[1] === link
true

julia> ip.link === link
true
Note

It is possible for an Outpin to have multiple Links bound to itself. On contract, an Inpin can have just one Link.

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.

Warning

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.InpinType
mutable 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

source
Causal.OutpinType
mutable 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

source
Base.bindMethod
bind(link, inpin)

Binds link to pin. When bound, data written into or read from pin is written into or read from link.

source
Base.put!Method
put!(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)
source
Base.take!Method
take!(pin)

Takes data from pin. The data is taken from 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> 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
source
Causal.connect!Method
connect!(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
source