-- |-- Module: FRP.NetWire.Concurrent-- Copyright: (c) 2011 Ertugrul Soeylemez-- License: BSD3-- Maintainer: Ertugrul Soeylemez <es@ertes.de>---- Wire concurrency. Send signals through multiple wires concurrently.-- This module is *highly experimental* and subject to change entirely-- in future revisions. Please use it with care.moduleFRP.NetWire.Concurrent(-- * Combining wires(~*~),(~&~),(~+~))whereimportControl.ApplicativeimportControl.ArrowimportControl.ConcurrentimportControl.Concurrent.STMimportControl.DeepSeqimportFRP.NetWire.ToolsimportFRP.NetWire.Wire-- | Concurrent version of '***'. Passes its input signals to both-- argument wires concurrently.(~*~)::WireIOac->WireIObd->WireIO(a,b)(c,d)w1'~*~w2'=mkGen$\ws(x',y')->do(xVar,thr1)<-forkWirew1'wsx'(yVar,thr2)<-forkWirew2'wsy'(mx,w1)<-takeMVarxVar(my,w2)<-takeMVaryVarmapM_killThread[thr1,thr2]return(liftA2(,)mxmy,w1~*~w2)infixr3~*~-- | Concurrent version of '&&&'. Passes its input signal to both-- argument wires concurrently.(~&~)::WireIOab->WireIOac->WireIOa(b,c)w1'~&~w2'=arrdup>>>w1'~*~w2'infixr3~&~-- | Concurrent version of '<+>'. Passes its input signal to both-- argument wires concurrently, returning the result of the first wire-- which does not inhibit.(~+~)::NFDatab=>WireIOab->WireIOab->WireIOabw1'~+~w2'=mkGen$\wsx'->dox1Var<-newEmptyTMVarIOx2Var<-newEmptyTMVarIOthr1<-forkIO(toGenw1'wsx'>>=atomically.putTMVarx1Var)thr2<-forkIO(toGenw2'wsx'>>=atomically.putTMVarx2Var)letres1=do(mx,w1)<-takeTMVarx1Var;check(isRightmx);return(mx,w1~+~w2')res2=do(mx,w2)<-takeTMVarx2Var;check(isRightmx);return(mx,w1'~+~w2)noRes=do(mx1,w1)<-takeTMVarx1Var(mx2,w2)<-takeTMVarx2Varcheck(isLeftmx1&&isLeftmx2)return(mx2,w1~+~w2)atomically(res1<|>res2<|>noRes)<*mapM_killThread[thr1,thr2]-- | Pass the given input to the given wire concurrently.forkWire::WireIOab->WireStateIO->a->IO(MVar(Outputb,WireIOab),ThreadId)forkWirew'wsx'=doresultVar<-newEmptyMVarthr<-forkIO(toGenw'wsx'>>=putMVarresultVar)return(resultVar,thr)-- | Is this a left value?isLeft::Eitherea->BoolisLeft=either(constTrue)(constFalse)-- | Is this a right value?isRight::Eitherea->BoolisRight=either(constFalse)(constTrue)