Nesting json unmarshal functions

graph-rework
noah metz 2023-06-23 22:19:43 -06:00
parent cb718d486f
commit fd9af3ef96
2 changed files with 59 additions and 53 deletions

@ -7,17 +7,19 @@ import (
// LockHolderState is the interface that any node that wants to posses locks must implement // LockHolderState is the interface that any node that wants to posses locks must implement
// //
// ReturnLock returns the node that held the resource pointed to by ID before this node, // ReturnLock returns the node that held the resource pointed to by ID before this node and
// or nil if the resource was unlocked previously // removes the mapping from it's state, or nil if the resource was unlocked previously
// //
// AllowedToTakeLock returns true if the node pointed to by ID is allowed to take a lock from this node // AllowedToTakeLock returns true if the node pointed to by ID is allowed to take a lock from this node
//
// RecordLockHolder records that resource_id needs to be passed back to lock_holder
type LockHolderState interface { type LockHolderState interface {
ReturnLock(resource_id NodeID) GraphNode ReturnLock(resource_id NodeID) GraphNode
AllowedToTakeLock(node_id NodeID, resource_id NodeID) bool AllowedToTakeLock(node_id NodeID, resource_id NodeID) bool
RecordLockHolder(resource_id NodeID, lock_holder GraphNode) RecordLockHolder(resource_id NodeID, lock_holder GraphNode)
} }
// Any node that wants to be connected to the lockable DAG must implement this interface // LockableState is the interface that a lockables state must have to allow it to connect to the DAG
type LockableState interface { type LockableState interface {
LockHolderState LockHolderState
Name() string Name() string
@ -29,12 +31,45 @@ type LockableState interface {
SetOwner(owner GraphNode) SetOwner(owner GraphNode)
} }
type BaseLockHolderState struct {
delegation_map map[NodeID] GraphNode
}
type BaseLockHolderStateJSON struct {
Delegations map[NodeID]*NodeID `json:"delegations"`
}
func (state * BaseLockHolderState) MarshalJSON() ([]byte, error) {
delegations := map[NodeID]*NodeID{}
for lockable_id, node := range(state.delegation_map) {
if node == nil {
delegations[lockable_id] = nil
} else {
str := node.ID()
delegations[lockable_id] = &str
}
}
return json.Marshal(&BaseLockHolderStateJSON{
Delegations: delegations,
})
}
// BaseLockableStates are a minimum collection of variables for a basic implementation of a LockHolder
// Include in any state structs that should be lockable
type BaseLockableState struct { type BaseLockableState struct {
BaseLockHolderState
name string name string
owner GraphNode owner GraphNode
requirements []Lockable requirements []Lockable
dependencies []Lockable dependencies []Lockable
delegation_map map[NodeID]GraphNode }
type BaseLockableStateJSON struct {
Name string `json:"name"`
Owner *NodeID `json:"owner"`
Dependencies []NodeID `json:"dependencies"`
Requirements []NodeID `json:"requirements"`
HolderState *BaseLockHolderState `json:"holder_state"`
} }
func (state * BaseLockableState) MarshalJSON() ([]byte, error) { func (state * BaseLockableState) MarshalJSON() ([]byte, error) {
@ -48,34 +83,18 @@ func (state * BaseLockableState) MarshalJSON() ([]byte, error) {
dependency_ids[i] = dependency.ID() dependency_ids[i] = dependency.ID()
} }
delegations := map[NodeID]*NodeID{}
for resource_id, node := range(state.delegation_map) {
if node == nil {
delegations[resource_id] = nil
} else {
str := node.ID()
delegations[resource_id] = &str
}
}
var owner_id *NodeID = nil var owner_id *NodeID = nil
if state.owner != nil { if state.owner != nil {
new_str := state.owner.ID() new_str := state.owner.ID()
owner_id = &new_str owner_id = &new_str
} }
return json.Marshal(&struct{ return json.Marshal(&BaseLockableStateJSON{
Name string `json:"name"`
Owner *NodeID `json:"owner"`
Dependencies []NodeID `json:"dependencies"`
Requirements []NodeID `json:"requirements"`
Delegations map[NodeID]*NodeID `json:"delegations"`
}{
Name: state.name, Name: state.name,
Owner: owner_id, Owner: owner_id,
Dependencies: dependency_ids, Dependencies: dependency_ids,
Requirements: requirement_ids, Requirements: requirement_ids,
Delegations: delegations, HolderState: &state.BaseLockHolderState,
}) })
} }
@ -85,7 +104,7 @@ func (state * BaseLockableState) Name() string {
// Locks cannot be passed between base lockables, so the answer to // Locks cannot be passed between base lockables, so the answer to
// "who used to own this lock held by a base lockable" is always "nobody" // "who used to own this lock held by a base lockable" is always "nobody"
func (state * BaseLockableState) ReturnLock(resource_id NodeID) GraphNode { func (state * BaseLockHolderState) ReturnLock(resource_id NodeID) GraphNode {
node, exists := state.delegation_map[resource_id] node, exists := state.delegation_map[resource_id]
if exists == false { if exists == false {
panic("Attempted to take a get the original lock holder of a resource we don't own") panic("Attempted to take a get the original lock holder of a resource we don't own")
@ -95,7 +114,7 @@ func (state * BaseLockableState) ReturnLock(resource_id NodeID) GraphNode {
} }
// Nothing can take a lock from a base lockable either // Nothing can take a lock from a base lockable either
func (state * BaseLockableState) AllowedToTakeLock(node_id NodeID, resource_id NodeID) bool { func (state * BaseLockHolderState) AllowedToTakeLock(node_id NodeID, resource_id NodeID) bool {
_, exists := state.delegation_map[resource_id] _, exists := state.delegation_map[resource_id]
if exists == false { if exists == false {
panic ("Trying to give away lock we don't own") panic ("Trying to give away lock we don't own")
@ -103,7 +122,7 @@ func (state * BaseLockableState) AllowedToTakeLock(node_id NodeID, resource_id N
return false return false
} }
func (state * BaseLockableState) RecordLockHolder(resource_id NodeID, lock_holder GraphNode) { func (state * BaseLockHolderState) RecordLockHolder(resource_id NodeID, lock_holder GraphNode) {
_, exists := state.delegation_map[resource_id] _, exists := state.delegation_map[resource_id]
if exists == true { if exists == true {
panic("Attempted to lock a resource we're already holding(lock cycle)") panic("Attempted to lock a resource we're already holding(lock cycle)")
@ -143,13 +162,19 @@ func (state * BaseLockableState) AddDependency(dependency Lockable) {
state.dependencies = append(state.dependencies, dependency) state.dependencies = append(state.dependencies, dependency)
} }
func NewLockHolderState() BaseLockHolderState {
return BaseLockHolderState{
delegation_map: map[NodeID]GraphNode{},
}
}
func NewLockableState(name string) BaseLockableState { func NewLockableState(name string) BaseLockableState {
return BaseLockableState{ return BaseLockableState{
BaseLockHolderState: NewLockHolderState(),
name: name, name: name,
owner: nil, owner: nil,
requirements: []Lockable{}, requirements: []Lockable{},
dependencies: []Lockable{}, dependencies: []Lockable{},
delegation_map: map[NodeID]GraphNode{},
} }
} }

@ -84,6 +84,12 @@ type BaseThreadState struct {
info_type reflect.Type info_type reflect.Type
} }
type BaseThreadStateJSON struct {
Parent *NodeID `json:"parent"`
Children map[NodeID]interface{} `json:"children"`
LockableState *BaseLockableState `json:"lockable_state"`
}
func (state * BaseThreadState) MarshalJSON() ([]byte, error) { func (state * BaseThreadState) MarshalJSON() ([]byte, error) {
children := map[NodeID]interface{}{} children := map[NodeID]interface{}{}
for _, child := range(state.children) { for _, child := range(state.children) {
@ -96,35 +102,10 @@ func (state * BaseThreadState) MarshalJSON() ([]byte, error) {
parent_id = &new_str parent_id = &new_str
} }
requirements := make([]NodeID, len(state.requirements)) return json.Marshal(&BaseThreadStateJSON{
for i, requirement := range(state.requirements) {
requirements[i] = requirement.ID()
}
dependencies := make([]NodeID, len(state.dependencies))
for i, dependency := range(state.dependencies) {
dependencies[i] = dependency.ID()
}
delegations := map[NodeID]NodeID{}
for lockable_id, node := range(state.delegation_map) {
delegations[lockable_id] = node.ID()
}
return json.Marshal(&struct{
Name string `json:"name"`
Parent *NodeID `json:"parent"`
Children map[NodeID]interface{} `json:"children"`
Dependencies []NodeID `json:"dependencies"`
Requirements []NodeID `json:"requirements"`
Delegations map[NodeID]NodeID `json:"delegations"`
}{
Name: state.Name(),
Parent: parent_id, Parent: parent_id,
Children: children, Children: children,
Dependencies: dependencies, LockableState: &state.BaseLockableState,
Requirements: requirements,
Delegations: delegations,
}) })
} }