1 // The MIT License (MIT)
2 //
3 // Copyright (c) 2015 Sergey Makeev, Vadim Slyusarev
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22
23 #include "Tests.h"
24 #include <UnitTest++.h>
25 #include <MTScheduler.h>
26
SUITE(WaitTests)27 SUITE(WaitTests)
28 {
29 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30 namespace SimpleWaitFromSubtask
31 {
32 MT::Atomic32<int32> subTaskCount;
33 MT::Atomic32<int32> taskCount;
34
35 MT::TaskGroup testGroup;
36
37 struct Subtask
38 {
39 MT_DECLARE_TASK(Subtask, MT::StackRequirements::STANDARD, MT::TaskPriority::NORMAL, MT::Color::Blue);
40
41 void Do(MT::FiberContext&)
42 {
43 MT::SpinSleepMilliSeconds(2);
44 subTaskCount.IncFetch();
45 }
46 };
47
48
49 struct Task
50 {
51 MT_DECLARE_TASK(Task, MT::StackRequirements::STANDARD, MT::TaskPriority::NORMAL, MT::Color::Blue);
52
53 void Do(MT::FiberContext& ctx)
54 {
55 Subtask tasks[2];
56 ctx.RunSubtasksAndYield(testGroup, &tasks[0], MT_ARRAY_SIZE(tasks));
57
58 taskCount.IncFetch();
59
60 }
61 };
62
63
64 // Checks one simple task
65 TEST(RunOneSimpleWaitTask)
66 {
67 taskCount.Store(0);
68 subTaskCount.Store(0);
69
70 MT::TaskScheduler scheduler;
71
72 testGroup = scheduler.CreateGroup();
73
74 Task tasks[16];
75 scheduler.RunAsync(MT::TaskGroup::Default(), &tasks[0], MT_ARRAY_SIZE(tasks));
76
77 CHECK(scheduler.WaitAll(2000));
78
79 int subTaskCountFinisehd = subTaskCount.Load();
80 CHECK_EQUAL(MT_ARRAY_SIZE(tasks) * 2, (size_t)subTaskCountFinisehd);
81
82 int taskCountFinished = taskCount.Load();
83 CHECK_EQUAL(MT_ARRAY_SIZE(tasks), (size_t)taskCountFinished);
84 }
85
86 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
87
88 struct LongTask
89 {
90 MT_DECLARE_TASK(LongTask, MT::StackRequirements::STANDARD, MT::TaskPriority::NORMAL, MT::Color::Blue);
91
92 void Do(MT::FiberContext&)
93 {
94 MT::Thread::Sleep(1);
95 }
96 };
97
98 TEST(TimeoutWaitAllTest)
99 {
100 MT::TaskScheduler scheduler;
101
102 LongTask tasks[4000];
103 scheduler.RunAsync(MT::TaskGroup::Default(), &tasks[0], MT_ARRAY_SIZE(tasks));
104
105 int64 startTime = MT::GetTimeMicroSeconds();
106
107 CHECK_EQUAL(false, scheduler.WaitAll(33));
108
109 int64 endTime = MT::GetTimeMicroSeconds();
110 int32 waitTime = (int32)(endTime - startTime);
111 printf("WaitAll(33) = %3.2f ms\n", waitTime / 1000.0f);
112 }
113
114 TEST(TimeoutWaitGroupTest)
115 {
116 MT::TaskScheduler scheduler;
117
118 MT::TaskGroup myGroup = scheduler.CreateGroup();
119
120 LongTask tasks[4000];
121 scheduler.RunAsync(myGroup, &tasks[0], MT_ARRAY_SIZE(tasks));
122
123 int64 startTime = MT::GetTimeMicroSeconds();
124
125 CHECK_EQUAL(false, scheduler.WaitGroup(myGroup, 33));
126
127 int64 endTime = MT::GetTimeMicroSeconds();
128 int32 waitTime = (int32)(endTime - startTime);
129 printf("WaitGroup(33) = %3.2f ms\n", waitTime / 1000.0f);
130 }
131
132
133 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
134
135
136 MT::Atomic32<uint32> finishedTaskCount;
137
138 struct SecondaryTask
139 {
140 MT_DECLARE_TASK(SecondaryTask, MT::StackRequirements::STANDARD, MT::TaskPriority::NORMAL, MT::Color::Blue);
141
142 void Do(MT::FiberContext&)
143 {
144 MT::SpinSleepMicroSeconds(20);
145 finishedTaskCount.IncFetch();
146 }
147 };
148
149
150 struct PrimaryTask
151 {
152 MT::TaskGroup secondaryGroup;
153
154 MT_DECLARE_TASK(PrimaryTask, MT::StackRequirements::STANDARD, MT::TaskPriority::NORMAL, MT::Color::Blue);
155
156 PrimaryTask(MT::TaskGroup _secondaryGroup)
157 : secondaryGroup(_secondaryGroup)
158 {
159 }
160
161 void Do(MT::FiberContext& ctx)
162 {
163 SecondaryTask tasks[64];
164 ctx.RunAsync(secondaryGroup, &tasks[0], MT_ARRAY_SIZE(tasks));
165
166 //CHECK(ctx.WaitGroup(secondaryGroup, 10000));
167
168 finishedTaskCount.IncFetch();
169 }
170 };
171
172
173 TEST(RunOneSimpleWaitTaskFromTask)
174 {
175 finishedTaskCount.Store(0);
176
177 MT::TaskScheduler scheduler;
178
179 MT::TaskGroup mainGroup = scheduler.CreateGroup();
180 MT::TaskGroup secondaryGroup = scheduler.CreateGroup();
181
182 PrimaryTask task(secondaryGroup);
183 scheduler.RunAsync(mainGroup, &task, 1);
184
185 CHECK(scheduler.WaitGroup(mainGroup, 10000));
186 }
187
188
189 }
190 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
191 }
192
193