This repository has been archived by the owner on Sep 12, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
queue.go
147 lines (113 loc) · 2.32 KB
/
queue.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
package main
import (
"sync"
)
type Queue struct {
m map[uint16]*Head
sync.Cond
*sync.RWMutex
size uint32
smallest uint16
count uint8
}
type Head struct {
*Node
count uint32
}
type Node struct {
*Board
next *Node
}
type Map struct {
m map[uint32]uint16
*sync.RWMutex
}
func NewMap() Map {
m := Map{}
m.m = make(map[uint32]uint16)
m.RWMutex = new(sync.RWMutex)
return m
}
func (m *Map) set(key uint32, f uint16) {
m.Lock()
defer m.Unlock()
m.m[key] = f
}
func (m *Map) get(key uint32) (uint16, bool) {
m.RLock()
defer m.RUnlock()
val, ok := m.m[key]
return val, ok
}
func (m *Map) del(key uint32) {
m.Lock()
defer m.Unlock()
delete(m.m, key)
}
func (m *Map) len() int {
m.RLock()
defer m.RUnlock()
return len(m.m)
}
func NewQueue(initial *Board) Queue {
queue := Queue{size: 1}
queue.m = make(map[uint16]*Head)
queue.m[initial.f] = &Head{Node: &Node{Board: initial}, count: 1}
queue.RWMutex = new(sync.RWMutex)
queue.Cond.L = queue.RWMutex
return queue
}
func (q *Queue) push(board *Board) {
q.Lock()
defer q.Unlock()
defer q.Signal()
q.size++
head := q.m[board.f]
if head == nil {
head = &Head{}
q.m[board.f] = head
}
node := Node{Board: board, next: head.Node}
head.Node = &node
head.count++
if q.smallest == 0 || board.f < q.smallest {
q.smallest = board.f
}
}
func (q *Queue) pop() *Board {
q.Lock()
defer q.Unlock()
for len(q.m) == 0 {
if q.count >= uint8(threads)-1 { // Deadlock if all threads are waiting here
return nil
}
q.count++
q.Wait()
q.count--
}
q.size--
head := q.m[q.smallest]
board := head.Board
if head.next != nil {
head.Node = head.next
} else { // We need to find the next best priority
delete(q.m, q.smallest)
if len(q.m) == 0 {
q.smallest = 0
return board
}
for { // We will never hit an endless loop
q.smallest++
_, ok := q.m[q.smallest]
if ok {
return board
}
}
}
return board
}
func (q *Queue) len() uint32 {
q.RLock()
defer q.RUnlock()
return q.size
}