@@ -20,11 +20,9 @@ package dag
20
20
21
21
import (
22
22
"errors"
23
- "math/rand"
24
23
"sync"
25
- "time"
26
24
27
- cmap "github.com/orcaman/concurrent-map/v2 "
25
+ "go.uber.org/atomic "
28
26
29
27
"d7y.io/dragonfly/v2/pkg/container/set"
30
28
)
33
31
// ErrVertexNotFound represents vertex not found.
34
32
ErrVertexNotFound = errors .New ("vertex not found" )
35
33
34
+ // ErrVertexInvalid represents vertex invalid.
35
+ ErrVertexInvalid = errors .New ("vertex invalid" )
36
+
36
37
// ErrVertexAlreadyExists represents vertex already exists.
37
38
ErrVertexAlreadyExists = errors .New ("vertex already exists" )
38
39
@@ -63,17 +64,14 @@ type DAG[T comparable] interface {
63
64
// GetRandomVertices returns random map of vertices.
64
65
GetRandomVertices (n uint ) []* Vertex [T ]
65
66
66
- // GetVertexKeys returns keys of vertices.
67
- GetVertexKeys () []string
68
-
69
67
// GetSourceVertices returns source vertices.
70
68
GetSourceVertices () []* Vertex [T ]
71
69
72
70
// GetSinkVertices returns sink vertices.
73
71
GetSinkVertices () []* Vertex [T ]
74
72
75
73
// VertexCount returns count of vertices.
76
- VertexCount () int
74
+ VertexCount () uint64
77
75
78
76
// AddEdge adds edge between two vertices.
79
77
AddEdge (fromVertexID , toVertexID string ) error
@@ -93,14 +91,17 @@ type DAG[T comparable] interface {
93
91
94
92
// dag provides directed acyclic graph function.
95
93
type dag [T comparable ] struct {
94
+ vertices * sync.Map
95
+ count * atomic.Uint64
96
96
mu sync.RWMutex
97
- vertices cmap.ConcurrentMap [string , * Vertex [T ]]
98
97
}
99
98
100
99
// New returns a new DAG interface.
101
100
func NewDAG [T comparable ]() DAG [T ] {
102
101
return & dag [T ]{
103
- vertices : cmap .New [* Vertex [T ]](),
102
+ vertices : & sync.Map {},
103
+ count : atomic .NewUint64 (0 ),
104
+ mu : sync.RWMutex {},
104
105
}
105
106
}
106
107
@@ -109,11 +110,11 @@ func (d *dag[T]) AddVertex(id string, value T) error {
109
110
d .mu .Lock ()
110
111
defer d .mu .Unlock ()
111
112
112
- if _ , ok := d .vertices .Get (id ); ok {
113
+ if _ , loaded := d .vertices .LoadOrStore (id , NewVertex ( id , value )); loaded {
113
114
return ErrVertexAlreadyExists
114
115
}
115
116
116
- d .vertices . Set ( id , NewVertex ( id , value ) )
117
+ d .count . Inc ( )
117
118
return nil
118
119
}
119
120
@@ -122,7 +123,12 @@ func (d *dag[T]) DeleteVertex(id string) {
122
123
d .mu .Lock ()
123
124
defer d .mu .Unlock ()
124
125
125
- vertex , ok := d .vertices .Get (id )
126
+ rawVertex , loaded := d .vertices .Load (id )
127
+ if ! loaded {
128
+ return
129
+ }
130
+
131
+ vertex , ok := rawVertex .(* Vertex [T ])
126
132
if ! ok {
127
133
return
128
134
}
@@ -136,55 +142,75 @@ func (d *dag[T]) DeleteVertex(id string) {
136
142
continue
137
143
}
138
144
139
- d .vertices .Remove (id )
145
+ d .vertices .Delete (id )
146
+ d .count .Dec ()
140
147
}
141
148
142
149
// GetVertex gets vertex from graph.
143
150
func (d * dag [T ]) GetVertex (id string ) (* Vertex [T ], error ) {
144
- vertex , ok := d .vertices .Get (id )
145
- if ! ok {
151
+ rawVertex , loaded := d .vertices .Load (id )
152
+ if ! loaded {
146
153
return nil , ErrVertexNotFound
147
154
}
148
155
156
+ vertex , ok := rawVertex .(* Vertex [T ])
157
+ if ! ok {
158
+ return nil , ErrVertexInvalid
159
+ }
160
+
149
161
return vertex , nil
150
162
}
151
163
152
164
// GetVertices returns map of vertices.
153
165
func (d * dag [T ]) GetVertices () map [string ]* Vertex [T ] {
154
- return d .vertices .Items ()
166
+ d .mu .RLock ()
167
+ defer d .mu .RUnlock ()
168
+
169
+ vertices := make (map [string ]* Vertex [T ], d .count .Load ())
170
+ d .vertices .Range (func (key , value interface {}) bool {
171
+ vertex , ok := value .(* Vertex [T ])
172
+ if ! ok {
173
+ return true
174
+ }
175
+
176
+ id , ok := key .(string )
177
+ if ! ok {
178
+ return true
179
+ }
180
+
181
+ vertices [id ] = vertex
182
+ return true
183
+ })
184
+
185
+ return vertices
155
186
}
156
187
157
188
// GetRandomVertices returns random map of vertices.
158
189
func (d * dag [T ]) GetRandomVertices (n uint ) []* Vertex [T ] {
159
190
d .mu .RLock ()
160
191
defer d .mu .RUnlock ()
161
192
162
- keys := d .GetVertexKeys ()
163
- if int (n ) >= len (keys ) {
164
- n = uint (len (keys ))
193
+ if n == 0 {
194
+ return nil
165
195
}
166
196
167
- r := rand .New (rand .NewSource (time .Now ().UnixNano ()))
168
- permutation := r .Perm (len (keys ))[:n ]
169
197
randomVertices := make ([]* Vertex [T ], 0 , n )
170
- for _ , v := range permutation {
171
- key := keys [ v ]
172
- if vertex , err := d . GetVertex ( key ); err == nil {
173
- randomVertices = append ( randomVertices , vertex )
198
+ d . vertices . Range ( func ( key , value interface {}) bool {
199
+ vertex , ok := value .( * Vertex [ T ])
200
+ if ! ok {
201
+ return true
174
202
}
175
- }
176
203
177
- return randomVertices
178
- }
204
+ randomVertices = append (randomVertices , vertex )
205
+ return uint (len (randomVertices )) < n
206
+ })
179
207
180
- // GetVertexKeys returns keys of vertices.
181
- func (d * dag [T ]) GetVertexKeys () []string {
182
- return d .vertices .Keys ()
208
+ return randomVertices
183
209
}
184
210
185
211
// VertexCount returns count of vertices.
186
- func (d * dag [T ]) VertexCount () int {
187
- return d .vertices . Count ()
212
+ func (d * dag [T ]) VertexCount () uint64 {
213
+ return d .count . Load ()
188
214
}
189
215
190
216
// AddEdge adds edge between two vertices.
@@ -196,14 +222,14 @@ func (d *dag[T]) AddEdge(fromVertexID, toVertexID string) error {
196
222
return ErrCycleBetweenVertices
197
223
}
198
224
199
- fromVertex , ok := d .vertices . Get (fromVertexID )
200
- if ! ok {
201
- return ErrVertexNotFound
225
+ fromVertex , err := d .GetVertex (fromVertexID )
226
+ if err != nil {
227
+ return err
202
228
}
203
229
204
- toVertex , ok := d .vertices . Get (toVertexID )
205
- if ! ok {
206
- return ErrVertexNotFound
230
+ toVertex , err := d .GetVertex (toVertexID )
231
+ if err != nil {
232
+ return err
207
233
}
208
234
209
235
for _ , child := range fromVertex .Children .Values () {
@@ -232,14 +258,14 @@ func (d *dag[T]) DeleteEdge(fromVertexID, toVertexID string) error {
232
258
d .mu .Lock ()
233
259
defer d .mu .Unlock ()
234
260
235
- fromVertex , ok := d .vertices . Get (fromVertexID )
236
- if ! ok {
237
- return ErrVertexNotFound
261
+ fromVertex , err := d .GetVertex (fromVertexID )
262
+ if err != nil {
263
+ return err
238
264
}
239
265
240
- toVertex , ok := d .vertices . Get (toVertexID )
241
- if ! ok {
242
- return ErrVertexNotFound
266
+ toVertex , err := d .GetVertex (toVertexID )
267
+ if err != nil {
268
+ return err
243
269
}
244
270
245
271
fromVertex .Children .Delete (toVertex )
@@ -256,12 +282,12 @@ func (d *dag[T]) CanAddEdge(fromVertexID, toVertexID string) bool {
256
282
return false
257
283
}
258
284
259
- fromVertex , ok := d .vertices . Get (fromVertexID )
260
- if ! ok {
285
+ fromVertex , err := d .GetVertex (fromVertexID )
286
+ if err != nil {
261
287
return false
262
288
}
263
289
264
- if _ , ok := d .vertices . Get (toVertexID ); ! ok {
290
+ if _ , err := d .GetVertex (toVertexID ); err != nil {
265
291
return false
266
292
}
267
293
@@ -283,9 +309,9 @@ func (d *dag[T]) DeleteVertexInEdges(id string) error {
283
309
d .mu .Lock ()
284
310
defer d .mu .Unlock ()
285
311
286
- vertex , ok := d .vertices . Get (id )
287
- if ! ok {
288
- return ErrVertexNotFound
312
+ vertex , err := d .GetVertex (id )
313
+ if err != nil {
314
+ return err
289
315
}
290
316
291
317
for _ , parent := range vertex .Parents .Values () {
@@ -301,9 +327,9 @@ func (d *dag[T]) DeleteVertexOutEdges(id string) error {
301
327
d .mu .Lock ()
302
328
defer d .mu .Unlock ()
303
329
304
- vertex , ok := d .vertices . Get (id )
305
- if ! ok {
306
- return ErrVertexNotFound
330
+ vertex , err := d .GetVertex (id )
331
+ if err != nil {
332
+ return err
307
333
}
308
334
309
335
for _ , child := range vertex .Children .Values () {
@@ -320,7 +346,7 @@ func (d *dag[T]) GetSourceVertices() []*Vertex[T] {
320
346
defer d .mu .RUnlock ()
321
347
322
348
var sourceVertices []* Vertex [T ]
323
- for _ , vertex := range d .vertices . Items () {
349
+ for _ , vertex := range d .GetVertices () {
324
350
if vertex .InDegree () == 0 {
325
351
sourceVertices = append (sourceVertices , vertex )
326
352
}
@@ -335,7 +361,7 @@ func (d *dag[T]) GetSinkVertices() []*Vertex[T] {
335
361
defer d .mu .RUnlock ()
336
362
337
363
var sinkVertices []* Vertex [T ]
338
- for _ , vertex := range d .vertices . Items () {
364
+ for _ , vertex := range d .GetVertices () {
339
365
if vertex .OutDegree () == 0 {
340
366
sinkVertices = append (sinkVertices , vertex )
341
367
}
@@ -354,8 +380,8 @@ func (d *dag[T]) depthFirstSearch(fromVertexID, toVertexID string) bool {
354
380
355
381
// search finds successors of vertex.
356
382
func (d * dag [T ]) search (vertexID string , successors map [string ]struct {}) {
357
- vertex , ok := d .vertices . Get (vertexID )
358
- if ! ok {
383
+ vertex , err := d .GetVertex (vertexID )
384
+ if err != nil {
359
385
return
360
386
}
361
387
0 commit comments