1+ import {
2+ type WritablePort ,
3+ Parameter ,
4+ InPort ,
5+ OutPort ,
6+ State ,
7+ Reactor ,
8+ App ,
9+ type TimeValue ,
10+ Log
11+ } from "../core/internal" ;
12+
13+ // This is the thrshold for the quicksort algorithm, feeding sorters below this number will use Array.prototype.sort()
14+ // toSorted() is more ideal but I think there is some compatibility issue.
15+ const T = 8 ;
16+
17+ Log . global . level = Log . levels . INFO ;
18+
19+ class QuickSorter extends Reactor {
20+ parentReadPort : InPort < number [ ] > ;
21+ parentWritePort : OutPort < number [ ] > ;
22+ leftWritePort : OutPort < number [ ] > ;
23+ rightWritePort : OutPort < number [ ] > ;
24+ leftReadPort : InPort < number [ ] > ;
25+ rightReadPort : InPort < number [ ] > ;
26+
27+ leftArr : State < number [ ] | undefined > ;
28+ rightArr : State < number [ ] | undefined > ;
29+
30+ leftReactor : Reactor | undefined ;
31+ rightReactor : Reactor | undefined ;
32+
33+ constructor ( parent : Reactor , name = "Innocent QuickSorter" ) {
34+ super ( parent , name ) ;
35+ this . parentReadPort = new InPort < number [ ] > ( this ) ;
36+ this . parentWritePort = new OutPort < number [ ] > ( this ) ;
37+ this . leftWritePort = new OutPort < number [ ] > ( this ) ;
38+ this . rightWritePort = new OutPort < number [ ] > ( this ) ;
39+ this . leftReadPort = new InPort < number [ ] > ( this ) ;
40+ this . rightReadPort = new InPort < number [ ] > ( this ) ;
41+ this . leftArr = new State ( undefined ) ;
42+ this . rightArr = new State ( undefined ) ;
43+
44+ // When the parent sends a message, we send it to children.
45+ this . addMutation (
46+ [ this . parentReadPort ] ,
47+ [ this . parentReadPort ,
48+ this . parentWritePort ,
49+ this . leftWritePort ,
50+ this . rightWritePort
51+ ] ,
52+ function ( this , parentReadPort , parentWritePort , leftWritePort , rightWritePort ) {
53+ const fullarr = parentReadPort . get ( ) ;
54+ if ( fullarr == null ) {
55+ throw Error ( "Received null from port" )
56+ }
57+ if ( fullarr . length <= T ) {
58+ const sorted = [ ...fullarr ] . sort ( ( a , b ) => ( a - b ) ) ;
59+ this . getReactor ( ) . writable ( parentWritePort ) . set ( sorted ) ;
60+ return ;
61+ }
62+ const pivot = fullarr [ 0 ] ;
63+ const leftToSort = fullarr . filter ( ( val ) => ( val <= pivot ) ) ;
64+ const righttoSort = fullarr . filter ( ( val ) => ( val > pivot ) ) ;
65+
66+ console . log ( `I received a request! ${ fullarr } ! Pivot is ${ pivot } , so I divided it into ${ leftToSort } and ${ righttoSort } ` ) ;
67+
68+ // First, create 2 new reactors
69+ const leftReactor = this . getReactor ( ) . _uncheckedAddSibling ( QuickSorter ) ;
70+ const rightReactor = this . getReactor ( ) . _uncheckedAddSibling ( QuickSorter ) ;
71+
72+ // Connect ports accoringly
73+ this . connect ( leftWritePort , leftReactor . parentReadPort ) ;
74+ this . connect ( rightWritePort , rightReactor . parentReadPort ) ;
75+
76+ this . getReactor ( ) . writable ( leftWritePort ) . set ( leftToSort ) ;
77+ this . getReactor ( ) . writable ( rightWritePort ) . set ( righttoSort ) ;
78+ }
79+ ) ;
80+
81+ this . addMutation (
82+ [ this . leftReadPort ] ,
83+ [
84+ this . leftReadPort ,
85+ this . rightReadPort ,
86+ this . leftArr ,
87+ this . rightArr ,
88+ this . writable ( this . parentWritePort )
89+ ] ,
90+ function ( this , leftreadport , rightreadport , leftarr , rightarr , parentWrite ) {
91+ const leftState = leftarr . get ( ) ;
92+ const rightState = rightarr . get ( ) ;
93+ const leftResult = leftreadport . get ( ) ;
94+ if ( leftState != null && leftState . length > 0 ) {
95+ throw Error ( "Received sort result from left, but left already has message." ) ;
96+ }
97+ if ( leftResult == null ) {
98+ throw Error ( "Left return null" ) ;
99+ }
100+ console . log ( `I received a result! ${ leftResult } !` ) ;
101+ if ( rightState == null ) {
102+ leftarr . set ( leftResult ) ;
103+ } else {
104+ // First, detach from parent read
105+ this . disconnect ( leftreadport ) ;
106+ this . disconnect ( rightreadport ) ;
107+ this . connect ( parentWrite , /* What to put here??????? */ unknown ) ;
108+ const consolidated = [ ...leftResult , ...rightState ] ;
109+ console . log ( `Left completed! Setting parent to ${ consolidated } ` )
110+ parentWrite . set ( consolidated ) ;
111+ }
112+ }
113+ ) ;
114+
115+ this . addMutation (
116+ [ this . rightReadPort ] ,
117+ [
118+ this . rightReadPort ,
119+ this . leftArr ,
120+ this . rightArr ,
121+ this . writable ( this . parentWritePort )
122+ ] ,
123+ function ( this , rightreadport , leftarr , rightarr , parentWrite ) {
124+ const leftState = leftarr . get ( ) ;
125+ const rightState = rightarr . get ( ) ;
126+ const rightResult = rightreadport . get ( ) ;
127+ if ( rightState != null && rightState . length > 0 ) {
128+ throw Error ( "Received sort result from left, but left already has message." ) ;
129+ }
130+ if ( rightResult == null ) {
131+ throw Error ( "Left return null" ) ;
132+ }
133+ console . log ( `I received a result! ${ rightResult } !` ) ;
134+ if ( leftState == null ) {
135+ leftarr . set ( rightResult ) ;
136+ } else {
137+ const consolidated = [ ...leftState , ...rightResult ] ;
138+ console . log ( `Left completed! Setting parent to ${ consolidated } ` )
139+ parentWrite . set ( consolidated ) ;
140+ }
141+ }
142+ ) ;
143+ }
144+ }
145+
146+ class Supplier extends Reactor {
147+ rootWritePort : OutPort < number [ ] > ;
148+ rootReadPort : InPort < number [ ] > ;
149+
150+ constructor ( parent : Reactor , arr : number [ ] , name = "Innocent Supplier" ) {
151+ super ( parent , name ) ;
152+ this . rootWritePort = new OutPort < number [ ] > ( this ) ;
153+ this . rootReadPort = new InPort < number [ ] > ( this ) ;
154+ this . writable ( this . rootWritePort ) . set ( arr ) ;
155+
156+ this . addReaction (
157+ [ this . rootReadPort ] ,
158+ [ this . rootReadPort ] ,
159+ function ( this , rootReadPort ) {
160+ console . log ( `I received final result: ${ rootReadPort . get ( ) ?? "null" } ` ) ;
161+ }
162+ )
163+ }
164+ }
165+
166+ class Arbiter extends App {
167+ rootSorter : QuickSorter ;
168+ supplier : Supplier ;
169+
170+ constructor (
171+ name : string ,
172+ timeout : TimeValue | undefined = undefined ,
173+ keepAlive = false ,
174+ fast = false ,
175+ success ?: ( ) => void ,
176+ fail ?: ( ) => void
177+ ) {
178+ super ( timeout , keepAlive , fast , success , fail , name ) ;
179+ this . rootSorter = new QuickSorter ( this , "rootroot" ) ;
180+ this . supplier = new Supplier ( this , [ 5 , 1 , 4 , 1 , 1 , 4 , 8 , 1 , 0 , 1 , 9 , 1 , 9 ] ) ;
181+ this . _connect ( this . supplier . rootWritePort , this . rootSorter . parentReadPort ) ;
182+ // this._connect(this.rootSorter.parentWritePort, this.supplier.rootReadPort);
183+ }
184+ }
185+
186+ const arb = new Arbiter ( "arbiter" ) ;
187+ arb . _start ( ) ;
0 commit comments