Updated listener to have explicit unregister. Cleanup of initializers. More stuff I don't remember.

graph-rework
noah metz 2023-06-01 22:42:47 -06:00
parent d7b13de82f
commit 55d977e9b8
8 changed files with 234 additions and 250 deletions

@ -6,19 +6,18 @@ import (
"errors"
"reflect"
"sort"
"sync"
)
// Update the events listeners, and notify the parent to do the same
func (event * BaseEvent) Update(reason string) error {
log.Printf("UPDATE BaseEvent %s: %s", event.Name(), reason)
err := event.UpdateListeners(reason)
if err != nil {
return err
}
func (event * BaseEvent) Update(signal GraphSignal) error {
log.Printf("UPDATE BaseEvent %s: %+v", event.Name(), signal)
event.signal <- signal
event.BaseNode.Update(signal)
if event.parent != nil{
return event.parent.Update("update parent")
return event.parent.Update(signal)
}
return nil
}
@ -58,7 +57,6 @@ type Event interface {
FindChild(id string) Event
Run() error
Abort() error
Signal(action string) error
LockResources() error
Finish() error
}
@ -76,32 +74,16 @@ type BaseEvent struct {
children []Event
child_info map[Event]EventInfo
actions map[string]func() (string, error)
handlers map[string]func() (string, error)
parent Event
signal chan string
abort chan string
}
func (queue * EventQueue) Abort() error {
for _, event := range(queue.children) {
event.Abort()
}
for _, c := range(queue.resource_aborts) {
c <- "event abort"
}
queue.signal <- "abort"
return nil
}
func (event * BaseEvent) Abort() error {
for _, event := range(event.children) {
event.Abort()
}
event.signal <- "abort"
return nil
}
func (event * BaseEvent) Signal(action string) error {
event.signal <- action
event.signal <- NewSignal(event, "abort")
return nil
}
@ -141,11 +123,17 @@ func (event * BaseEvent) Finish() error {
}
resource.NotifyUnlocked()
}
err := event.DoneResource().Unlock(event)
if err != nil {
return err
}
return event.DoneResource().NotifyUnlocked()
err = event.DoneResource().NotifyUnlocked()
event.Update(NewSignal(event, "event_done"))
return err
}
func (event * BaseEvent) LockDone() {
@ -153,11 +141,11 @@ func (event * BaseEvent) LockDone() {
}
func (event * BaseEvent) Run() error {
log.Printf("EVENT_RUN: %s", event.Name())
next_action := "start"
var err error = nil
for next_action != "" {
// Check if the edge exists
cur_action := next_action
action, exists := event.actions[next_action]
if exists == false {
error_str := fmt.Sprintf("%s is not a valid action", next_action)
@ -165,37 +153,17 @@ func (event * BaseEvent) Run() error {
}
// Run the edge function
update_str := fmt.Sprintf("EVENT_ACTION: %s", next_action)
log.Printf(update_str)
next_action, err = action()
if err != nil {
return err
} else if next_action == "wait" {
// Wait for an external signal to set the next_action
signal := <- event.signal
if signal == "abort" {
return errors.New("State Machine aborted by signal")
} else {
next_action = signal
}
} else {
// next_action is already set correctly
}
// Update the event after running the edge
update_str := fmt.Sprintf("ACTION %s: NEXT %s", cur_action, next_action)
event.Update(update_str)
}
return nil
}
// EventQueue is a basic event that can have children.
// On start, it attempts to start it's children from the highest 'priority'
type EventQueue struct {
BaseEvent
resource_aborts map[string]chan string
resource_lock sync.Mutex
}
func NewBaseEvent(name string, description string, required_resources []Resource) (BaseEvent) {
done_resource := NewResource("event_done", "signal that event is done", []Resource{})
event := BaseEvent{
@ -203,7 +171,8 @@ func NewBaseEvent(name string, description string, required_resources []Resource
name: name,
description: description,
id: randid(),
listeners: []chan string{},
signal: make(chan GraphSignal, 10),
listeners: map[chan GraphSignal] chan GraphSignal{},
},
parent: nil,
children: []Event{},
@ -211,10 +180,26 @@ func NewBaseEvent(name string, description string, required_resources []Resource
done_resource: done_resource,
required_resources: required_resources,
actions: map[string]func()(string, error){},
signal: make(chan string, 10),
handlers: map[string]func()(string, error){},
abort: make(chan string, 1),
}
event.actions["wait"] = func() (string, error) {
signal := <- event.signal
if signal.Type() == "abort" {
return "", errors.New("State machine aborted by signal")
} else if signal.Type() == "do_action" {
return signal.Description(), nil
} else {
signal_fn, exists := event.handlers[signal.Type()]
if exists == true {
return signal_fn()
}
}
// ignore signals other than "abort" and "do_action"
return "wait", nil
}
return event
}
@ -232,10 +217,26 @@ func NewEvent(name string, description string, required_resources []Resource) (*
return event_ptr
}
// EventQueue is a basic event that can have children.
// On start, it attempts to start it's children from the highest 'priority'
type EventQueue struct {
BaseEvent
listened_resources map[string]Resource
}
func (queue * EventQueue) Finish() error {
for _, resource := range(queue.listened_resources) {
resource.UnregisterChannel(queue.signal)
}
return queue.BaseEvent.Finish()
}
func NewEventQueue(name string, description string, required_resources []Resource) (* EventQueue) {
queue := &EventQueue{
BaseEvent: NewBaseEvent(name, description, []Resource{}),
resource_aborts: map[string]chan string{},
listened_resources: map[string]Resource{},
}
// Need to lock it with th BaseEvent since Unlock is implemented on the BaseEvent
@ -257,42 +258,11 @@ func NewEventQueue(name string, description string, required_resources []Resourc
sort.SliceStable(copied_events, less)
wait := false
needed_resources := map[string]Resource{}
for _, event := range(copied_events) {
// Update the resource_chans
// make sure all the required resources are registered to update the event
for _, resource := range(event.RequiredResources()) {
queue.resource_lock.Lock()
_, exists := queue.resource_aborts[resource.ID()]
if exists == false {
log.Printf("RESOURCE_LISTENER_START: %s", resource.Name())
abort := make(chan string, 1)
queue.resource_aborts[resource.ID()] = abort
go func(queue *EventQueue, resource Resource, abort chan string) {
log.Printf("RESOURCE_LISTENER_GOROUTINE: %s", resource.Name())
resource_chan := resource.UpdateChannel()
for true {
select {
case <- abort:
queue.resource_lock.Lock()
delete(queue.resource_aborts, resource.ID())
queue.resource_lock.Unlock()
log.Printf("RESORCE_LISTENER_ABORT: %s", resource.Name())
break
case msg, ok := <- resource_chan:
if ok == false {
queue.resource_lock.Lock()
delete(queue.resource_aborts, resource.ID())
queue.resource_lock.Unlock()
log.Printf("RESOURCE_LISTENER_CLOSED: %s : %s", resource.Name(), msg)
break
}
log.Printf("RESOURCE_LISTENER_UPDATED: %s : %s", resource.Name(), msg)
queue.signal <- "resource_update"
}
}
log.Printf("RESOURCE_LISTENER_DYING: %s", resource.Name())
}(queue, resource, abort)
}
queue.resource_lock.Unlock()
needed_resources[resource.ID()] = resource
}
info := queue.ChildInfo(event).(*EventQueueInfo)
@ -313,7 +283,6 @@ func NewEventQueue(name string, description string, required_resources []Resourc
}
info.state = "done"
event.Finish()
queue.Signal("event_done")
}(event, info, queue)
}
} else if info.state == "running" {
@ -321,6 +290,11 @@ func NewEventQueue(name string, description string, required_resources []Resourc
}
}
for _, resource := range(needed_resources) {
queue.listened_resources[resource.ID()] = resource
resource.RegisterChannel(queue.signal)
}
if wait == true {
return "wait", nil
} else {
@ -340,6 +314,14 @@ func NewEventQueue(name string, description string, required_resources []Resourc
return "queue_event", nil
}
queue.handlers["lock_change"] = func() (string, error) {
return "queue_event", nil
}
queue.handlers["event_done"] = func() (string, error) {
return "queue_event", nil
}
return queue
}
@ -410,7 +392,7 @@ func (event * BaseEvent) addChild(child Event, info EventInfo) error {
event.children = append(event.children, child)
event.child_info[child] = info
event.Update("child added")
event.Update(NewSignal(event, "child_added"))
return nil
}

@ -1,7 +1,6 @@
package main
import (
"errors"
"log"
"sync"
"github.com/google/uuid"
@ -13,14 +12,47 @@ func randid() string{
return uuid_str
}
type GraphSignal interface {
Source() GraphNode
Type() string
Description() string
}
type BaseSignal struct {
source GraphNode
signal_type string
description string
}
func (signal BaseSignal) Source() GraphNode {
return signal.source
}
func (signal BaseSignal) Type() string {
return signal.signal_type
}
func (signal BaseSignal) Description() string {
return signal.description
}
func NewSignal(source GraphNode, signal_type string) (BaseSignal) {
signal := BaseSignal{
source: source,
signal_type: signal_type,
}
return signal
}
// GraphNode is the interface common to both DAG nodes and Event tree nodes
type GraphNode interface {
Name() string
Description() string
ID() string
UpdateListeners(info string) error
UpdateChannel() chan string
Update(reason string) error
Update(update GraphSignal) error
RegisterChannel(listener chan GraphSignal)
UnregisterChannel(listener chan GraphSignal)
UpdateChannel() chan GraphSignal
}
// BaseNode is the most basic implementation of the GraphNode interface
@ -29,8 +61,9 @@ type BaseNode struct {
name string
description string
id string
listeners []chan string
signal chan GraphSignal
listeners_lock sync.Mutex
listeners map[chan GraphSignal]chan GraphSignal
}
func (node * BaseNode) Name() string {
@ -47,58 +80,47 @@ func (node * BaseNode) ID() string {
// Create a new listener channel for the node, add it to the nodes listener list, and return the new channel
const listener_buffer = 10
func (node * BaseNode) UpdateChannel() chan string{
new_listener := make(chan string, listener_buffer)
node.listeners_lock.Lock()
node.listeners = append(node.listeners, new_listener)
node.listeners_lock.Unlock()
func (node * BaseNode) UpdateChannel() chan GraphSignal {
new_listener := make(chan GraphSignal, listener_buffer)
node.RegisterChannel(new_listener)
return new_listener
}
// Send the update to listener channels
func (node * BaseNode) UpdateListeners(info string) error {
closed_listeners := []int{}
listeners_closed := false
// Send each listener nil to signal it to check for new content
// if the first attempt to send it fails close the listener
func (node * BaseNode) RegisterChannel(listener chan GraphSignal) {
node.listeners_lock.Lock()
for i, listener := range node.listeners {
select {
case listener <- info:
default:
close(listener)
closed_listeners = append(closed_listeners, i)
listeners_closed = true
}
_, exists := node.listeners[listener]
if exists == false {
node.listeners[listener] = listener
}
node.listeners_lock.Unlock()
}
// If any listeners have been closed, loop over the listeners
// Add listeners to the "remaining" list if i insn't in closed_listeners
if listeners_closed == true {
remaining_listeners := []chan string{}
for i, listener := range node.listeners {
listener_closed := false
for _, index := range closed_listeners {
if index == i {
listener_closed = true
break
}
}
if listener_closed == false {
remaining_listeners = append(remaining_listeners, listener)
}
}
node.listeners = remaining_listeners
func (node * BaseNode) UnregisterChannel(listener chan GraphSignal) {
node.listeners_lock.Lock()
_, exists := node.listeners[listener]
if exists == false {
panic("Attempting to unregister non-registered listener")
} else {
delete(node.listeners, listener)
}
node.listeners_lock.Unlock()
}
return nil
// Send the update to listener channels
func (node * BaseNode) UpdateListeners(update GraphSignal) {
node.listeners_lock.Lock()
for _, listener := range node.listeners {
log.Printf("UPDATE_LISTENER %s: %p", node.Name(), listener)
listener <- update
}
node.listeners_lock.Unlock()
}
// Basic implementation must be overwritten to do anything useful
func (node * BaseNode) Update(reason string) error {
log.Printf("UPDATE: BaseNode %s: %s", node.Name(), reason)
return errors.New("Cannot Update a BaseNode")
// Basic implementation that sends the signal to the nodes channel
func (node * BaseNode) Update(signal GraphSignal) error {
log.Printf("UPDATE: BaseNode %s: %+v", node.Name(), signal)
node.UpdateListeners(signal)
return nil
}

@ -2,7 +2,6 @@ package main
import (
"log"
"math/rand"
)
func fake_team(org string, id string, names []string) (*Team, []*Member) {
@ -26,10 +25,14 @@ func fake_data() * EventManager {
t6, m6 := fake_team("210", "X", []string{"toby"})
t7, m7 := fake_team("210", "Y", []string{"jennifer"})
t8, m8 := fake_team("210", "Z", []string{"emily"})
t9, m9 := fake_team("315", "W", []string{"bobby"})
t10, m10 := fake_team("315", "X", []string{"toby"})
t11, m11 := fake_team("315", "Y", []string{"jennifer"})
t12, m12 := fake_team("315", "Z", []string{"emily"})
t9, m9 := fake_team("666", "A", []string{"jimmy"})
t10, m10 := fake_team("666", "B", []string{"timmy"})
//t11, m11 := fake_team("666", "C", []string{"grace"})
//t12, m12 := fake_team("666", "D", []string{"jeremy"})
//t13, m13 := fake_team("315", "W", []string{"bobby"})
//t14, m14 := fake_team("315", "X", []string{"toby"})
//t15, m15 := fake_team("315", "Y", []string{"jennifer"})
//t16, m16 := fake_team("315", "Z", []string{"emily"})
teams = append(teams, t1)
teams = append(teams, t2)
@ -41,8 +44,12 @@ func fake_data() * EventManager {
teams = append(teams, t8)
teams = append(teams, t9)
teams = append(teams, t10)
teams = append(teams, t11)
teams = append(teams, t12)
//teams = append(teams, t11)
//teams = append(teams, t12)
//teams = append(teams, t13)
//teams = append(teams, t14)
//teams = append(teams, t15)
//teams = append(teams, t16)
resources = append(resources, m1[0])
resources = append(resources, m2[0])
@ -54,25 +61,22 @@ func fake_data() * EventManager {
resources = append(resources, m8[0])
resources = append(resources, m9[0])
resources = append(resources, m10[0])
resources = append(resources, m11[0])
resources = append(resources, m12[0])
alliances := []*Alliance{}
for i, team := range(teams){
for true {
idx := rand.Intn(len(teams))
if idx != i {
alliance := NewAlliance(team, teams[idx])
alliances = append(alliances, alliance)
break
}
}
}
//resources = append(resources, m11[0])
//resources = append(resources, m12[0])
//resources = append(resources, m13[0])
//resources = append(resources, m14[0])
//resources = append(resources, m15[0])
//resources = append(resources, m16[0])
arenas := []*Arena{}
arenas = append(arenas, NewVirtualArena("Arena 1"))
arenas = append(arenas, NewVirtualArena("Arena 2"))
arenas = append(arenas, NewVirtualArena("Arena 3"))
arenas = append(arenas, NewVirtualArena("Arena 4"))
arenas = append(arenas, NewVirtualArena("Arena 5"))
arenas = append(arenas, NewVirtualArena("Arena 6"))
arenas = append(arenas, NewVirtualArena("Arena 7"))
arenas = append(arenas, NewVirtualArena("Arena 8"))
for _, arena := range arenas {
resources = append(resources, arena)
@ -82,19 +86,27 @@ func fake_data() * EventManager {
resources = append(resources, team)
}
alliances := []*Alliance{}
for i, team := range(teams) {
for j, team2 := range(teams) {
if i != j {
alliance := NewAlliance(team, team2)
alliances = append(alliances, alliance)
}
}
}
for _, alliance := range alliances {
resources = append(resources, alliance)
}
root_event := NewEventQueue("root_event", "", []Resource{})
event_manager := NewEventManager(root_event, resources)
arena_idx := 0
for i := 0; i < len(alliances)*5; i++ {
alliance := alliances[i % len(alliances)]
for true {
idx := rand.Intn(len(alliances))
if idx != i {
alliance2 := alliances[idx]
// Generate 3 games for each team by picking 3 random teams
for i, alliance := range(alliances) {
for j, alliance2 := range(alliances) {
if j != i {
if alliance.Children()[0] == alliance2.Children()[0] || alliance.Children()[0] == alliance2.Children()[1] || alliance.Children()[1] == alliance2.Children()[0] || alliance.Children()[1] == alliance2.Children()[1] {
} else {
match := NewMatch(alliance, alliance2, arenas[arena_idx])
@ -108,7 +120,6 @@ func fake_data() * EventManager {
arena_idx = 0
}
}
break
}
}
}

@ -55,8 +55,10 @@ func (manager * EventManager) Run() error {
c <- nil
}
}(abort, aborts)
err := manager.root_event.LockResources()
if err != nil {
abort <- nil
return err
}

@ -9,7 +9,7 @@ import (
type graph_tester testing.T
const listner_timeout = 100 * time.Millisecond
func (t * graph_tester) CheckForValue(listener chan string, str string) {
func (t * graph_tester) CheckForValue(listener chan GraphSignal, str string) {
timeout := time.After(listner_timeout)
select {
case <- listener:
@ -19,7 +19,7 @@ func (t * graph_tester) CheckForValue(listener chan string, str string) {
}
}
func (t * graph_tester) CheckForNone(listener chan string, str string) {
func (t * graph_tester) CheckForNone(listener chan GraphSignal, str string) {
timeout := time.After(listner_timeout)
select {
case <- listener:
@ -99,21 +99,23 @@ func TestResourceUpdate(t * testing.T) {
r4_l := r4.UpdateChannel()
// Calling Update() on the parent with no other parents should only notify node listeners
r3.Update("test")
println("UPDATE_START")
r3.Update(NewSignal(nil, "test"))
println("UPDATE_DONE")
(*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r3")
(*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r3")
(*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r3")
(*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r3")
// Calling Update() on a child should notify listeners of the parent and child, but not siblings
r2.Update("test")
r2.Update(NewSignal(nil, "test"))
(*graph_tester)(t).CheckForNone(r1_l, "Update on r1 after updating r2")
(*graph_tester)(t).CheckForValue(r2_l, "No update on r2 after updating r2")
(*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r2")
(*graph_tester)(t).CheckForValue(r4_l, "No update on r4 after updating r2")
// Calling Update() on a child should notify listeners of the parent and child, but not siblings
r1.Update("test")
r1.Update(NewSignal(nil, "test"))
(*graph_tester)(t).CheckForValue(r1_l, "No update on r1 after updating r1")
(*graph_tester)(t).CheckForNone(r2_l, "Update on r2 after updating r1")
(*graph_tester)(t).CheckForValue(r3_l, "No update on r3 after updating r1")
@ -268,7 +270,7 @@ func TestAddToEventQueue(t * testing.T) {
}
func TestStartBaseEvent(t * testing.T) {
event_1 := NewEvent("1", "", []Resource{})
event_1 := NewEvent("TestStartBaseEvent event_1", "", []Resource{})
r := event_1.DoneResource()
manager := NewEventManager(event_1, []Resource{})
@ -331,7 +333,7 @@ func TestAbortEventQueue(t * testing.T) {
}
func TestStartEventQueue(t * testing.T) {
root_event := NewEventQueue("", "", []Resource{})
root_event := NewEventQueue("root_event", "", []Resource{})
r := root_event.DoneResource()
rel := root_event.UpdateChannel();
res_1 := NewResource("test_resource", "", []Resource{})

@ -9,15 +9,13 @@ import (
// Resources propagate update up to multiple parents, and not downwards
// (subscriber to team won't get update to alliance, but subscriber to alliance will get update to team)
func (resource * BaseResource) Update(reason string) error {
log.Printf("UPDATE BaseResource %s: %s", resource.Name(), reason)
err := resource.UpdateListeners(reason)
if err != nil {
return err
}
func (resource * BaseResource) Update(signal GraphSignal) error {
log.Printf("UPDATE BaseResource %s: %+v", resource.Name(), signal)
resource.BaseNode.Update(signal)
for _, parent := range resource.Parents() {
err := parent.Update("update parents")
err := parent.Update(signal)
if err != nil {
return err
}
@ -62,7 +60,7 @@ func (resource * BaseResource) Owner() Event {
}
func (resource * BaseResource) NotifyUnlocked() error {
err := resource.Update("finalize_unlock")
err := resource.Update(NewSignal(resource, "lock_change"))
if err != nil {
return err
}
@ -78,7 +76,7 @@ func (resource * BaseResource) NotifyUnlocked() error {
}
func (resource * BaseResource) NotifyLocked() error {
err := resource.Update("finalize_lock")
err := resource.Update(NewSignal(resource, "lock_change"))
if err != nil {
return err
}
@ -90,7 +88,7 @@ func (resource * BaseResource) NotifyLocked() error {
}
}
resource.lock_holder.Update("finalize_lock")
resource.lock_holder.Update(NewSignal(resource, "lock_change"))
return nil
}
@ -153,10 +151,6 @@ func (resource * BaseResource) Unlock(event Event) error {
}
resource.state_lock.Unlock()
/*if unlocked == true {
resource.Update("unlocking resource")
}*/
return err
}
@ -189,13 +183,13 @@ func (resource * BaseResource) AddParent(parent Resource) error {
return nil
}
func NewResource(name string, description string, children []Resource) * BaseResource {
resource := &BaseResource{
func NewBaseResource(name string, description string, children []Resource) BaseResource {
resource := BaseResource{
BaseNode: BaseNode{
name: name,
description: description,
id: randid(),
listeners: []chan string{},
listeners: map[chan GraphSignal]chan GraphSignal{},
},
parents: []Resource{},
children: children,
@ -203,3 +197,8 @@ func NewResource(name string, description string, children []Resource) * BaseRes
return resource
}
func NewResource(name string, description string, children []Resource) * BaseResource {
resource := NewBaseResource(name, description, children)
return &resource
}

@ -13,16 +13,7 @@ type Member struct {
func NewMember(name string) * Member {
member := &Member{
BaseResource: BaseResource{
BaseNode: BaseNode{
name: name,
description: "A Team Member",
id: randid(),
listeners: []chan string{},
},
parents: []Resource{},
children: []Resource{},
},
BaseResource: NewBaseResource(name, "A Team Member", []Resource{}),
}
return member
@ -47,22 +38,15 @@ func NewTeam(org string, team string, members []*Member) * Team {
name := fmt.Sprintf("%s%s", org, team)
description := fmt.Sprintf("Team %s", name)
resource := &Team{
BaseResource: BaseResource{
BaseNode: BaseNode{
name: name,
description: description,
id: randid(),
listeners: []chan string{},
},
parents: []Resource{},
children: make([]Resource, len(members)),
},
BaseResource: NewBaseResource(name, description, make([]Resource, len(members))),
Org: org,
Team: team,
}
for idx, member := range(members) {
resource.children[idx] = member
}
return resource
}
@ -75,16 +59,7 @@ func NewAlliance(team0 * Team, team1 * Team) * Alliance {
description := ""
resource := &Alliance{
BaseResource: BaseResource{
BaseNode: BaseNode{
name: name,
description: description,
id: randid(),
listeners: []chan string{},
},
parents: []Resource{},
children: []Resource{team0, team1},
},
BaseResource: NewBaseResource(name, description, []Resource{team0, team1}),
}
return resource
}
@ -103,16 +78,7 @@ type Arena struct {
func NewVirtualArena(name string) * Arena {
arena := &Arena{
BaseResource: BaseResource{
BaseNode: BaseNode{
name: name,
description: "A virtual vex arena",
id: randid(),
listeners: []chan string{},
},
parents: []Resource{},
children: []Resource{},
},
BaseResource: NewBaseResource(name, "A virtual vex arena", []Resource{}),
connected: false,
}
@ -128,28 +94,34 @@ func (arena * Arena) Lock(event Event) error {
return arena.lock(event)
}
func (arena * Arena) Update(signal GraphSignal) error {
log.Printf("UPDATE Arena %s: %+v", arena.Name(), signal)
arena.BaseResource.Update(signal)
if arena.connected == true {
arena.signal <- signal
}
return nil
}
func (arena * Arena) Connect(abort chan error) bool {
log.Printf("Connecting %s", arena.Name())
go func(arena * Arena, abort chan error) {
update_channel := arena.UpdateChannel()
owner := arena.Owner()
var owner_channel chan string = nil
if owner != nil {
owner_channel = owner.UpdateChannel()
}
arena.connected = true
update_str := fmt.Sprintf("VIRTUAL_ARENA connected: %s", arena.Name())
arena.Update(update_str)
signal := NewSignal(arena, "arena_connected")
signal.description = update_str
arena.Update(signal)
log.Printf("VIRTUAL_ARENA goroutine starting: %s", arena.Name())
for true {
select {
case <- abort:
log.Printf("Virtual arena %s aborting", arena.Name())
break
case update, ok := <- update_channel:
if !ok {
panic("own update_channel closed")
}
case update := <- arena.signal:
log.Printf("%s update: %s", arena.Name(), update)
new_owner := arena.Owner()
if new_owner != owner {
@ -168,17 +140,9 @@ func (arena * Arena) Connect(abort chan error) bool {
owner = new_owner
if owner != nil {
owner_channel = owner.UpdateChannel()
} else {
owner_channel = nil
}
}
case update, ok := <- owner_channel:
if !ok {
panic("owner update channel closed")
}
log.Printf("%s owner update: %s", arena.Name(), update)
log.Printf("owner: %s", owner.Name())
}
}
}(arena, abort)

@ -130,9 +130,11 @@ func TestNewMatch(t *testing.T) {
arena := NewVirtualArena(arena_name)
root_event := NewMatch(alliance_1, alliance_2, arena)
match := NewMatch(alliance_1, alliance_2, arena)
root_event := NewEventQueue("root_event", "", []Resource{})
event_manager := NewEventManager(root_event, []Resource{member_1, member_2, member_3, member_4, team_1, team_2, team_3, team_4, alliance_1, alliance_2, arena})
event_manager.AddEvent(root_event, match, NewEventQueueInfo(1))
go func() {
time.Sleep(time.Second * 2)
@ -140,7 +142,7 @@ func TestNewMatch(t *testing.T) {
}()
err := event_manager.Run()
if err == nil {
if err != nil {
t.Fatal(err)
}
}