Skip to content

Commit

Permalink
update linearization logic multiple semantics
Browse files Browse the repository at this point in the history
  • Loading branch information
trungnotchung committed Nov 27, 2024
1 parent e8adfc2 commit c436b74
Showing 1 changed file with 45 additions and 161 deletions.
206 changes: 45 additions & 161 deletions packages/object/src/linearize/multipleSemantics.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { hash } from "node:crypto";
import { BitSet } from "../hashgraph/bitset.js";
import {
ActionType,
type Hash,
Expand All @@ -8,112 +6,7 @@ import {
type Vertex,
} from "../hashgraph/index.js";

export function fullLinearization(hashGraph: HashGraph): Operation[] {
const order = hashGraph.topologicalSort(true);
const dropped = new Array(order.length).fill(false);
const indices: Map<Hash, number> = new Map();
const result: Operation[] = [];
let i = 0;

while (i < order.length) {
if (dropped[i]) {
i++;
continue;
}
const anchor = order[i];
let j = i + 1;

while (j < order.length) {
if (dropped[j]) {
j = hashGraph.findNextCausallyUnrelated(anchor, j) ?? order.length;
continue;
}
const moving = order[j];

if (!hashGraph.areCausallyRelatedUsingBitsets(anchor, moving)) {
const concurrentOps: Hash[] = [];
concurrentOps.push(anchor);
indices.set(anchor, i);
concurrentOps.push(moving);
indices.set(moving, j);

let reachableVertices: BitSet = new BitSet(
hashGraph.getCurrentBitsetSize(),
);
const anchorReachablePredecessors =
hashGraph.getReachablePredecessors(anchor);
if (anchorReachablePredecessors) {
reachableVertices = reachableVertices.or(anchorReachablePredecessors);
}
const movingReachablePredecessors =
hashGraph.getReachablePredecessors(moving);
if (movingReachablePredecessors) {
reachableVertices = reachableVertices.or(movingReachablePredecessors);
}

let k = reachableVertices.findNext(j, 0);
while (k < order.length) {
if (dropped[k]) {
k = reachableVertices.findNext(k, 0);
continue;
}

let add = true;
for (const hash of concurrentOps) {
if (hashGraph.areCausallyRelatedUsingBitsets(hash, order[k])) {
add = false;
break;
}
}
if (add) {
concurrentOps.push(order[k]);
indices.set(order[k], k);
const reachablePredecessors = hashGraph.getReachablePredecessors(
order[k],
);
if (reachablePredecessors) {
reachableVertices = reachableVertices.or(reachablePredecessors);
}
}

k = reachableVertices.findNext(k, 0);
}
const resolved = hashGraph.resolveConflicts(
concurrentOps.map((hash) => hashGraph.vertices.get(hash) as Vertex),
);

switch (resolved.action) {
case ActionType.Drop: {
for (const hash of resolved.vertices || []) {
dropped[indices.get(hash) || -1] = true;
}
if (dropped[i]) {
j = order.length;
}
break;
}
case ActionType.Nop:
j = hashGraph.findNextCausallyUnrelated(anchor, j) ?? order.length;
break;
default:
break;
}
} else {
j = hashGraph.findNextCausallyUnrelated(anchor, j) ?? order.length;
}
}

if (!dropped[i]) {
const op = hashGraph.vertices.get(order[i])?.operation;
if (op && op.value !== null) result.push(op);
}
i++;
}

return result;
}

export function partialLinearization(
export function linearizeMultipleSemantics(
hashGraph: HashGraph,
origin: Hash,
subgraph: Set<string>,
Expand All @@ -133,58 +26,60 @@ export function partialLinearization(
let j = i + 1;

while (j < order.length) {
if (dropped[j]) {
if (
hashGraph.areCausallyRelatedUsingBitsets(anchor, order[j]) ||
dropped[j]
) {
j++;
continue;
}
const moving = order[j];

if (!hashGraph.areCausallyRelatedUsingBitsets(anchor, moving)) {
const concurrentOps: Hash[] = [];
concurrentOps.push(anchor);
indices.set(anchor, i);
concurrentOps.push(moving);
indices.set(moving, j);

let k = j + 1;
for (; k < order.length; k++) {
if (dropped[k]) {
continue;
}
let add = true;
for (const hash of concurrentOps) {
if (hashGraph.areCausallyRelatedUsingBitsets(hash, order[k])) {
add = false;
break;
}
}
if (add) {
concurrentOps.push(order[k]);
indices.set(order[k], k);
}
const concurrentOps: Hash[] = [];
concurrentOps.push(anchor);
indices.set(anchor, i);
concurrentOps.push(moving);
indices.set(moving, j);

let k = j + 1;
while (k < order.length) {
if (dropped[k]) {
k++;
continue;
}
const resolved = hashGraph.resolveConflicts(
concurrentOps.map((hash) => hashGraph.vertices.get(hash) as Vertex),
);

switch (resolved.action) {
case ActionType.Drop: {
for (const hash of resolved.vertices || []) {
dropped[indices.get(hash) || -1] = true;
}
if (dropped[i]) {
j = order.length;
}
let add = true;
for (const hash of concurrentOps) {
if (hashGraph.areCausallyRelatedUsingBitsets(hash, order[k])) {
add = false;
break;
}
case ActionType.Nop:
j++;
break;
default:
break;
}
} else {
j++;
if (add) {
concurrentOps.push(order[k]);
indices.set(order[k], k);
}
k++;
}
const resolved = hashGraph.resolveConflicts(
concurrentOps.map((hash) => hashGraph.vertices.get(hash) as Vertex),
);

switch (resolved.action) {
case ActionType.Drop: {
for (const hash of resolved.vertices || []) {
dropped[indices.get(hash) || -1] = true;
}
if (dropped[i]) {
j = order.length;
}
break;
}
case ActionType.Nop:
j++;
break;
default:
break;
}
}

Expand All @@ -197,14 +92,3 @@ export function partialLinearization(

return result;
}

export function linearizeMultipleSemantics(
hashGraph: HashGraph,
origin: Hash,
subgraph: Set<string>,
): Operation[] {
if (subgraph.size === hashGraph.vertices.size) {
return fullLinearization(hashGraph);
}
return partialLinearization(hashGraph, origin, subgraph);
}

0 comments on commit c436b74

Please sign in to comment.