Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
progress on graph structure
  • Loading branch information
canonic-epicure committed Jun 12, 2020
1 parent 9d32123 commit b343eac
Show file tree
Hide file tree
Showing 12 changed files with 209 additions and 274 deletions.
2 changes: 2 additions & 0 deletions src/chrono2/CalculationMode.ts
Expand Up @@ -53,3 +53,5 @@ export type CalculationReturnValue<Result, Mode extends CalculationMode> =


export type CalculationFunction<Result, Mode extends CalculationMode> = (Y : EffectHandler<Mode>) => CalculationReturnValue<Result, Mode>

export type CalculationFunction2 = <Result, Mode extends CalculationMode>(Y : EffectHandler<Mode>) => CalculationReturnValue<Result, Mode>
130 changes: 91 additions & 39 deletions src/chrono2/Iteration.ts → src/chrono2/Graph.ts
@@ -1,39 +1,60 @@
import { Base } from "../class/Base.js"
import { AnyConstructor } from "../class/Mixin.js"
import { MIN_SMI } from "../util/Helpers.js"
import { LeveledQueue } from "../util/LeveledQueue.js"
import { Uniqable } from "../util/Uniqable.js"
import { Box } from "./data/Box.js"
import { Immutable, Owner } from "./data/Immutable.js"
import { ChronoId, Identifiable } from "./Identifiable.js"
import { Atom, Quark } from "./Quark.js"
import { Atom, AtomState, Quark } from "./Quark.js"


const TombStone = null
// const TombStone = null

let revisionIdSource = MIN_SMI

