├── .gitignore
├── 1.png
├── 2.png
├── cppgo.vcxproj
├── go.cpp
├── go.h
├── main.cpp
└── readme.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /Debug
2 | /Release
3 | /*.vcxproj
4 | /*.filters
5 | /*.user
--------------------------------------------------------------------------------
/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InsZVA/cppgo/ea84eee9fbd15e5562aba70f22bdc458e68d84f5/1.png
--------------------------------------------------------------------------------
/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/InsZVA/cppgo/ea84eee9fbd15e5562aba70f22bdc458e68d84f5/2.png
--------------------------------------------------------------------------------
/cppgo.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Debug
14 | x64
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {E848081F-3C25-4CD7-AE1F-5307C036318F}
23 | cppgo
24 | 8.1
25 |
26 |
27 |
28 | Application
29 | true
30 | v140
31 | MultiByte
32 |
33 |
34 | Application
35 | false
36 | v140
37 | true
38 | MultiByte
39 |
40 |
41 | Application
42 | true
43 | v140
44 | MultiByte
45 |
46 |
47 | Application
48 | false
49 | v140
50 | true
51 | MultiByte
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | Level3
75 | Disabled
76 | true
77 |
78 |
79 |
80 |
81 | Level3
82 | Disabled
83 | true
84 |
85 |
86 |
87 |
88 | Level3
89 | MaxSpeed
90 | true
91 | true
92 | true
93 |
94 |
95 | true
96 | true
97 |
98 |
99 |
100 |
101 | Level3
102 | MaxSpeed
103 | true
104 | true
105 | true
106 |
107 |
108 | true
109 | true
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------
/go.cpp:
--------------------------------------------------------------------------------
1 | #include "go.h"
2 |
3 | namespace go {
4 | volatile unsigned int nmspinning = 0;
5 | RWMutex nmspinning_lock;
6 | const unsigned int MAX_PROCS = 8;
7 | unsigned newP = 0;
8 | unsigned newM = 0;
9 |
10 | Queue
gfpqueue;
11 | Queue tqueue;
12 |
13 | std::vector gplist;
14 | //std::mutex gplist_mutex;
15 | //std::unique_lock gplist_lock(gplist_mutex);
16 | std::mutex gplist_lock;
17 |
18 | template void debugPrint(T t) {
19 | #ifdef DEBUG //Because the empty function will be optimized by compiler
20 | std::cout << t << std::endl;
21 | #endif
22 | }
23 |
24 | void addnmspinning() {
25 | nmspinning_lock.wLock();
26 | nmspinning++;
27 | nmspinning_lock.wUnlock();
28 | }
29 |
30 | void minusnmspinning() {
31 | nmspinning_lock.wLock();
32 | nmspinning--;
33 | nmspinning_lock.wUnlock();
34 | }
35 |
36 | bool steal(P* p, P* p2) {
37 | auto ng = p2->gqueue.queue.size();
38 | if (ng == 0)
39 | return false;
40 | else {
41 | ng = p2->gqueue.queue.size();
42 | if (ng == 0)
43 | return false;
44 | for (unsigned i = 0;i <= ng / 2;i++)
45 | {
46 | p->gqueue.push(p2->gqueue.get());
47 | }
48 | }
49 | debugPrint("steal success");
50 | return true;
51 | }
52 |
53 | void spin(M* m) {
54 |
55 | debugPrint("spinning...");
56 | addnmspinning();
57 | nmspinning_lock.rLock();
58 | while (nmspinning == 1)
59 | {
60 | nmspinning_lock.rUnLock(); //spinning
61 | nmspinning_lock.rLock();
62 | }
63 | nmspinning_lock.rUnLock();
64 | minusnmspinning();
65 | debugPrint("a m spin -> nonspin");
66 | while (1) {
67 | start_while:
68 | if (m->g != nullptr) {
69 | debugPrint("working...");
70 | m->g->func(*(m->g->args));
71 | delete m->g;
72 | m->g = nullptr;
73 | continue;
74 | }
75 | if (m->p == nullptr) {
76 | debugPrint("find a new p to m");
77 | auto nfp = gfpqueue.queue.size();
78 | if (nfp == 0) {
79 | debugPrint("a m go park");
80 | delete m;
81 | break;
82 | }
83 | else {
84 | auto p = gfpqueue.get();
85 | m->p = p;
86 | p->free = false;
87 | continue;
88 | }
89 | }
90 | if (m->g == nullptr) {
91 | debugPrint("find a new g to m");
92 | auto ng = m->p->gqueue.queue.size();
93 | if (ng == 0) {
94 | auto np = gplist.size();
95 | if (np == 0) {
96 | m->p = nullptr;
97 | delete m;
98 | debugPrint("a m go park");
99 | break;
100 | };
101 | auto i = rand() % np;
102 | if (steal(m->p, gplist[i])) {
103 | continue;
104 | }
105 | else {
106 | for (int j = 0;j < gplist.size();j++) {
107 | i = (i + 1) % gplist.size();
108 | if (steal(m->p, gplist[i])) {
109 | goto start_while;
110 | }
111 | }
112 |
113 | //gfpqueue.push(m->p);
114 | gfpqueue.lock.lock();
115 | gfpqueue.queue.push(m->p);
116 | m->p->free = true;
117 | gfpqueue.lock.unlock();
118 |
119 | debugPrint("p steal faild and go free");
120 | m->p = nullptr;
121 | delete m;
122 | debugPrint("a m go park");
123 | break;
124 | }
125 | }
126 | else {
127 | auto g = m->p->gqueue.get();
128 | m->g = g;
129 | continue;
130 | }
131 | }
132 | }
133 |
134 |
135 | }
136 |
137 | void gocommit(G* g) {
138 | debugPrint("new g commit");
139 | auto np = gplist.size();
140 | P* p = nullptr;
141 | if (np == 0) {
142 | p = new P;
143 | newP++;
144 | debugPrint("new p");
145 | gplist_lock.lock();
146 | gplist.push_back(p);
147 | gplist_lock.unlock();
148 | p->gqueue.push(g);
149 | gfpqueue.push(p);
150 | debugPrint("a p go to gfpqueue");
151 | }
152 | else {
153 | //TODO find a runnable p
154 | auto np = gplist.size();
155 | auto i = rand() % np;
156 | while (gplist[i]->free)
157 | i = (i + 1) % gplist.size();
158 | gplist[i]->gqueue.queue.push(g);
159 | }
160 | np = gplist.size();
161 | if (np < MAX_PROCS && nmspinning == 1) {
162 | auto m = new M;
163 | newM++;
164 | debugPrint("new m");
165 | if (p == nullptr) {
166 | m->p = new P;
167 | newP++;
168 | }
169 | else if (gfpqueue.queue.size() == 0) {
170 | m->p = new P;
171 | newP++;
172 | }
173 | else {
174 | m->p = gfpqueue.get();
175 | }
176 | debugPrint("new p");
177 | gplist_lock.lock();
178 | gplist.push_back(m->p);
179 | gplist_lock.unlock();
180 | auto t = new std::thread (spin, m);
181 | //t->detach();
182 | tqueue.push(t);
183 | }
184 | }
185 |
186 | void goinit() {
187 | auto m = new M;
188 | newM++;
189 | debugPrint("new m");
190 | auto t = new std::thread(spin, m);
191 | //t->detach();
192 | tqueue.push(t);
193 | }
194 |
195 | void goend() {
196 | while (!tqueue.queue.empty()) {
197 | auto t = tqueue.get();
198 | t->join();
199 | }
200 | }
201 | }
--------------------------------------------------------------------------------
/go.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include