Skip to content

Commit 9a95399

Browse files
committed
quicksort prototype
1 parent 7413e83 commit 9a95399

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

src/benchmark/quicksort-sibling.ts

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
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();

src/core/reactor.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,6 +1199,7 @@ export abstract class Reactor extends Component {
11991199
) {
12001200
return true;
12011201
} else {
1202+
console.log(`out to in, ${src._isContainedByContainerOf(this)}, ${dst._isContainedByContainerOf(this)}`);
12021203
return false;
12031204
}
12041205
} else {
@@ -1209,6 +1210,7 @@ export abstract class Reactor extends Component {
12091210
) {
12101211
return true;
12111212
} else {
1213+
console.log(`out to out, ${src._isContainedByContainerOf(this)}, ${(dst === undefined || dst._isContainedBy(this))}`);
12121214
return false;
12131215
}
12141216
}
@@ -1218,6 +1220,7 @@ export abstract class Reactor extends Component {
12181220
if (src._isContainedBy(this) && dst._isContainedByContainerOf(this)) {
12191221
return true;
12201222
} else {
1223+
console.log("in to in");
12211224
return false;
12221225
}
12231226
} else {
@@ -1229,6 +1232,7 @@ export abstract class Reactor extends Component {
12291232
) {
12301233
return true;
12311234
} else {
1235+
console.log("in to out");
12321236
return false;
12331237
}
12341238
}

0 commit comments

Comments
 (0)