//----------------------------------------------------------------------------------------------------------------------
export class ChronoIteration extends Immutable {
owner : ChronoTransaction

quarks : Map<ChronoId, Quark> = new Map()
quarks : Quark[] = []

revision : Revision = revisionIdSource++

getQuarkById (id : ChronoId) : Quark | null {
let iteration : this = this
// quarks : Map<ChronoId, Quark> = new Map()
//
//
// getQuarkById (id : ChronoId) : Quark | null {
// let iteration : this = this
//
// while (iteration) {
// const quark = iteration.quarks.get(id)
//
// if (quark !== undefined) return quark
//
// iteration = iteration.previous
// }
//
// return null
// }

while (iteration) {
const quark = iteration.quarks.get(id)

if (quark !== undefined) return quark
addQuark (quark : Quark) {
// TODO setup dev/prod builds
// <debug>
if (this.frozen) throw new Error("Can't modify frozen data")
// </debug>

iteration = iteration.previous
}
// this.quarks.set(quark.owner.id, quark)
this.quarks.push(quark)

return null
quark.iteration = this
}


addQuark (quark : Quark) {
this.quarks.set(quark.owner.id, quark)
freeze () {
for (let i = 0; i < this.quarks.length; i++) this.quarks[ i ].freeze()

super.freeze()
}


Expand All @@ -55,7 +76,7 @@ export class ChronoTransaction extends Owner implements Immutable {
get immutable () : ChronoIteration {
if (this.$immutable !== undefined) return this.$immutable

return this.$immutable = ChronoIteration.new({ owner : this })
return this.$immutable = ChronoIteration.new({ owner : this, previous : this.previous ? this.previous.immutable : undefined })
}

set immutable (value : ChronoIteration) {
Expand All @@ -71,7 +92,7 @@ export class ChronoTransaction extends Owner implements Immutable {

this.owner.setCurrent(next)

next.setCurrent(immutable)
// next.immutable = immutable
} else {
this.immutable = immutable
}
Expand Down Expand Up @@ -133,16 +154,28 @@ export class ChronoTransaction extends Owner implements Immutable {
}


//----------------------------------------------------------------------------------------------------------------------
export type Revision = number

//----------------------------------------------------------------------------------------------------------------------
export class ChronoGraph extends Base implements Owner, Uniqable {
uniqable : number = MIN_SMI

historyLimit : number = 0

stack : LeveledQueue<Quark> = new LeveledQueue()



//region ChronoGraph as Owner
immutable : ChronoTransaction = ChronoTransaction.new({ owner : this })

immutableForWrite () : this[ 'immutable' ] {
if (this.immutable.frozen) this.setCurrent(this.immutable.createNext())

return this.immutable
}


setCurrent (immutable : this[ 'immutable' ]) {
if (this.immutable && immutable && immutable.previous !== this.immutable) throw new Error("Invalid state thread")
Expand All @@ -152,49 +185,58 @@ export class ChronoGraph extends Base implements Owner, Uniqable {
//endregion


commit () {
const atoms = this.atomsA

for (let i = 0; i < atoms.length; i++) {
const atom = atoms[ i ] as Box

atom.read()
getCurrentRevision () : Revision {
return this.immutable.immutable.revision
}

atom.freeze()

this.immutable.addQuark(atom.immutable)
}
commit () {
this.calculateTransitionsSync()

this.immutable.freeze()

// this.revision++
}

reject () {
// nothing to reject
if (this.immutable.frozen) return

this.immutable = this.immutable.previous
}


atoms : Set<Atom> = new Set()
undo () {
}

redo () {

}

$atomsA : Atom[] = undefined

get atomsA () : Atom[] {
if (this.$atomsA !== undefined) return this.$atomsA
calculateTransitionsSync () {
const queue = this.stack

return this.$atomsA = Array.from(this.atoms)
while (queue.length) {
this.calculateTransitionsStackSync(queue.takeLowestLevel())
}
}

calculateTransitionsStackSync (stack : Quark[]) {
for (let i = 0; i < stack.length; i++) {
const atom = stack[ i ].owner as Box

hasAtom (atom : Atom) : boolean {
return this.atoms.has(atom)
if (atom.state !== AtomState.UpToDate) atom.read()

atom.freeze()
}
}


addAtom (atom : Atom) {
this.atoms.add(atom)

atom.enterGraph(this)

this.$atomsA = undefined
this.immutable.addQuark(atom.immutable)
}

addAtoms (atoms : Atom[]) {
Expand All @@ -203,10 +245,20 @@ export class ChronoGraph extends Base implements Owner, Uniqable {


removeAtom (atom : Atom) {
this.atoms.delete(atom)

atom.leaveGraph(this)
}

removeAtoms (atoms : Atom[]) {
atoms.forEach(atom => this.removeAtom(atom))
}


addPossiblyStaleStrictAtomToTransaction (atom : Atom) {
this.stack.push(atom.immutable)
}


this.$atomsA = undefined
addChangedAtomToTransaction (atom : Atom) {
this.immutableForWrite().addQuark(atom.immutable)
}
}
23 changes: 12 additions & 11 deletions src/chrono2/Meta.ts
@@ -1,8 +1,10 @@
import { Identifier } from "../chrono/Identifier.js"
import { Base } from "../class/Base.js"
import { Context } from "../primitives/Calculation.js"
import { Equality, strictEquality } from "../util/Helpers.js"
import { CalculationFunction, CalculationMode, CalculationModeSync, CalculationReturnValue } from "./CalculationMode.js"
import { EffectHandler, ProposedOrPrevious } from "./Effect.js"
import { globalContext } from "./GlobalContext.js"

//---------------------------------------------------------------------------------------------------------------------
/**
Expand All @@ -23,7 +25,7 @@ export class Meta extends Base {
/**
* The name of the identifiers. Not an id, does not imply uniqueness.
*/
name : string = 'Default Meta instance'
name : string = undefined

/**
* Whether this identifier is lazy (`true`) or strict (`false`).
Expand All @@ -32,11 +34,10 @@ export class Meta extends Base {
*
* Strict identifiers will be calculated on read or during the [[ChronoGraph.commit|commit]] call.
*/
lazy : boolean = false
lazy : boolean = true

/**
* Whether this identifier is sync (`true`) or generator-based (`false`). Default value is `true`.
* This attribute is supposed to be defined on the prototype level only.
*/
sync : boolean = true

Expand Down Expand Up @@ -71,21 +72,21 @@ export class Meta extends Base {
*
* @param Y
*/
calculation : CalculationFunction<unknown, CalculationMode>
calculation : CalculationFunction<unknown, CalculationMode> = defaultCalculationSync

/**
* The equality check of the identifier. By default is performed with `===`.
*
* @param v1 First value
* @param v2 Second value
*/
equality (v1 : unknown, v2 : unknown) : boolean {
return v1 === v2
}
equality : Equality = strictEquality
}

export const defaultCalculationSync = (Y : EffectHandler<CalculationModeSync>) => Y(ProposedOrPrevious)
export const defaultCalculationSync = (Y : EffectHandler<CalculationModeSync>) => {
// return Y(ProposedOrPrevious)

export const defaultMetaSync = Meta.new({
calculation : defaultCalculationSync
})
return globalContext.activeQuark.owner.readProposeOrPrevious()
}

export const DefaultMetaSync = Meta.new({ name : 'DefaultMetaSync' })
6 changes: 5 additions & 1 deletion src/chrono2/Node.ts
Expand Up @@ -10,6 +10,7 @@ export class Node implements Uniqable {

outgoingCompacted : boolean = false

// TODO we can also just check the last element in the `$outgoing`, need to benchmark
lastOutgoingTo : Node = undefined


Expand Down Expand Up @@ -37,6 +38,7 @@ export class Node implements Uniqable {
clearOutgoing () {
this.$outgoing = undefined
this.outgoingCompacted = false
this.lastOutgoingTo = undefined
}


Expand All @@ -53,7 +55,9 @@ export class Node implements Uniqable {

this.outgoingCompacted = false

this.getOutgoing().push(to)
if (this.$outgoing === undefined) this.$outgoing = []

this.$outgoing.push(to)
if (!calledFromPartner) to.addIncoming(this, true)
}
}
Expand Down

0 comments on commit b343eac

Please sign in to comment.