1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <benchmark/benchmark.h>
17 #include <sys/types.h>
18 #include <sys/timerfd.h>
19 #include <sys/prctl.h>
20 #include "unistd.h"
21 #include <cstdint>
22 #include <cstring>
23 #include <string>
24 #include <thread>
25 #include <mutex>
26 #include <memory>
27 #include <atomic>
28 #include <algorithm>
29 #include <list>
30 #include <map>
31 #include <functional>
32 #include <iostream>
33 #include "common_timer_errors.h"
34 #include "common_event_sys_errors.h"
35 #include "io_event_handler.h"
36 #include "io_event_reactor.h"
37 #include <sys/time.h>
38 #include "benchmark_log.h"
39 #include "benchmark_assert.h"
40 using namespace OHOS::Utils;
41
42 namespace OHOS {
43 namespace {
44
45 class BenchmarkEventTest : public benchmark::Fixture {
46 public:
BenchmarkEventTest()47 BenchmarkEventTest()
48 {
49 Iterations(iterations);
50 Repetitions(repetitions);
51 ReportAggregatesOnly();
52 }
53
54 ~BenchmarkEventTest() override = default;
SetUp(const::benchmark::State & state)55 void SetUp(const ::benchmark::State& state) override
56 {
57 }
58
TearDown(const::benchmark::State & state)59 void TearDown(const ::benchmark::State& state) override
60 {
61 }
62
63 protected:
64 const int32_t repetitions = 3;
65 const int32_t iterations = 500;
66 };
67
68 int g_data = 0;
TimerCallback1()69 void TimerCallback1()
70 {
71 g_data++;
72 }
73
74 static const int MILLI_TO_BASE = 1000;
75 static const int NANO_TO_BASE = 1000000000;
76 static constexpr int MILLI_TO_NANO = NANO_TO_BASE / MILLI_TO_BASE;
77 const int INVALID_FD = -1;
78 const int SLEEP_SIXTEEN_MILLISECONDS = 16;
79 const int TIMER_INIT_DELAY = 15;
80 const int TIMER_INIT_DELAY_TEN = 10;
81 constexpr uint32_t TIMEOUT_ONE_MS = 1;
82 constexpr uint32_t TIMEOUT_TWO_MS = 2;
83
84
85 class TimerFdHandler : public IOEventHandler {
86 public:
87 using TimerEventCallback = std::function<void()>;
88 TimerFdHandler(int fd, const TimerEventCallback& cb);
~TimerFdHandler()89 ~TimerFdHandler() {}
90 bool Initialize(uint32_t interval);
91 void Uninitialize();
92 void TimeOut();
93
94 private:
95 TimerEventCallback timerCallback_;
96 };
97
TestCallback()98 void TestCallback()
99 {
100 }
101
SetFdAndCallback(std::shared_ptr<IOEventHandler> & handler,benchmark::State & state)102 void SetFdAndCallback(std::shared_ptr<IOEventHandler>& handler, benchmark::State& state)
103 {
104 // 1. Set fd
105 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
106 AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state);
107 handler->SetFd(fd);
108 AssertEqual(handler->GetFd(), fd, "handler->GetFd() did not equal fd as expected.", state);
109
110 // 2. Set callback
111 handler->SetCallback(&TestCallback);
112 AssertUnequal(handler->GetCallback(), nullptr,
113 "handler->GetCallback() was not different from nullptr as expected.", state);
114 }
115
116 /*
117 * @tc.name: testIOEventHandler001
118 * @tc.desc: test basic interfaces of IOEventHandler.
119 */
BENCHMARK_F(BenchmarkEventTest,testIOEventHandler001)120 BENCHMARK_F(BenchmarkEventTest, testIOEventHandler001)(benchmark::State& state)
121 {
122 BENCHMARK_LOGD("EventTest testIOEventHandler001 start.");
123 while (state.KeepRunning()) {
124 g_data = 0;
125 // 1. Create io event handler
126 std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(INVALID_FD);
127
128 // 2. Set fd and callback
129 SetFdAndCallback(handler, state);
130
131 // 3. Set interest events
132 handler->SetEvents(Events::EVENT_READ | Events::EVENT_WRITE);
133 AssertEqual(handler->GetEvents(), (Events::EVENT_READ | Events::EVENT_WRITE),
134 "handler->GetEvents() did not equal (Events::EVENT_READ | Events::EVENT_WRITE) as expected.", state);
135
136 // 4. Check status
137 AssertEqual(handler->Prev(), nullptr, "handler->Prev() did not equal nullptr as expected.", state);
138 AssertEqual(handler->Next(), nullptr, "handler->Next() did not equal nullptr as expected.", state);
139 AssertEqual(handler->IsActive(), false, "handler->IsActive() did not equal false as expected.", state);
140
141 // 5. disable events
142 handler->DisableAll();
143 AssertEqual(handler->GetEvents(), Events::EVENT_NONE,
144 "handler->GetEvents() did not equal Events::EVENT_NONE as expected.", state);
145
146 // 6. enable events
147 handler->EnableRead();
148 handler->EnableWrite();
149 AssertEqual(handler->GetEvents(), (Events::EVENT_READ | Events::EVENT_WRITE),
150 "handler->GetEvents() did not equal (Events::EVENT_READ | Events::EVENT_WRITE) as expected.", state);
151
152 // 7. disable one of the events
153 handler->DisableWrite();
154 AssertEqual(handler->GetEvents(), Events::EVENT_READ,
155 "handler->GetEvents() did not equal Events::EVENT_READ as expected.", state);
156 }
157 BENCHMARK_LOGD("EventTest testIOEventHandler001 end.");
158 }
159
160 /*
161 * @tc.name: testIOEventHandler002
162 * @tc.desc: test reactor-related interfaces of IOEventHandler.
163 */
BENCHMARK_F(BenchmarkEventTest,testIOEventHandler002)164 BENCHMARK_F(BenchmarkEventTest, testIOEventHandler002)(benchmark::State& state)
165 {
166 BENCHMARK_LOGD("EventTest testIOEventHandler002 start.");
167 while (state.KeepRunning()) {
168 g_data = 0;
169 // 1. Create io event handler
170 std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(INVALID_FD);
171
172 // 2. Set fd and callback
173 SetFdAndCallback(handler, state);
174
175 // 3. Set interest events
176 handler->EnableRead();
177 AssertEqual(handler->GetEvents(), Events::EVENT_READ,
178 "handler->GetEvents() did not equal Events::EVENT_READ as expected.", state);
179
180 // 4. Create a reactor but not run
181 std::shared_ptr<IOEventReactor> reactor = std::make_shared<IOEventReactor>();
182 AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK,
183 "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state);
184
185 // 5. Start handler
186 handler->Start(reactor.get());
187 AssertEqual(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_OK,
188 "reactor->FindHandler(handler.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
189
190 // 6. Change setting and update handler to the reactor
191 handler->EnableWrite();
192 AssertTrue((handler->Update(reactor.get())),
193 "handler->Update(reactor.get()) did not equal true as expected.", state);
194
195 // 7. Remove the handler
196 handler->Stop(reactor.get());
197 AssertEqual(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_NOT_FOUND,
198 "reactor->FindHandler(handler.get()) did not equal EVENT_SYS_ERR_NOT_FOUND as expected.", state);
199
200 // 8. Add handler, then delete handler. handler will remove itself from the reactor during deconstruction.
201 AssertTrue((handler->Start(reactor.get())),
202 "handler->Start(reactor.get()) did not equal true as expected.", state);
203 handler.reset();
204 }
205 BENCHMARK_LOGD("EventTest testIOEventHandler002 end.");
206 }
207
AddHandler(std::shared_ptr<IOEventReactor> & reactor,std::shared_ptr<IOEventHandler> & handler1,std::shared_ptr<IOEventHandler> & handler2,std::shared_ptr<IOEventHandler> & handler3,benchmark::State & state)208 static void AddHandler(std::shared_ptr<IOEventReactor>& reactor, std::shared_ptr<IOEventHandler>& handler1,
209 std::shared_ptr<IOEventHandler>& handler2, std::shared_ptr<IOEventHandler>& handler3,
210 benchmark::State& state)
211 {
212 AssertEqual(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK,
213 "reactor->AddHandler(handler1.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
214 AssertEqual(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK,
215 "reactor->AddHandler(handler2.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
216 AssertUnequal(reactor->AddHandler(handler3.get()), EVENT_SYS_ERR_OK,
217 "reactor->AddHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state);
218 AssertUnequal(reactor->AddHandler(nullptr), EVENT_SYS_ERR_OK,
219 "reactor->AddHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state);
220 }
221
RemoveHandler(std::shared_ptr<IOEventReactor> & reactor,std::shared_ptr<IOEventHandler> & handler2,std::shared_ptr<IOEventHandler> & handler3,std::shared_ptr<IOEventHandler> & handler4,benchmark::State & state)222 static void RemoveHandler(std::shared_ptr<IOEventReactor>& reactor, std::shared_ptr<IOEventHandler>& handler2,
223 std::shared_ptr<IOEventHandler>& handler3, std::shared_ptr<IOEventHandler>& handler4,
224 benchmark::State& state)
225 {
226 AssertUnequal(reactor->RemoveHandler(nullptr), EVENT_SYS_ERR_OK,
227 "reactor->RemoveHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state);
228 AssertUnequal(reactor->RemoveHandler(handler3.get()), EVENT_SYS_ERR_OK,
229 "reactor->RemoveHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state);
230 AssertUnequal(reactor->RemoveHandler(handler4.get()), EVENT_SYS_ERR_OK,
231 "reactor->RemoveHandler(handler4.get()) was not different from EVENT_SYS_ERR_OK as expected.", state);
232 AssertEqual(reactor->RemoveHandler(handler2.get()), EVENT_SYS_ERR_OK,
233 "reactor->RemoveHandler(handler2.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
234 }
235
UpdateHandler(std::shared_ptr<IOEventReactor> & reactor,std::shared_ptr<IOEventHandler> & handler1,std::shared_ptr<IOEventHandler> & handler3,std::shared_ptr<IOEventHandler> & handler4,benchmark::State & state)236 static void UpdateHandler(std::shared_ptr<IOEventReactor>& reactor, std::shared_ptr<IOEventHandler>& handler1,
237 std::shared_ptr<IOEventHandler>& handler3, std::shared_ptr<IOEventHandler>& handler4,
238 benchmark::State& state)
239 {
240 // Update handler
241 AssertUnequal(reactor->UpdateHandler(nullptr), EVENT_SYS_ERR_OK,
242 "reactor->UpdateHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state);
243 AssertUnequal(reactor->UpdateHandler(handler3.get()), EVENT_SYS_ERR_OK,
244 "reactor->UpdateHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state);
245 AssertEqual(reactor->UpdateHandler(handler1.get()), EVENT_SYS_ERR_OK,
246 "reactor->UpdateHandler(handler1.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
247 AssertEqual(reactor->UpdateHandler(handler4.get()), EVENT_SYS_ERR_OK,
248 "reactor->UpdateHandler(handler4.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
249 }
250
251 /*
252 * @tc.name: testIOEventReactor001
253 * @tc.desc: test basic interfaces of IOEventReactor.
254 */
BENCHMARK_F(BenchmarkEventTest,testIOEventReactor001)255 BENCHMARK_F(BenchmarkEventTest, testIOEventReactor001)(benchmark::State& state)
256 {
257 BENCHMARK_LOGD("EventTest testIOEventReactor001 start.");
258 while (state.KeepRunning()) {
259 g_data = 0;
260 // Get fd
261 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
262 AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state);
263
264 // 1. Create io event handlers
265 std::shared_ptr<IOEventHandler> handler1 = std::make_shared<IOEventHandler>(fd);
266 std::shared_ptr<IOEventHandler> handler2 = std::make_shared<IOEventHandler>(fd);
267 std::shared_ptr<IOEventHandler> handler3 = std::make_shared<IOEventHandler>(INVALID_FD);
268 std::shared_ptr<IOEventHandler> handler4 = std::make_shared<IOEventHandler>(fd);
269
270 // 2. Create a reactor but not run
271 std::shared_ptr<IOEventReactor> reactor = std::make_shared<IOEventReactor>();
272 AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK,
273 "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state);
274
275 // 3. Add handler
276 AddHandler(reactor, handler1, handler2, handler3, state);
277
278 // 4. Add handler from the handler side.
279 AssertUnequal(handler1->Start(reactor.get()), true,
280 "handler1->Start(reactor.get()) was not different from false as expected.", state);
281 AssertUnequal(handler3->Start(reactor.get()), true,
282 "handler3->Start(reactor.get()) was not different from false as expected.", state);
283
284 // 5. Remove handler
285 RemoveHandler(reactor, handler2, handler3, handler4, state);
286
287 // 6. Remove handler from the handler side.
288 AssertUnequal(handler2->Stop(reactor.get()), true,
289 "handler2->Stop(reactor.get()) was not different from false as expected.", state);
290
291 // 7. Update handler
292 UpdateHandler(reactor, handler1, handler3, handler4, state);
293
294 // Update handler from the handler side.
295 AssertEqual(handler2->Update(reactor.get()), true,
296 "handler2->Update(reactor.get()) was not different from false as expected.", state);
297 AssertUnequal(handler3->Update(reactor.get()), true,
298 "handler3->Update(reactor.get()) was not different from true as expected.", state);
299
300 // 9. Find handler
301 AssertUnequal(reactor->FindHandler(nullptr), EVENT_SYS_ERR_OK,
302 "reactor->FindHandler(nullptr) was not different from EVENT_SYS_ERR_OK as expected.", state);
303 AssertUnequal(reactor->FindHandler(handler3.get()), EVENT_SYS_ERR_OK,
304 "reactor->FindHandler(handler3.get()) was not different from EVENT_SYS_ERR_OK as expected.", state);
305
306 // 10. Clean handler
307 AssertUnequal(reactor->Clean(INVALID_FD), EVENT_SYS_ERR_OK,
308 "reactor->Clean(INVALID_FD) was not different from EVENT_SYS_ERR_OK as expected.", state);
309 AssertEqual(reactor->Clean(fd), EVENT_SYS_ERR_OK,
310 "reactor->Clean(fd) did not equal EVENT_SYS_ERR_OK as expected.", state);
311 }
312 BENCHMARK_LOGD("EventTest testIOEventReactor001 end.");
313 }
314
315 /*
316 * @tc.name: testIOEventReactor002
317 * @tc.desc: test change event but not update.
318 */
BENCHMARK_F(BenchmarkEventTest,testIOEventReactor002)319 BENCHMARK_F(BenchmarkEventTest, testIOEventReactor002)(benchmark::State& state)
320 {
321 BENCHMARK_LOGD("EventTest testIOEventReactor002 start.");
322 while (state.KeepRunning()) {
323 g_data = 0;
324 // 1. Open timer
325 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
326 AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state);
327
328 // 2. Create io event handlers
329 std::shared_ptr<IOEventHandler> handler1 = std::make_shared<IOEventHandler>(fd);
330 std::shared_ptr<IOEventHandler> handler2 = std::make_shared<IOEventHandler>(fd);
331
332 // 3. Create a reactor but not run
333 std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
334 AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK,
335 "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state);
336
337 // 4. Add handler
338 AssertEqual(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK,
339 "reactor->AddHandler(handler1.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
340 AssertEqual(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK,
341 "reactor->AddHandler(handler2.get()) did not equal EVENT_SYS_ERR_OK as expected.", state);
342
343 // 5. release one handler
344 handler2.reset(); // will be removed from the inner list.
345 }
346 BENCHMARK_LOGD("EventTest testIOEventReactor002 end.");
347 }
348
TimerFdHandler(int fd,const TimerEventCallback & cb)349 TimerFdHandler::TimerFdHandler(int fd, const TimerEventCallback& cb)
350 : IOEventHandler(fd), timerCallback_(cb)
351 {
352 BENCHMARK_LOGD("EventTest TimerFdHandler::TimerFdHandler is called.");
353 }
354
Initialize(uint32_t interval)355 bool TimerFdHandler::Initialize(uint32_t interval)
356 {
357 BENCHMARK_LOGD("EventTest bool TimerFdHandler::Initialize is called.");
358 if ((GetFd() == INVALID_FD)) {
359 return false;
360 }
361
362 struct itimerspec newValue = {{0, 0}, {0, 0}};
363 timespec now{0, 0};
364 if (clock_gettime(CLOCK_MONOTONIC, &now) == INVALID_FD) {
365 return false;
366 }
367
368 // next time out time is now + interval
369 newValue.it_value.tv_sec = now.tv_sec + interval / MILLI_TO_BASE;
370 newValue.it_value.tv_nsec = now.tv_nsec + (interval % MILLI_TO_BASE) * MILLI_TO_NANO;
371 if (newValue.it_value.tv_nsec >= NANO_TO_BASE) {
372 newValue.it_value.tv_sec += 1;
373 newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE;
374 }
375
376 // interval
377 newValue.it_interval.tv_sec = interval / MILLI_TO_BASE;
378 newValue.it_interval.tv_nsec = (interval % MILLI_TO_BASE) * MILLI_TO_NANO;
379
380 if (timerfd_settime(GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == INVALID_FD) {
381 BENCHMARK_LOGD("Set timerFd failed-%{public}s timer_fd:%{public}d", strerror(errno), GetFd());
382 return false;
383 }
384
385 EnableRead();
386 SetCallback(std::bind(&TimerFdHandler::TimeOut, this));
387
388 return true;
389 }
390
Uninitialize()391 void TimerFdHandler::Uninitialize()
392 {
393 BENCHMARK_LOGD("EventTest void TimerFdHandler::Uninitialize is called.");
394 DisableAll();
395 }
396
TimeOut()397 void TimerFdHandler::TimeOut()
398 {
399 BENCHMARK_LOGD("EventTest void TimerFdHandler::TimeOut is called.");
400 if (GetFd() == INVALID_FD) {
401 BENCHMARK_LOGD("Invalid timer_fd.");
402 return;
403 }
404 uint64_t expirations = 0;
405 ssize_t n = ::read(GetFd(), &expirations, sizeof(expirations));
406 if (n != sizeof(expirations)) {
407 BENCHMARK_LOGD("reads %{public}d bytes instead of 8.", static_cast<int>(n));
408 }
409
410 if (timerCallback_) {
411 timerCallback_();
412 }
413 }
414
415 /*
416 * @tc.name: testEvent001
417 * @tc.desc: test handling event of timerfd.
418 */
BENCHMARK_F(BenchmarkEventTest,testEvent001)419 BENCHMARK_F(BenchmarkEventTest, testEvent001)(benchmark::State& state)
420 {
421 BENCHMARK_LOGD("EventTest testEvent001 start.");
422 while (state.KeepRunning()) {
423 g_data = 0;
424 // 1. Open timer
425 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
426 AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state);
427 // 2. Create timer event handler
428 std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
429
430 // 3. Create reactor for event loop
431 std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
432 AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK,
433 "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state);
434 reactor->EnableHandling();
435
436 // 4. Initialize timer handler and add it to reactor
437 AssertTrue((handler->Initialize(10)), "handler->Initialize(10) did not equal true as expected.", state);
438 AssertTrue((handler->Start(reactor.get())),
439 "handler->Start(reactor.get()) did not equal true as expected.", state);
440
441 // 5. Run event loop
442 std::thread loopThread([&reactor] {
443 reactor->Run(INVALID_FD);
444 });
445
446 // 6. Wait for event handling
447 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS));
448
449 // 7. Check result, execute once at least
450 AssertGreaterThanOrEqual(g_data, 1, "g_data was not greater than or equal to 1 as expected.", state);
451
452 // 8. terminate the event-loop (aka Run())
453 reactor->Terminate();
454 loopThread.join();
455 }
456 BENCHMARK_LOGD("EventTest testEvent001 end.");
457 }
458
EventLoop(std::shared_ptr<TimerFdHandler> & handler,benchmark::State & state,std::thread & loopThread)459 std::unique_ptr<IOEventReactor> EventLoop(std::shared_ptr<TimerFdHandler>& handler, benchmark::State& state,
460 std::thread& loopThread)
461 {
462 // 1. Open timer
463 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
464 AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state);
465 // 2. Create timer event handler
466 handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
467
468 // 3. Create reactor for event loop
469 std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
470 AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK,
471 "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state);
472
473 // 4. Initialize timer handler and add it to reactor
474 AssertTrue((handler->Initialize(TIMER_INIT_DELAY_TEN)),
475 "handler->Initialize(TIMER_INIT_DELAY_TEN) did not equal true as expected.", state);
476 AssertTrue((handler->Start(reactor.get())),
477 "handler->Start(reactor.get()) did not equal true as expected.", state);
478
479 // 5. Run event loop
480 loopThread = std::thread([&reactor] {
481 reactor->Run(INVALID_FD);
482 });
483
484 return reactor;
485 }
486
487 /*
488 * @tc.name: testEvent002
489 * @tc.desc: test changing event to EVENT_NONE.
490 */
BENCHMARK_F(BenchmarkEventTest,testEvent002)491 BENCHMARK_F(BenchmarkEventTest, testEvent002)(benchmark::State& state)
492 {
493 BENCHMARK_LOGD("EventTest testEvent002 start.");
494 while (state.KeepRunning()) {
495 g_data = 0;
496 std::shared_ptr<TimerFdHandler> handler;
497 std::thread loopThread;
498 // 1. event loop
499 std::unique_ptr<IOEventReactor> reactor = EventLoop(handler, state, loopThread);
500
501 // 2. Change settings
502 reactor->DisableHandling();
503 std::this_thread::sleep_for(std::chrono::milliseconds(1));
504 reactor->EnableHandling();
505 handler->SetEvents(Events::EVENT_NONE);
506
507 // 3. Wait for event handling
508 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS));
509
510 // 4. Check result, no execution
511 AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state);
512
513 // 5. terminate the event-loop (aka Run())
514 reactor->Terminate();
515 loopThread.join();
516 }
517 BENCHMARK_LOGD("EventTest testEvent002 end.");
518 }
519
520 /*
521 * @tc.name: testEvent003
522 * @tc.desc: test disable single event.
523 */
BENCHMARK_F(BenchmarkEventTest,testEvent003)524 BENCHMARK_F(BenchmarkEventTest, testEvent003)(benchmark::State& state)
525 {
526 BENCHMARK_LOGD("EventTest testEvent003 start.");
527 while (state.KeepRunning()) {
528 g_data = 0;
529 std::shared_ptr<TimerFdHandler> handler;
530 std::thread loopThread;
531 // 1. event loop
532 std::unique_ptr<IOEventReactor> reactor = EventLoop(handler, state, loopThread);
533
534 // 2. Change settings
535 reactor->EnableHandling();
536 AssertTrue((handler->Stop(reactor.get())),
537 "handler->Stop(reactor.get()) did not equal true as expected.", state);
538
539 // 3. Check result, no execution
540 AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state);
541
542 // 4. terminate the event-loop (aka Run())
543 reactor->Terminate();
544 loopThread.join();
545 }
546 BENCHMARK_LOGD("EventTest testEvent003 end.");
547 }
548
549 /*
550 * @tc.name: testEvent004
551 * @tc.desc: test removing callback.
552 */
BENCHMARK_F(BenchmarkEventTest,testEvent004)553 BENCHMARK_F(BenchmarkEventTest, testEvent004)(benchmark::State& state)
554 {
555 BENCHMARK_LOGD("EventTest testEvent004 start.");
556 while (state.KeepRunning()) {
557 g_data = 0;
558 std::shared_ptr<TimerFdHandler> handler;
559 std::thread loopThread;
560 // 1. event loop
561 std::unique_ptr<IOEventReactor> reactor = EventLoop(handler, state, loopThread);
562
563 // 2. Change settings
564 reactor->EnableHandling();
565 handler->SetCallback(nullptr);
566
567 // 3. Wait for event handling
568 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS));
569
570 // 4. Check result, no execution
571 AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state);
572
573 // 5. terminate the event-loop (aka Run())
574 reactor->Terminate();
575 loopThread.join();
576 }
577 BENCHMARK_LOGD("EventTest testEvent004 end.");
578 }
579
580 /*
581 * @tc.name: testEvent005
582 * @tc.desc: test change event but not update.
583 */
BENCHMARK_F(BenchmarkEventTest,testEvent005)584 BENCHMARK_F(BenchmarkEventTest, testEvent005)(benchmark::State& state)
585 {
586 BENCHMARK_LOGD("EventTest testEvent005 start.");
587 while (state.KeepRunning()) {
588 g_data = 0;
589 // 1. Open timer
590 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
591 AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state);
592 // 2. Create timer event handler
593 std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
594
595 // 3. Create reactor for event loop
596 std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
597 AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK,
598 "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state);
599
600 // 4. Initialize timer handler and add it to reactor
601 AssertTrue((handler->Initialize(TIMER_INIT_DELAY)),
602 "handler->Initialize(TIMER_INIT_DELAY) did not equal true as expected.", state);
603 AssertTrue((handler->Start(reactor.get())),
604 "handler->Start(reactor.get()) did not equal true as expected.", state);
605
606 // 5. Run event loop
607 std::thread loopThread([&reactor] {
608 reactor->Run(INVALID_FD);
609 });
610
611 // 6. Change settings but not update
612 handler->SetEvents(Events::EVENT_WRITE);
613 reactor->EnableHandling();
614
615 // 7. Wait for event handling
616 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS));
617
618 // 8. Check result, no execution
619 AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state);
620
621 // 9. terminate the event-loop (aka Run())
622 reactor->Terminate();
623 loopThread.join();
624 }
625 BENCHMARK_LOGD("EventTest testEvent005 end.");
626 }
627
628 /*
629 * @tc.name: testEvent006
630 * @tc.desc: test release the handler when started.
631 */
BENCHMARK_F(BenchmarkEventTest,testEvent006)632 BENCHMARK_F(BenchmarkEventTest, testEvent006)(benchmark::State& state)
633 {
634 BENCHMARK_LOGD("EventTest testEvent006 start.");
635 while (state.KeepRunning()) {
636 g_data = 0;
637 // 1. Open timer
638 int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
639 AssertUnequal(fd, INVALID_FD, "fd was not different from INVALID_FD as expected.", state);
640 // 2. Create timer event handler
641 std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
642
643 // 3. Create reactor for event loop
644 std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
645 AssertEqual(reactor->SetUp(), EVENT_SYS_ERR_OK,
646 "reactor->SetUp() did not equal EVENT_SYS_ERR_OK as expected.", state);
647
648 // 4. Initialize timer handler and add it to reactor
649 AssertTrue((handler->Initialize(TIMER_INIT_DELAY)),
650 "handler->Initialize(TIMER_INIT_DELAY) did not equal true as expected.", state);
651 AssertTrue((handler->Start(reactor.get())),
652 "handler->Start(reactor.get()) did not equal true as expected.", state);
653
654 // 5. Run event loop
655 std::thread loopThread([&reactor] {
656 reactor->Run(INVALID_FD);
657 });
658
659 // 6. release eventhandler
660 handler.reset();
661 reactor->EnableHandling();
662
663 // 7. Wait for event handling
664 std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_SIXTEEN_MILLISECONDS));
665
666 // 8. Check result, no execution
667 AssertEqual(g_data, 0, "g_data did not equal 0 as expected.", state);
668
669 // 9. terminate the event-loop (aka Run())
670 reactor->Terminate();
671 loopThread.join();
672 }
673 BENCHMARK_LOGD("EventTest testEvent006 end.");
674 }
675
676 // Try to substitue underlying implementation of OHOS::UTILS::TIMER
677 class TimerEventHandler {
678 public:
679 using TimerEventCallback = std::function<void(TimerEventHandler*)>;
680 TimerEventHandler(int timerFd, uint32_t timeout, bool once);
681 TimerEventHandler(uint32_t timeout /* ms */, bool once);
682 ~TimerEventHandler();
683
684 TimerEventHandler(const TimerEventHandler&) = delete;
685 TimerEventHandler& operator=(const TimerEventHandler&) = delete;
686 TimerEventHandler(const TimerEventHandler&&) = delete;
687 TimerEventHandler& operator=(const TimerEventHandler&&) = delete;
688
689 ErrCode Initialize();
690 void Uninitialize();
691
692 bool Start(IOEventReactor* reactor);
693 bool Stop(IOEventReactor* reactor);
694
SetTimerEventCallback(const TimerEventCallback & callback)695 inline void SetTimerEventCallback(const TimerEventCallback& callback) { timerEventCallback_ = callback; }
696
SetTimerId(const uint32_t & id)697 inline void SetTimerId(const uint32_t& id) { timerId_ = id; }
698
GetInterval() const699 inline uint32_t GetInterval() const { return interval_; }
GetTimerId() const700 inline uint32_t GetTimerId() const { return timerId_; }
GetTimerFd() const701 inline int GetTimerFd() const { return handler_->GetFd(); }
702
703 private:
704 void TimeOut();
705
706 private:
707 bool once_;
708 uint32_t timerId_;
709 uint32_t interval_;
710 TimerEventCallback timerEventCallback_;
711
712 std::unique_ptr<IOEventHandler> handler_;
713
714 friend class Timer;
715 };
716
717 class Timer {
718 public:
719 using TimerCallback = std::function<void ()>;
720 using TimerCallbackPtr = std::shared_ptr<TimerCallback>;
721 using TimerEventCallback = TimerEventHandler::TimerEventCallback;
722
723 explicit Timer(const std::string& name, int timeoutMs = 1000);
~Timer()724 virtual ~Timer() {}
725 virtual uint32_t Setup();
726 virtual void Shutdown(bool useJoin = true);
727 uint32_t Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once = false);
728 void Unregister(uint32_t timerId);
729
730 private:
731 void MainLoop();
732 void OnTimer(TimerEventHandler* handler, const TimerCallback& callback);
733 uint32_t GetValidId() const;
734 int GetTimerFd(uint32_t interval /* ms */);
735 void EraseUnusedTimerId(uint32_t interval, const std::vector<uint32_t>& unusedIds);
736
737 private:
738 using TimerHandlerPtr = std::shared_ptr<TimerEventHandler>;
739 using TimerHandlerList = std::list<TimerHandlerPtr>;
740
741 ErrCode ScheduleTimer(const TimerEventCallback& callback, uint32_t interval, uint32_t timerId, int& timerFd,
742 bool once);
743 ErrCode CancelTimer(TimerHandlerPtr target);
744
745 std::map<uint32_t, TimerHandlerPtr> timerHandlers_;
746 std::map<uint32_t, TimerHandlerList> intervalToTimers_;
747
748 std::string name_;
749 int timeoutMs_;
750 std::thread thread_;
751 std::unique_ptr<IOEventReactor> reactor_;
752 std::mutex mutex_;
753 };
754
Timer(const std::string & name,int timeoutMs)755 Timer::Timer(const std::string& name, int timeoutMs) : name_(name), timeoutMs_(timeoutMs),
756 reactor_(new IOEventReactor())
757 {
758 BENCHMARK_LOGD("EventTest Timer::Timer is called.");
759 }
760
MainLoop()761 void Timer::MainLoop()
762 {
763 prctl(PR_SET_NAME, name_.c_str(), 0, 0, 0);
764
765 reactor_->Run(timeoutMs_);
766 BENCHMARK_LOGD("||%{public}d||Loop finished", gettid());
767 BENCHMARK_LOGD("MainLoop timeoutMs_: %{public}d", timeoutMs_);
768
769 if (reactor_->CleanUp() != EVENT_SYS_ERR_OK) {
770 BENCHMARK_LOGD("||%{public}d||Reactor Clean Failed. It will clean during deconstruction", gettid());
771 }
772 }
773
Setup()774 uint32_t Timer::Setup()
775 {
776 BENCHMARK_LOGD("EventTest uint32_t Timer::Setup is called.");
777 if (thread_.joinable()) { // avoid double assign to an active thread
778 return TIMER_ERR_INVALID_VALUE;
779 }
780
781 if (reactor_->SetUp() != EVENT_SYS_ERR_OK) {
782 BENCHMARK_LOGD("||%{public}d||Setup reactor failed.", gettid());
783 return TIMER_ERR_DEAL_FAILED;
784 }
785
786 reactor_->EnableHandling();
787
788 std::thread loopThread(std::bind(&Timer::MainLoop, this));
789 thread_.swap(loopThread);
790
791 return TIMER_ERR_OK;
792 }
793
Shutdown(bool useJoin)794 void Timer::Shutdown(bool useJoin)
795 {
796 BENCHMARK_LOGD("EventTest void Timer::Shutdown is called.");
797 if (!thread_.joinable()) {
798 BENCHMARK_LOGD("||%{public}d||Invalid operation. Already shutdown.", gettid());
799 return;
800 }
801
802 BENCHMARK_LOGD("||%{public}d||Stop reactor.", gettid());
803 reactor_->Terminate();
804
805 if (!useJoin) {
806 thread_.detach();
807 return;
808 }
809 thread_.join();
810 }
811
ScheduleTimer(const TimerEventCallback & callback,uint32_t interval,uint32_t timerId,int & timerFd,bool once)812 ErrCode Timer::ScheduleTimer(const TimerEventCallback& callback, uint32_t interval,
813 uint32_t timerId, int& timerFd, bool once)
814 {
815 BENCHMARK_LOGD("EventTest ErrCode Timer::ScheduleTimer is called.");
816 std::shared_ptr<TimerEventHandler> handler = std::make_shared<TimerEventHandler>(timerFd, interval, once);
817 BENCHMARK_LOGD("Timer::ScheduleTimer interval: %{public}u -- timerId: %{public}u -- timerFd: %{public}d",
818 interval, timerId, timerFd);
819
820 handler->SetTimerId(timerId);
821 handler->SetTimerEventCallback(callback);
822
823 uint32_t ret = handler->Initialize();
824 if (ret != TIMER_ERR_OK) {
825 BENCHMARK_LOGD("||%{public}d||Init timer handler failed.", gettid());
826 return ret;
827 }
828 if (!handler->Start(reactor_.get())) {
829 BENCHMARK_LOGD("||%{public}d||Start timer handler failed.", gettid());
830 return TIMER_ERR_DEAL_FAILED;
831 }
832 timerHandlers_.emplace(timerId, handler); // Add to the id2handlers map
833 intervalToTimers_[interval].push_back(handler); // Add to interval2handlerlist map
834 timerFd = handler->GetTimerFd();
835 return TIMER_ERR_OK;
836 }
837
838
Register(const TimerCallback & callback,uint32_t interval,bool once)839 uint32_t Timer::Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once)
840 {
841 BENCHMARK_LOGD("EventTest uint32_t Timer::Register is called.");
842 std::lock_guard<std::mutex> lock(mutex_);
843
844 // wrap the callback in OnTiner
845 TimerEventCallback wrappedCb = std::bind(&Timer::OnTimer, this, std::placeholders::_1, callback);
846 int timerFd = once ? IO_EVENT_INVALID_FD : GetTimerFd(interval); // Get timerFd
847 uint32_t timerId = GetValidId(); // Get timerId
848
849 uint32_t ret = ScheduleTimer(wrappedCb, interval, timerId, timerFd, once);
850 if (ret != TIMER_ERR_OK) {
851 BENCHMARK_LOGD("||%{public}d||Try schedule task failed. timer-id:%{public}d, interval:%{public}d, "\
852 "timer-fd:%{public}d", gettid(), timerId, interval, timerFd);
853 return TIMER_ERR_DEAL_FAILED;
854 }
855
856 return timerId;
857 }
858
CancelTimer(TimerHandlerPtr target)859 ErrCode Timer::CancelTimer(TimerHandlerPtr target)
860 {
861 BENCHMARK_LOGD("EventTest ErrCode Timer::CancelTimer is called.");
862 BENCHMARK_LOGD("||%{public}d||Cancle timer handler with fd:%{public}d", gettid(), target->GetTimerFd());
863 target->Uninitialize();
864 if (!target->Stop(reactor_.get())) {
865 BENCHMARK_LOGD("||%{public}d||Stop timer handler failed.", gettid());
866 return TIMER_ERR_DEAL_FAILED;
867 }
868
869 timerHandlers_.erase(target->timerId_);
870
871 auto handlerList = intervalToTimers_[target->interval_];
872 auto itor = std::find(handlerList.begin(), handlerList.end(), target);
873 if (itor != handlerList.end()) {
874 handlerList.erase(itor);
875 }
876
877 if (handlerList.empty()) {
878 intervalToTimers_.erase(target->interval_);
879 }
880
881 return TIMER_ERR_OK;
882 }
883
Unregister(uint32_t timerId)884 void Timer::Unregister(uint32_t timerId)
885 {
886 BENCHMARK_LOGD("EventTest void Timer::Unregister is called.");
887 std::lock_guard<std::mutex> lock(mutex_);
888
889 if (timerHandlers_.find(timerId) == timerHandlers_.end()) {
890 BENCHMARK_LOGD("||%{public}d||Unregister failed. timer-id:%{public}d not found.", gettid(), timerId);
891 return;
892 }
893
894 auto entry = timerHandlers_[timerId];
895 BENCHMARK_LOGD("||%{public}d||Try remove timer handler from reactor. timerId:%{public}d, interval:%{public}u",
896 gettid(), timerId, entry->interval_);
897
898 if (CancelTimer(entry) != TIMER_ERR_OK) {
899 BENCHMARK_LOGD("||%{public}d||Unregister timer handler failed.", gettid());
900 }
901 }
902
OnTimer(TimerEventHandler * handler,const TimerCallback & callback)903 void Timer::OnTimer(TimerEventHandler* handler, const TimerCallback& callback)
904 {
905 BENCHMARK_LOGD("EventTest void Timer::OnTimer is called.");
906 callback();
907
908 if (handler->once_) {
909 Unregister(handler->timerId_);
910 }
911 }
912
GetValidId() const913 uint32_t Timer::GetValidId() const
914 {
915 BENCHMARK_LOGD("EventTest uint32_t Timer::GetValidId is called.");
916 static std::atomic_uint32_t timerId = 1;
917
918 while (timerHandlers_.find(timerId) != timerHandlers_.end()) {
919 timerId++;
920 if (timerId == UINT32_MAX) {
921 timerId = 1;
922 }
923
924 if (timerId == TIMER_ERR_DEAL_FAILED) {
925 timerId++;
926 }
927 }
928
929 return timerId;
930 }
931
GetTimerFd(uint32_t interval)932 int Timer::GetTimerFd(uint32_t interval /* ms */)
933 {
934 BENCHMARK_LOGD("EventTest int Timer::GetTimerFd is called.");
935 if (intervalToTimers_.find(interval) == intervalToTimers_.end()) {
936 return IO_EVENT_INVALID_FD;
937 }
938 auto &handlerList = intervalToTimers_[interval];
939 for (const TimerHandlerPtr &ptr : handlerList) {
940 if (!ptr->once_) {
941 return ptr->GetTimerFd();
942 }
943 }
944 return IO_EVENT_INVALID_FD;
945 }
946
TimerEventHandler(int timerFd,uint32_t timeout,bool once)947 TimerEventHandler::TimerEventHandler(int timerFd, uint32_t timeout /* ms */, bool once)
948 : once_(once), interval_(timeout)
949 {
950 BENCHMARK_LOGD("EventTest : once_(once), interval_ is called.");
951 if (timerFd == IO_EVENT_INVALID_FD) {
952 handler_ = std::make_unique<IOEventHandler>(timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC));
953 } else {
954 handler_ = std::make_unique<IOEventHandler>(timerFd);
955 }
956 }
957
~TimerEventHandler()958 TimerEventHandler::~TimerEventHandler()
959 {
960 BENCHMARK_LOGD("EventTest TimerEventHandler::~TimerEventHandler is called.");
961 if (close(handler_->GetFd()) != 0) {
962 BENCHMARK_LOGD("||%{public}d||Close timer-fd failed. fd:%{public}d, interval:%{public}u, once:%{public}d",
963 gettid(), handler_->GetFd(), interval_, once_);
964 }
965 handler_->SetFd(IO_EVENT_INVALID_FD);
966 }
967
Initialize()968 ErrCode TimerEventHandler::Initialize()
969 {
970 BENCHMARK_LOGD("EventTest ErrCode TimerEventHandler::Initialize is called.");
971 if (handler_->GetFd() == IO_EVENT_INVALID_FD) {
972 BENCHMARK_LOGD("||%{public}d||Invalid timer-fd:%{public}d, interval:%{public}u, once:%{public}d",
973 gettid(), handler_->GetFd(), interval_, once_);
974 return TIMER_ERR_INVALID_VALUE;
975 }
976
977 struct itimerspec newValue = {{0, 0}, {0, 0}};
978 timespec now{0, 0};
979 if (clock_gettime(CLOCK_MONOTONIC, &now) == INVALID_FD) {
980 BENCHMARK_LOGD("||%{public}d||Get current time failed.", gettid());
981 return TIMER_ERR_DEAL_FAILED;
982 }
983
984 // next time out time is now + interval
985 newValue.it_value.tv_sec = now.tv_sec + interval_ / MILLI_TO_BASE;
986 newValue.it_value.tv_nsec = now.tv_nsec + (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO;
987 if (newValue.it_value.tv_nsec >= NANO_TO_BASE) {
988 newValue.it_value.tv_sec += 1;
989 newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE;
990 }
991
992 if (once_) {
993 // interval, 0 means time out only once
994 newValue.it_interval.tv_sec = 0;
995 newValue.it_interval.tv_nsec = 0;
996 } else {
997 // interval
998 newValue.it_interval.tv_sec = interval_ / MILLI_TO_BASE;
999 newValue.it_interval.tv_nsec = (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO;
1000 }
1001
1002 if (timerfd_settime(handler_->GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == INVALID_FD) {
1003 BENCHMARK_LOGD("||%{public}d||Set timer-fd failed. next:%{public}lld, interval:%{public}lld",
1004 gettid(), static_cast<long long>(newValue.it_value.tv_sec),
1005 static_cast<long long>(newValue.it_interval.tv_sec));
1006
1007 return TIMER_ERR_DEAL_FAILED;
1008 }
1009
1010 handler_->SetCallback(std::bind(&TimerEventHandler::TimeOut, this));
1011 handler_->EnableRead();
1012
1013 return TIMER_ERR_OK;
1014 }
1015
Uninitialize()1016 void TimerEventHandler::Uninitialize()
1017 {
1018 BENCHMARK_LOGD("EventTest void TimerEventHandler::Uninitialize is called.");
1019 handler_->DisableAll();
1020 }
1021
Start(IOEventReactor * reactor)1022 bool TimerEventHandler::Start(IOEventReactor* reactor)
1023 {
1024 BENCHMARK_LOGD("EventTest bool TimerEventHandler::Start is called.");
1025 if (handler_ == nullptr || !handler_->Start(reactor)) {
1026 return false;
1027 }
1028
1029 return true;
1030 }
1031
Stop(IOEventReactor * reactor)1032 bool TimerEventHandler::Stop(IOEventReactor* reactor)
1033 {
1034 BENCHMARK_LOGD("EventTest bool TimerEventHandler::Stop is called.");
1035 if (handler_ == nullptr || !handler_->Stop(reactor)) {
1036 return false;
1037 }
1038
1039 return true;
1040 }
1041
TimeOut()1042 void TimerEventHandler::TimeOut()
1043 {
1044 if (handler_->GetFd() == IO_EVENT_INVALID_FD) {
1045 BENCHMARK_LOGD("||%{public}d||Invalid timerfd.", gettid());
1046 return;
1047 }
1048 uint64_t expirations = 0;
1049 const size_t expirationSize = sizeof(expirations);
1050 ssize_t n = ::read(handler_->GetFd(), &expirations, expirationSize);
1051 if (n != expirationSize) {
1052 BENCHMARK_LOGD("||%{public}d||Reads %{public}d bytes instead of %{public}zu from timer fd.",
1053 gettid(), static_cast<int>(n), expirationSize);
1054 }
1055
1056 if (timerEventCallback_) {
1057 timerEventCallback_(this);
1058 }
1059 }
1060
1061
CurMs()1062 int64_t CurMs()
1063 {
1064 struct timeval tpend;
1065 gettimeofday(&tpend, nullptr);
1066 return (tpend.tv_sec * 1000000 + tpend.tv_usec) / 1000; // 1000000: s to us, 1000: us to ms
1067 }
1068
1069 std::atomic<int> g_data1(0);
TimeOutCallback1()1070 void TimeOutCallback1()
1071 {
1072 g_data1 = g_data1 + 1;
1073 }
1074
1075 std::atomic<int> g_data2(0);
TimeOutCallback2()1076 void TimeOutCallback2()
1077 {
1078 g_data2 += 1;
1079 }
1080
1081 /*
1082 * @tc.name: testNewTimer001
1083 * @tc.desc: test basic function of timer implemented by new event-system.
1084 */
BENCHMARK_F(BenchmarkEventTest,testNewTimer001)1085 BENCHMARK_F(BenchmarkEventTest, testNewTimer001)(benchmark::State& state)
1086 {
1087 BENCHMARK_LOGD("EventTest testNewTimer001 start.");
1088 const int sleepDurationMs = 15;
1089 while (state.KeepRunning()) {
1090 g_data1 = 0;
1091 Timer timer("test_timer", 100);
1092 uint32_t ret = timer.Setup();
1093 AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state);
1094 timer.Register(TimeOutCallback1, 1, true);
1095 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1096 timer.Shutdown();
1097 AssertEqual(1, g_data1, "1 did not equal g_data1 as expected.", state);
1098 }
1099 BENCHMARK_LOGD("EventTest testNewTimer001 end.");
1100 }
1101
1102 /*
1103 * @tc.name: testNewTimer002
1104 * @tc.desc: test basic function of timer implemented by new event-system.
1105 */
BENCHMARK_F(BenchmarkEventTest,testNewTimer002)1106 BENCHMARK_F(BenchmarkEventTest, testNewTimer002)(benchmark::State& state)
1107 {
1108 BENCHMARK_LOGD("EventTest testNewTimer002 start.");
1109 constexpr uint32_t sleepDurationMs = 200;
1110 constexpr int expectedData1 = 8;
1111 constexpr int expectedData2 = 2;
1112 while (state.KeepRunning()) {
1113 g_data1 = 0;
1114 g_data2 = 0;
1115 Timer timer("test_timer", 50);
1116 uint32_t ret = timer.Setup();
1117 AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state);
1118 timer.Register(TimeOutCallback1, TIMEOUT_ONE_MS);
1119 timer.Register(TimeOutCallback2, TIMEOUT_TWO_MS);
1120 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1121 timer.Shutdown();
1122 AssertGreaterThanOrEqual(g_data1, expectedData1,
1123 "g_data1 was not greater than or equal to expectedData1 as expected.", state);
1124 AssertGreaterThanOrEqual(g_data2, expectedData2,
1125 "g_data2 was not greater than or equal to expectedData2 as expected.", state);
1126 }
1127 BENCHMARK_LOGD("EventTest testNewTimer002 end.");
1128 }
1129
1130 /*
1131 * @tc.name: testNewTimer003
1132 * @tc.desc: test basic function of timer implemented by new event-system.
1133 */
BENCHMARK_F(BenchmarkEventTest,testNewTimer003)1134 BENCHMARK_F(BenchmarkEventTest, testNewTimer003)(benchmark::State& state)
1135 {
1136 BENCHMARK_LOGD("EventTest testNewTimer003 start.");
1137 constexpr uint32_t sleepDurationMs = 30;
1138 constexpr int expectedData = 5;
1139 while (state.KeepRunning()) {
1140 g_data1 = 0;
1141 Timer timer("test_timer", 100);
1142 uint32_t ret = timer.Setup();
1143 AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state);
1144 timer.Register(TimeOutCallback1, TIMEOUT_ONE_MS);
1145 timer.Register(TimeOutCallback1, TIMEOUT_TWO_MS);
1146 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1147 timer.Shutdown();
1148 AssertGreaterThanOrEqual(g_data1, expectedData,
1149 "g_data1 was not greater than or equal to expectedData as expected.", state);
1150 }
1151 BENCHMARK_LOGD("EventTest testNewTimer003 end.");
1152 }
1153
1154 class A {
1155 public:
A(int data)1156 explicit A(int data) : data_(data), timer_("ATimer", 100) {}
1157 ~A() = default;
1158 bool Init();
1159 bool StartTimer(int milliseconds, bool once);
1160 void StopTimer();
GetData() const1161 int GetData() const {return data_;}
1162 private:
TimeOutProc()1163 void TimeOutProc()
1164 {
1165 data_ = data_ - 1;
1166 };
1167 int data_;
1168 Timer timer_;
1169 };
1170
Init()1171 bool A::Init()
1172 {
1173 BENCHMARK_LOGD("EventTest bool A::Init is called.");
1174 return timer_.Setup() == Utils::TIMER_ERR_OK;
1175 }
1176
StartTimer(int milliseconds,bool once)1177 bool A::StartTimer(int milliseconds, bool once)
1178 {
1179 BENCHMARK_LOGD("EventTest bool A::StartTimer is called.");
1180 uint32_t timerId = timer_.Register(std::bind(&A::TimeOutProc, this), milliseconds, once);
1181 return timerId != Utils::TIMER_ERR_DEAL_FAILED;
1182 }
1183
StopTimer()1184 void A::StopTimer()
1185 {
1186 BENCHMARK_LOGD("EventTest void A::StopTimer is called.");
1187 timer_.Shutdown();
1188 }
1189
1190 /*
1191 * @tc.name: testNewTimer004
1192 * @tc.desc: test wrapper of the timer implemented by new event-system.
1193 */
BENCHMARK_F(BenchmarkEventTest,testNewTimer004)1194 BENCHMARK_F(BenchmarkEventTest, testNewTimer004)(benchmark::State& state)
1195 {
1196 BENCHMARK_LOGD("EventTest testNewTimer004 start.");
1197 constexpr int initialValue = 10;
1198 constexpr int timeoutSeconds = 1;
1199 constexpr int sleepDurationMs = 20;
1200 constexpr int expectedData = 9;
1201 while (state.KeepRunning()) {
1202 A a(initialValue);
1203 AssertTrue((a.Init()), "a.Init() did not equal true as expected.", state);
1204 AssertTrue((a.StartTimer(timeoutSeconds, true)),
1205 "a.StartTimer(timeoutSeconds, true) did not equal true as expected.", state);
1206 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1207 a.StopTimer();
1208 AssertEqual(expectedData, a.GetData(), "expectedData did not equal a.GetData() as expected.", state);
1209 }
1210 BENCHMARK_LOGD("EventTest testNewTimer004 end.");
1211 }
1212
1213 /*
1214 * @tc.name: testNewTimer005
1215 * @tc.desc: test abnormal case of timer implemented by new event-system.
1216 */
BENCHMARK_F(BenchmarkEventTest,testNewTimer005)1217 BENCHMARK_F(BenchmarkEventTest, testNewTimer005)(benchmark::State& state)
1218 {
1219 BENCHMARK_LOGD("EventTest testNewTimer005 start.");
1220 constexpr uint32_t loopCount = 10;
1221 constexpr uint32_t timeoutSeconds = 7;
1222 constexpr uint32_t sleepDurationMs = 10;
1223 constexpr int expectedData = 5;
1224 while (state.KeepRunning()) {
1225 g_data1 = 0;
1226 Timer timer("test_timer", INVALID_FD);
1227 uint32_t ret = timer.Setup();
1228 AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state);
1229
1230 uint32_t timerId = 0;
1231 for (uint32_t i = 0; i < loopCount; i++) {
1232 timerId = timer.Register(TimeOutCallback1, timeoutSeconds, true);
1233 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1234 }
1235 timer.Unregister(timerId);
1236 timer.Unregister(timerId);
1237
1238 timer.Shutdown();
1239 timer.Shutdown(false);
1240 AssertGreaterThanOrEqual(g_data1, expectedData,
1241 "g_data1 was not greater than or equal to expectedData as expected.", state);
1242 }
1243 BENCHMARK_LOGD("EventTest testNewTimer005 end.");
1244 }
1245
BENCHMARK_F(BenchmarkEventTest,testNewTimer006)1246 BENCHMARK_F(BenchmarkEventTest, testNewTimer006)(benchmark::State& state)
1247 {
1248 BENCHMARK_LOGD("EventTest testNewTimer006 start.");
1249 constexpr uint32_t timeoutSeconds = 10;
1250 constexpr int loopCount = 11;
1251 constexpr int sleepDurationMs = 10;
1252 constexpr int expectedTimeDiff = 10;
1253 constexpr int expectedData = 10;
1254 while (state.KeepRunning()) {
1255 g_data1 = 0;
1256 Timer timer("test_timer", 100);
1257 uint32_t ret = timer.Setup();
1258 AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state);
1259 timer.Register(TimeOutCallback1, timeoutSeconds);
1260
1261 for (int i = 0; i < loopCount; i++) {
1262 int64_t pre = CurMs();
1263 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1264 int64_t cur = CurMs();
1265 AssertGreaterThanOrEqual(cur - pre, expectedTimeDiff,
1266 "cur - pre was not greater than or equal to expectedTimeDiff as expected.", state);
1267 }
1268 timer.Shutdown();
1269 AssertGreaterThanOrEqual(g_data1, expectedData,
1270 "g_data1 was not greater than or equal to expectedData as expected.", state);
1271 }
1272 BENCHMARK_LOGD("EventTest testNewTimer006 end.");
1273 }
1274
1275 constexpr int RECURSION_DEPTH = 9;
1276 constexpr int INTERVAL_SECONDS = 10;
1277
1278 /*
1279 * @tc.name: testNewTimer007
1280 * @tc.desc: recursive test of timer implemented by new event-system.
1281 */
DoFunc(Timer & timer,int & count)1282 void DoFunc(Timer &timer, int &count)
1283 {
1284 BENCHMARK_LOGD("EventTest void DoFunc is called.");
1285 (void)timer.Register(
1286 [&timer, &count]() {
1287 count += 1;
1288 if (count > RECURSION_DEPTH) {
1289 return;
1290 }
1291 DoFunc(timer, count);
1292 },
1293 INTERVAL_SECONDS, true);
1294 g_data1++;
1295 }
1296
DoFunc2(Timer & timer,int & count)1297 void DoFunc2(Timer &timer, int &count)
1298 {
1299 BENCHMARK_LOGD("EventTest void DoFunc2 is called.");
1300 (void)timer.Register(
1301 [&timer, &count]() {
1302 count += 1;
1303 if (count > RECURSION_DEPTH) {
1304 return;
1305 }
1306 DoFunc2(timer, count);
1307 },
1308 INTERVAL_SECONDS, true);
1309 g_data1++;
1310 }
1311
BENCHMARK_F(BenchmarkEventTest,testNewTimer007)1312 BENCHMARK_F(BenchmarkEventTest, testNewTimer007)(benchmark::State& state)
1313 {
1314 BENCHMARK_LOGD("EventTest testNewTimer007 start.");
1315 constexpr int expectedMinData = 5;
1316 constexpr int expectedMaxData = 14;
1317 constexpr int expectedMinDataAfterShutdown = 10;
1318 constexpr int sleepDurationMs = 50;
1319 while (state.KeepRunning()) {
1320 g_data1 = 0;
1321 Timer timer("test_timer", 100);
1322 uint32_t ret = timer.Setup();
1323 AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state);
1324
1325 int cnt = 0, cnt1 = 0;
1326 DoFunc(timer, cnt);
1327 DoFunc2(timer, cnt1);
1328 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1329 AssertGreaterThanOrEqual(g_data1, expectedMinData,
1330 "g_data1 was not greater than or equal to expectedMinData as expected.", state);
1331 AssertGreaterThanOrEqual(expectedMaxData, g_data1,
1332 "expectedMaxData was not greater than or equal to g_data1 as expected.", state);
1333 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1334 timer.Shutdown();
1335 AssertGreaterThanOrEqual(g_data1, expectedMinDataAfterShutdown,
1336 "g_data1 was not greater than or equal to expectedMinDataAfterShutdown as expected.", state);
1337 }
1338 BENCHMARK_LOGD("EventTest testNewTimer007 end.");
1339 }
1340
1341 /*
1342 * @tc.name: testNewTimer008
1343 * @tc.desc: test execute-once and execute-periodly tasks.
1344 */
BENCHMARK_F(BenchmarkEventTest,testNewTimer008)1345 BENCHMARK_F(BenchmarkEventTest, testNewTimer008)(benchmark::State& state)
1346 {
1347 BENCHMARK_LOGD("EventTest testNewTimer008 start.");
1348 constexpr int intervalSeconds = 10;
1349 constexpr int sleepDurationMs = 52;
1350 constexpr int expectedMinData = 8;
1351 while (state.KeepRunning()) {
1352 g_data1 = 0;
1353 Timer timer("test_timer", 100);
1354 uint32_t ret = timer.Setup();
1355 AssertEqual(Utils::TIMER_ERR_OK, ret, "Utils::TIMER_ERR_OK did not equal ret as expected.", state);
1356 timer.Register(TimeOutCallback1, intervalSeconds, true);
1357 timer.Register(TimeOutCallback1, intervalSeconds);
1358 timer.Register(TimeOutCallback1, intervalSeconds, true);
1359 timer.Register(TimeOutCallback1, intervalSeconds);
1360 std::this_thread::sleep_for(std::chrono::milliseconds(sleepDurationMs));
1361 timer.Shutdown();
1362 AssertGreaterThanOrEqual(g_data1, expectedMinData,
1363 "g_data1 was not greater than or equal to expectedMinData as expected.", state);
1364 }
1365 BENCHMARK_LOGD("EventTest testNewTimer008 end.");
1366 }
1367
1368 /*
1369 * @tc.name: testIOEventHandlerConstruction001
1370 * @tc.desc: test construction of IOEventHandler.
1371 */
BENCHMARK_F(BenchmarkEventTest,testIOEventHandlerConstruction001)1372 BENCHMARK_F(BenchmarkEventTest, testIOEventHandlerConstruction001)(benchmark::State& state)
1373 {
1374 BENCHMARK_LOGD("EventTest testIOEventHandlerConstruction001 start.");
1375 while (state.KeepRunning()) {
1376 // 1. Construct IOEventHandler
1377 std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>();
1378
1379 // 2. Check initialization
1380 AssertEqual(handler->GetFd(), IO_EVENT_INVALID_FD,
1381 "handler->GetFd() did not equal IO_EVENT_INVALID_FD as expected.", state);
1382 AssertEqual(handler->GetEvents(), Events::EVENT_NONE,
1383 "handler->GetEvents() did not equal Events::EVENT_NONE as expected.", state);
1384 AssertEqual(handler->GetCallback(), nullptr,
1385 "handler->GetCallback() was not equal to nullptr as expected.", state);
1386 AssertEqual(handler->Prev(), nullptr, "handler->Prev() was not equal to nullptr as expected.", state);
1387 AssertEqual(handler->Next(), nullptr, "handler->Next() was not equal to nullptr as expected.", state);
1388 AssertEqual(handler->IsActive(), false, "handler->IsActive() was not equal to false as expected.", state);
1389 }
1390 BENCHMARK_LOGD("EventTest testIOEventHandlerConstruction001 end.");
1391 }
1392
1393 /*
1394 * @tc.name: testIOEventHandlerConstructionWithParameters001
1395 * @tc.desc: test construction of IOEventHandler with parameters.
1396 */
BENCHMARK_F(BenchmarkEventTest,testIOEventHandlerConstructionWithParameters001)1397 BENCHMARK_F(BenchmarkEventTest, testIOEventHandlerConstructionWithParameters001)(benchmark::State& state)
1398 {
1399 BENCHMARK_LOGD("EventTest testIOEventHandlerConstructionWithParameters001 start.");
1400 while (state.KeepRunning()) {
1401 // 1. Define file descriptor and events
1402 int fd = 10;
1403 EventId events = Events::EVENT_READ;
1404
1405 // 2. Construct IOEventHandler with parameters
1406 std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(fd, events);
1407
1408 // 3. Check initialization
1409 AssertEqual(handler->GetFd(), fd, "handler->GetFd() did not equal fd as expected.", state);
1410 AssertEqual(handler->GetEvents(), events, "handler->GetEvents() did not equal events as expected.", state);
1411 AssertEqual(handler->Prev(), nullptr, "handler->Prev() was not equal to nullptr as expected.", state);
1412 AssertEqual(handler->Next(), nullptr, "handler->Next() was not equal to nullptr as expected.", state);
1413 AssertEqual(handler->IsActive(), false, "handler->IsActive() was not equal to false as expected.", state);
1414 }
1415 BENCHMARK_LOGD("EventTest testIOEventHandlerConstructionWithParameters001 end.");
1416 }
1417
1418 /*
1419 * @tc.name: testIOEventHandlerConstructor001
1420 * @tc.desc: test construction of IOEventHandler.
1421 */
BENCHMARK_F(BenchmarkEventTest,testIOEventHandlerConstructor001)1422 BENCHMARK_F(BenchmarkEventTest, testIOEventHandlerConstructor001)(benchmark::State& state)
1423 {
1424 BENCHMARK_LOGD("EventTest testIOEventHandlerConstructor001 start.");
1425 while (state.KeepRunning()) {
1426 // 1. Define file descriptor and events
1427 int fd = 10;
1428 EventId events = Events::EVENT_READ;
1429
1430 // 2. Construct IOEventHandler with parameters and measure the time
1431 std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(fd, events);
1432
1433 // 3. Check if the handler is constructed correctly
1434 AssertEqual(handler->GetFd(), fd, "handler->GetFd() did not equal fd as expected.", state);
1435 AssertEqual(handler->GetEvents(), events, "handler->GetEvents() did not equal events as expected.", state);
1436 }
1437 BENCHMARK_LOGD("EventTest testIOEventHandlerConstructor001 end.");
1438 }
1439 } // namespace
1440 } // namespace OHOS
1441 // Run the benchmark
1442 BENCHMARK_MAIN();
1443