Remove sync.Once from dag.Graph

dag.Graph is used as a value, but contains a sync data structure. This
prevents copying the value, and is needed if one wants to upgrade a Graph
to an AcyclicGraph.

The sync.Once only guards the init() method, which can be guarded
internally with nil checks on the fields. The init method could be
removed entirely with a proper constructor later on of we so choose.
This commit is contained in:
James Bardin 2016-11-10 18:05:30 -05:00
parent 916d3522b1
commit f37b2fafed
2 changed files with 18 additions and 12 deletions

View File

@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"io" "io"
"sort" "sort"
"sync"
) )
// Graph is used to represent a dependency graph. // Graph is used to represent a dependency graph.
@ -15,7 +14,6 @@ type Graph struct {
edges *Set edges *Set
downEdges map[interface{}]*Set downEdges map[interface{}]*Set
upEdges map[interface{}]*Set upEdges map[interface{}]*Set
once sync.Once
// JSON encoder for recording debug information // JSON encoder for recording debug information
debug *encoder debug *encoder
@ -108,7 +106,7 @@ func (g *Graph) HasEdge(e Edge) bool {
// Add adds a vertex to the graph. This is safe to call multiple time with // Add adds a vertex to the graph. This is safe to call multiple time with
// the same Vertex. // the same Vertex.
func (g *Graph) Add(v Vertex) Vertex { func (g *Graph) Add(v Vertex) Vertex {
g.once.Do(g.init) g.init()
g.vertices.Add(v) g.vertices.Add(v)
g.debug.Add(v) g.debug.Add(v)
return v return v
@ -165,7 +163,7 @@ func (g *Graph) Replace(original, replacement Vertex) bool {
// RemoveEdge removes an edge from the graph. // RemoveEdge removes an edge from the graph.
func (g *Graph) RemoveEdge(edge Edge) { func (g *Graph) RemoveEdge(edge Edge) {
g.once.Do(g.init) g.init()
g.debug.RemoveEdge(edge) g.debug.RemoveEdge(edge)
// Delete the edge from the set // Delete the edge from the set
@ -182,13 +180,13 @@ func (g *Graph) RemoveEdge(edge Edge) {
// DownEdges returns the outward edges from the source Vertex v. // DownEdges returns the outward edges from the source Vertex v.
func (g *Graph) DownEdges(v Vertex) *Set { func (g *Graph) DownEdges(v Vertex) *Set {
g.once.Do(g.init) g.init()
return g.downEdges[hashcode(v)] return g.downEdges[hashcode(v)]
} }
// UpEdges returns the inward edges to the destination Vertex v. // UpEdges returns the inward edges to the destination Vertex v.
func (g *Graph) UpEdges(v Vertex) *Set { func (g *Graph) UpEdges(v Vertex) *Set {
g.once.Do(g.init) g.init()
return g.upEdges[hashcode(v)] return g.upEdges[hashcode(v)]
} }
@ -197,7 +195,7 @@ func (g *Graph) UpEdges(v Vertex) *Set {
// verified through pointer equality of the vertices, not through the // verified through pointer equality of the vertices, not through the
// value of the edge itself. // value of the edge itself.
func (g *Graph) Connect(edge Edge) { func (g *Graph) Connect(edge Edge) {
g.once.Do(g.init) g.init()
g.debug.Connect(edge) g.debug.Connect(edge)
source := edge.Source() source := edge.Source()
@ -312,10 +310,18 @@ func (g *Graph) String() string {
} }
func (g *Graph) init() { func (g *Graph) init() {
g.vertices = new(Set) if g.vertices == nil {
g.edges = new(Set) g.vertices = new(Set)
g.downEdges = make(map[interface{}]*Set) }
g.upEdges = make(map[interface{}]*Set) if g.edges == nil {
g.edges = new(Set)
}
if g.downEdges == nil {
g.downEdges = make(map[interface{}]*Set)
}
if g.upEdges == nil {
g.upEdges = make(map[interface{}]*Set)
}
} }
// Dot returns a dot-formatted representation of the Graph. // Dot returns a dot-formatted representation of the Graph.

View File

@ -175,7 +175,7 @@ func TestGraphJSON_annotations(t *testing.T) {
} }
found3 = true found3 = true
default: default:
t.Fatalf("unexpected annotation:", va) t.Fatalf("unexpected annotation: %#v", va)
} }
case "EdgeAnnotation": case "EdgeAnnotation":
ea := &edgeAnnotation{} ea := &edgeAnnotation{}