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 <gtest/gtest.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 
38 using namespace testing::ext;
39 using namespace OHOS::Utils;
40 
41 namespace OHOS {
42 namespace {
43 
44 class UtilsEventTest : public testing::Test {
45 public:
SetUpTestCase(void)46     static void SetUpTestCase(void) {}
TearDownTestCase(void)47     static void TearDownTestCase(void) {}
SetUp()48     void SetUp() {}
TearDown()49     void TearDown() {}
50 };
51 
52 int g_data = 0;
TimerCallback1()53 void TimerCallback1()
54 {
55     std::cout << "timer callback1 invoked." << std::endl;
56     g_data++;
57 }
58 
59 static const int MILLI_TO_BASE = 1000;
60 static const int NANO_TO_BASE = 1000000000;
61 static constexpr int MILLI_TO_NANO = NANO_TO_BASE / MILLI_TO_BASE;
62 class TimerFdHandler : public IOEventHandler {
63 public:
64     using TimerEventCallback = std::function<void()>;
65     TimerFdHandler(int fd, const TimerEventCallback& cb);
~TimerFdHandler()66     ~TimerFdHandler() {}
67     void TimeOut();
68     bool Initialize(uint32_t interval);
69     void Uninitialize();
70 
71 private:
72     TimerEventCallback timerCallback_;
73 };
74 
TestCallback()75 void TestCallback() {}
76 
77 /*
78  * @tc.name: testIOEventHandler001
79  * @tc.desc: test basic interfaces of IOEventHandler.
80  */
81 HWTEST_F(UtilsEventTest, testIOEventHandler001, TestSize.Level0)
82 {
83     g_data = 0;
84     // 1. Create io event handler
85     std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(-1);
86 
87     // 2. Set fd
88     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
89     ASSERT_NE(fd, -1);
90     handler->SetFd(fd);
91     EXPECT_EQ(handler->GetFd(), fd);
92 
93     // 3. Set callback
94     handler->SetCallback(&TestCallback);
95     EXPECT_NE(handler->GetCallback(), nullptr);
96 
97     // 4. Set interest events
98     handler->SetEvents(Events::EVENT_READ | Events::EVENT_WRITE);
99     EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ | Events::EVENT_WRITE);
100 
101     // 5. Check status
102     EXPECT_EQ(handler->Prev(), nullptr);
103     EXPECT_EQ(handler->Next(), nullptr);
104     EXPECT_EQ(handler->IsActive(), false);
105 
106     // 6. disable events
107     handler->DisableAll();
108     EXPECT_EQ(handler->GetEvents(), Events::EVENT_NONE);
109 
110     // 7. enable events
111     handler->EnableRead();
112     handler->EnableWrite();
113     EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ | Events::EVENT_WRITE);
114 
115     // 8. disable one of the events
116     handler->DisableWrite();
117     EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ);
118 }
119 
120 /*
121  * @tc.name: testIOEventHandler002
122  * @tc.desc: test reactor-related interfaces of IOEventHandler.
123  */
124 HWTEST_F(UtilsEventTest, testIOEventHandler002, TestSize.Level0)
125 {
126     g_data = 0;
127     // 1. Create io event handler
128     std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(-1);
129 
130     // 2. Set fd
131     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
132     ASSERT_NE(fd, -1);
133     handler->SetFd(fd);
134     EXPECT_EQ(handler->GetFd(), fd);
135 
136     // 3. Set callback
137     handler->SetCallback(&TestCallback);
138     EXPECT_NE(handler->GetCallback(), nullptr);
139 
140     // 4. Set interest events
141     handler->EnableRead();
142     EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ);
143 
144     // 5. Create a reactor but not run
145     std::shared_ptr<IOEventReactor> reactor = std::make_shared<IOEventReactor>();
146     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
147 
148     // 6. Start handler
149     handler->Start(reactor.get());
150     EXPECT_EQ(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_OK);
151 
152     // 7. Change setting and update handler to the reactor
153     handler->EnableWrite();
154     EXPECT_TRUE(handler->Update(reactor.get()));
155 
156     // 8. Remove the handler
157     handler->Stop(reactor.get());
158     EXPECT_EQ(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_NOT_FOUND);
159 
160     // 9. Add handler, then delete handler. handler will remove itself from the reactor during deconstruction.
161     ASSERT_TRUE(handler->Start(reactor.get()));
162     handler.reset();
163 }
164 
165 /*
166  * @tc.name: testIOEventReactor001
167  * @tc.desc: test basic interfaces of IOEventReactor.
168  */
169 HWTEST_F(UtilsEventTest, testIOEventReactor001, TestSize.Level0)
170 {
171     g_data = 0;
172     // Get fd
173     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
174     ASSERT_NE(fd, -1);
175 
176     // 1. Create io event handlers
177     std::shared_ptr<IOEventHandler> handler1 = std::make_shared<IOEventHandler>(fd);
178     std::shared_ptr<IOEventHandler> handler2 = std::make_shared<IOEventHandler>(fd);
179     std::shared_ptr<IOEventHandler> handler3 = std::make_shared<IOEventHandler>(-1); // -1: invalid fd
180     std::shared_ptr<IOEventHandler> handler4 = std::make_shared<IOEventHandler>(fd);
181 
182     // 2. Create a reactor but not run
183     std::shared_ptr<IOEventReactor> reactor = std::make_shared<IOEventReactor>();
184     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
185 
186     // 3. Add handler
187     EXPECT_EQ(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK);
188     EXPECT_EQ(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK);
189     EXPECT_NE(reactor->AddHandler(handler3.get()), EVENT_SYS_ERR_OK);
190     EXPECT_NE(reactor->AddHandler(nullptr), EVENT_SYS_ERR_OK);
191 
192     // 4. Add handler from the handler side.
193     EXPECT_NE(handler1->Start(reactor.get()), EVENT_SYS_ERR_OK); // already started.
194     EXPECT_NE(handler3->Start(reactor.get()), EVENT_SYS_ERR_OK); // Bad fd.
195 
196     // 5. Remove handler
197     EXPECT_NE(reactor->RemoveHandler(nullptr), EVENT_SYS_ERR_OK);
198     EXPECT_NE(reactor->RemoveHandler(handler3.get()), EVENT_SYS_ERR_OK); // Bad fd.
199     EXPECT_NE(reactor->RemoveHandler(handler4.get()), EVENT_SYS_ERR_OK);
200     EXPECT_EQ(reactor->RemoveHandler(handler2.get()), EVENT_SYS_ERR_OK);
201 
202     // 6. Remove handler from the handler side.
203     EXPECT_NE(handler2->Stop(reactor.get()), EVENT_SYS_ERR_OK); // Not found.
204 
205     // 7. Update handler
206     EXPECT_NE(reactor->UpdateHandler(nullptr), EVENT_SYS_ERR_OK);
207     EXPECT_NE(reactor->UpdateHandler(handler3.get()), EVENT_SYS_ERR_OK);
208     EXPECT_EQ(reactor->UpdateHandler(handler1.get()), EVENT_SYS_ERR_OK);
209     EXPECT_EQ(reactor->UpdateHandler(handler4.get()), EVENT_SYS_ERR_OK);
210 
211     // 8. Update handler from the handler side.
212     EXPECT_NE(handler2->Update(reactor.get()), EVENT_SYS_ERR_OK); // Not found.
213     EXPECT_NE(handler3->Update(reactor.get()), EVENT_SYS_ERR_OK); // Bad fd.
214 
215     // 9. Find handler
216     EXPECT_NE(reactor->FindHandler(nullptr), EVENT_SYS_ERR_OK);
217     EXPECT_NE(reactor->FindHandler(handler3.get()), EVENT_SYS_ERR_OK);
218 
219     // 10. Clean handler
220     EXPECT_NE(reactor->Clean(-1), EVENT_SYS_ERR_OK);
221     EXPECT_EQ(reactor->Clean(fd), EVENT_SYS_ERR_OK);
222 }
223 
224 /*
225  * @tc.name: testIOEventReactor002
226  * @tc.desc: test change event but not update.
227  */
228 HWTEST_F(UtilsEventTest, testIOEventReactor002, TestSize.Level0)
229 {
230     g_data = 0;
231     // 1. Open timer
232     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
233     ASSERT_NE(fd, -1);
234 
235     // 2. Create io event handlers
236     std::shared_ptr<IOEventHandler> handler1 = std::make_shared<IOEventHandler>(fd);
237     std::shared_ptr<IOEventHandler> handler2 = std::make_shared<IOEventHandler>(fd);
238 
239     // 3. Create a reactor but not run
240     std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
241     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
242 
243     // 4. Add handler
244     EXPECT_EQ(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK);
245     EXPECT_EQ(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK);
246 
247     // 5. release one handler
248     handler2.reset(); // will be removed from the inner list.
249 }
250 
TimerFdHandler(int fd,const TimerEventCallback & cb)251 TimerFdHandler::TimerFdHandler(int fd, const TimerEventCallback& cb)
252     : IOEventHandler(fd),  timerCallback_(cb) {}
253 
Initialize(uint32_t interval)254 bool TimerFdHandler::Initialize(uint32_t interval)
255 {
256     if ((GetFd() == -1)) {
257         return false;
258     }
259 
260     struct itimerspec newValue = {{0, 0}, {0, 0}};
261     timespec now{0, 0};
262     if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) {
263         return false;
264     }
265 
266     // next time out time is now + interval
267     newValue.it_value.tv_sec = now.tv_sec + interval / MILLI_TO_BASE;
268     newValue.it_value.tv_nsec = now.tv_nsec + (interval % MILLI_TO_BASE) * MILLI_TO_NANO;
269     if (newValue.it_value.tv_nsec >= NANO_TO_BASE) {
270         newValue.it_value.tv_sec = newValue.it_value.tv_sec + 1;
271         newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE;
272     }
273 
274     // interval
275     newValue.it_interval.tv_sec  = interval / MILLI_TO_BASE;
276     newValue.it_interval.tv_nsec = (interval % MILLI_TO_BASE) * MILLI_TO_NANO;
277 
278     if (timerfd_settime(GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == -1) {
279         std::cout << "Set timerFd failed-" << strerror(errno) << "timer_fd:" << GetFd() << ", next_time:" <<
280                   newValue.it_value.tv_sec << ", interval:" << newValue.it_interval.tv_sec << std::endl;
281         return false;
282     }
283 
284     EnableRead();
285     SetCallback(std::bind(&TimerFdHandler::TimeOut, this));
286 
287     return true;
288 }
289 
Uninitialize()290 void TimerFdHandler::Uninitialize()
291 {
292     DisableAll();
293 }
294 
TimeOut()295 void TimerFdHandler::TimeOut()
296 {
297     if (GetFd() == -1) {
298         std::cout << "Invalid timer_fd." << std::endl;
299         return;
300     }
301     uint64_t expirations = 0;
302     ssize_t n = ::read(GetFd(), &expirations, sizeof(expirations));
303     if (n != sizeof(expirations)) {
304         std::cout << "reads " << static_cast<int>(n) << "bytes instead of 8." << std::endl;
305     }
306 
307     if (timerCallback_) {
308         timerCallback_();
309     }
310 }
311 
InitAndRun(std::shared_ptr<TimerFdHandler> & handler,const uint32_t interval,std::unique_ptr<IOEventReactor> & reactor,std::thread & loopThread)312 static void InitAndRun(std::shared_ptr<TimerFdHandler>& handler, const uint32_t interval,
313                        std::unique_ptr<IOEventReactor>& reactor, std::thread& loopThread)
314 {
315     // Initialize timer handler and add it to reactor
316     ASSERT_TRUE(handler->Initialize(interval));
317     ASSERT_TRUE(handler->Start(reactor.get()));
318 
319     // Run event loop
320     loopThread = std::thread([&reactor] {
321         reactor->Run(-1);
322     }
323     );
324 }
325 
326 /*
327  * @tc.name: testEvent001
328  * @tc.desc: test handling event of timerfd.
329  */
330 HWTEST_F(UtilsEventTest, testEvent001, TestSize.Level0)
331 {
332     g_data = 0;
333     // 1. Open timer
334     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
335     ASSERT_NE(fd, -1);
336     // 2. Create timer event handler
337     std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
338 
339     // 3. Create reactor for event loop
340     std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
341     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
342     reactor->EnableHandling();
343 
344     // 4. Initialize timer handler and add it to reactor. Run event loop
345     uint32_t interval = 10;
346     std::thread loopThread;
347     InitAndRun(handler, interval, reactor, loopThread);
348 
349     // 5. Wait for event handling
350     std::this_thread::sleep_for(std::chrono::milliseconds(16));
351 
352     // 6. Check result, execute once at least
353     EXPECT_GE(g_data, 1);
354 
355     // 7. terminate the event-loop (aka Run())
356     reactor->Terminate();
357     loopThread.join();
358 }
359 
360 /*
361  * @tc.name: testEvent002
362  * @tc.desc: test changing event to EVENT_NONE.
363  */
364 HWTEST_F(UtilsEventTest, testEvent002, TestSize.Level0)
365 {
366     g_data = 0;
367     // 1. Open timer
368     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
369     ASSERT_NE(fd, -1);
370     // 2. Create timer event handler
371     std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
372 
373     // 3. Create reactor for event loop
374     std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
375     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
376 
377     // 4. Initialize timer handler and add it to reactor. Run event loop
378     uint32_t interval = 10;
379     std::thread loopThread;
380     InitAndRun(handler, interval, reactor, loopThread);
381 
382     // 5. Change settings
383     reactor->DisableHandling();
384     std::this_thread::sleep_for(std::chrono::milliseconds(1));
385     reactor->EnableHandling();
386     handler->SetEvents(Events::EVENT_NONE);
387 
388     // 6. Wait for event handling
389     std::this_thread::sleep_for(std::chrono::milliseconds(16));
390 
391     // 7. Check result, no execution
392     EXPECT_EQ(g_data, 0);
393 
394     // 8. terminate the event-loop (aka Run())
395     reactor->Terminate();
396     loopThread.join();
397 }
398 
399 /*
400  * @tc.name: testEvent003
401  * @tc.desc: test disable single event.
402  */
403 HWTEST_F(UtilsEventTest, testEvent003, TestSize.Level0)
404 {
405     g_data = 0;
406     // 1. Open timer
407     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
408     ASSERT_NE(fd, -1);
409     // 2. Create timer event handler
410     std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
411 
412     // 3. Create reactor for event loop
413     std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
414     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
415 
416     // 4. Initialize timer handler and add it to reactor. Run event loop
417     uint32_t interval = 10;
418     std::thread loopThread;
419     InitAndRun(handler, interval, reactor, loopThread);
420 
421     // 5. Change settings
422     reactor->EnableHandling();
423     ASSERT_TRUE(handler->Stop(reactor.get())); // block to get lock, so no need to wait.
424 
425     // 6. Check result, no execution
426     EXPECT_EQ(g_data, 0);
427 
428     // 7. terminate the event-loop (aka Run())
429     reactor->Terminate();
430     loopThread.join();
431 }
432 
433 /*
434  * @tc.name: testEvent004
435  * @tc.desc: test removing callback.
436  */
437 HWTEST_F(UtilsEventTest, testEvent004, TestSize.Level0)
438 {
439     g_data = 0;
440     // 1. Open timer
441     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
442     ASSERT_NE(fd, -1);
443     // 2. Create timer event handler
444     std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
445 
446     // 3. Create reactor for event loop
447     std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
448     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
449 
450     // 4. Initialize timer handler and add it to reactor. Run event loop
451     uint32_t interval = 10;
452     std::thread loopThread;
453     InitAndRun(handler, interval, reactor, loopThread);
454 
455     // 5. Change settings
456     reactor->EnableHandling();
457     handler->SetCallback(nullptr);
458 
459     // 6. Wait for event handling
460     std::this_thread::sleep_for(std::chrono::milliseconds(16));
461 
462     // 7. Check result, no execution
463     EXPECT_EQ(g_data, 0);
464 
465     // 8. terminate the event-loop (aka Run())
466     reactor->Terminate();
467     loopThread.join();
468 }
469 
470 /*
471  * @tc.name: testEvent005
472  * @tc.desc: test change event but not update.
473  */
474 HWTEST_F(UtilsEventTest, testEvent005, TestSize.Level0)
475 {
476     g_data = 0;
477     // 1. Open timer
478     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
479     ASSERT_NE(fd, -1);
480     // 2. Create timer event handler
481     std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
482 
483     // 3. Create reactor for event loop
484     std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
485     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
486 
487     // 4. Initialize timer handler and add it to reactor. Run event loop
488     uint32_t interval = 15;
489     std::thread loopThread;
490     InitAndRun(handler, interval, reactor, loopThread);
491 
492     // 5. Change settings but not update
493     handler->SetEvents(Events::EVENT_WRITE);
494     reactor->EnableHandling();
495 
496     // 6. Wait for event handling
497     std::this_thread::sleep_for(std::chrono::milliseconds(16));
498 
499     // 7. Check result, no execution
500     EXPECT_EQ(g_data, 0);
501 
502     // 8. terminate the event-loop (aka Run())
503     reactor->Terminate();
504     loopThread.join();
505 }
506 
507 /*
508  * @tc.name: testEvent006
509  * @tc.desc: test release the handler when started.
510  */
511 HWTEST_F(UtilsEventTest, testEvent006, TestSize.Level0)
512 {
513     g_data = 0;
514     // 1. Open timer
515     int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
516     ASSERT_NE(fd, -1);
517     // 2. Create timer event handler
518     std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1);
519 
520     // 3. Create reactor for event loop
521     std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>();
522     ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK);
523 
524     // 4. Initialize timer handler and add it to reactor. Run event loop
525     uint32_t interval = 15;
526     std::thread loopThread;
527     InitAndRun(handler, interval, reactor, loopThread);
528 
529     // 5. release eventhandler
530     handler.reset();
531     reactor->EnableHandling();
532 
533     // 6. Wait for event handling
534     std::this_thread::sleep_for(std::chrono::milliseconds(16));
535 
536     // 7. Check result, no execution
537     EXPECT_EQ(g_data, 0);
538 
539     // 8. terminate the event-loop (aka Run())
540     reactor->Terminate();
541     loopThread.join();
542 }
543 
544 // Try to substitue underlying implementation of OHOS::UTILS::TIMER
545 class TimerEventHandler {
546 public:
547     using TimerEventCallback = std::function<void(TimerEventHandler*)>;
548     TimerEventHandler(int timerFd, uint32_t timeout, bool once);
549     TimerEventHandler(uint32_t timeout /* ms */, bool once);
550     ~TimerEventHandler();
551 
552     TimerEventHandler(const TimerEventHandler&&) = delete;
553     TimerEventHandler& operator=(const TimerEventHandler&&) = delete;
554     TimerEventHandler(const TimerEventHandler&) = delete;
555     TimerEventHandler& operator=(const TimerEventHandler&) = delete;
556 
557     ErrCode Initialize();
558     void Uninitialize();
559 
560     bool Start(IOEventReactor* reactor);
561     bool Stop(IOEventReactor* reactor);
562 
SetTimerId(const uint32_t & id)563     inline void SetTimerId(const uint32_t& id) { timerId_ = id; }
564 
SetTimerEventCallback(const TimerEventCallback & callback)565     inline void SetTimerEventCallback(const TimerEventCallback& callback) { timerEventCallback_ = callback; }
566 
GetInterval() const567     inline uint32_t GetInterval() const { return interval_; }
GetTimerFd() const568     inline int GetTimerFd() const { return handler_->GetFd(); }
GetTimerId() const569     inline uint32_t GetTimerId() const { return timerId_; }
570 
571 private:
572     void TimeOut();
573 
574 private:
575     bool           once_;
576     uint32_t       timerId_;
577     uint32_t       interval_;
578     std::unique_ptr<IOEventHandler> handler_;
579     TimerEventCallback  timerEventCallback_;
580 
581     friend class Timer;
582 };
583 
584 class Timer {
585 public:
586     using TimerCallback = std::function<void ()>;
587     using TimerCallbackPtr = std::shared_ptr<TimerCallback>;
588     using TimerEventCallback = TimerEventHandler::TimerEventCallback;
589 
590     explicit Timer(const std::string& name, int timeoutMs = 1000);
~Timer()591     virtual ~Timer()
592     {
593     }
594     virtual uint32_t Setup();
595     virtual void Shutdown(bool useJoin = true);
596     uint32_t Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once = false);
597     void Unregister(uint32_t timerId);
598 
599 private:
600     void MainLoop();
601     void OnTimer(TimerEventHandler* handler, const TimerCallback& callback);
602     int GetTimerFd(uint32_t interval /* ms */);
603     uint32_t GetValidId() const;
604     void EraseUnusedTimerId(uint32_t interval, const std::vector<uint32_t>& unusedIds);
605 
606 private:
607     using TimerHandlerPtr = std::shared_ptr<TimerEventHandler>;
608     using TimerHandlerList = std::list<TimerHandlerPtr>;
609 
610     ErrCode ScheduleTimer(const TimerEventCallback& callback, uint32_t interval, uint32_t timerId, int& timerFd,
611                           bool once);
612     void EraseExistNode(TimerHandlerPtr target);
613     ErrCode CancelTimer(TimerHandlerPtr target);
614 
615     std::map<uint32_t, TimerHandlerList> intervalToTimers_;
616     std::map<uint32_t, TimerHandlerPtr> timerHandlers_;
617 
618     std::string name_;
619     int timeoutMs_;
620     std::thread thread_;
621     std::unique_ptr<IOEventReactor> reactor_;
622     std::mutex mutex_;
623 };
624 
Timer(const std::string & name,int timeoutMs)625 Timer::Timer(const std::string& name, int timeoutMs) : name_(name), timeoutMs_(timeoutMs),
626     reactor_(new IOEventReactor()) {}
627 
MainLoop()628 void Timer::MainLoop()
629 {
630     prctl(PR_SET_NAME, name_.c_str(), 0, 0, 0);
631 
632     reactor_->Run(timeoutMs_);
633     std::cout << "||" << gettid() << "||" << "Loop finished" << std::endl;
634 
635     if (reactor_->CleanUp() != EVENT_SYS_ERR_OK) {
636         std::cout << "||" << gettid() << "||" <<
637                   "Reactor Clean Failed. It will clean during deconstruction" << std::endl;
638     }
639 }
640 
Setup()641 uint32_t Timer::Setup()
642 {
643     if (thread_.joinable()) { // avoid double assign to an active thread
644         return TIMER_ERR_INVALID_VALUE;
645     }
646 
647     if (reactor_->SetUp() != EVENT_SYS_ERR_OK) {
648         std::cout << "||" << gettid() << "||" << "Setup reactor failed." << std::endl;
649         return TIMER_ERR_DEAL_FAILED;
650     }
651 
652     reactor_->EnableHandling();
653 
654     std::thread loopThread(std::bind(&Timer::MainLoop, this));
655     thread_.swap(loopThread);
656 
657     return TIMER_ERR_OK;
658 }
659 
Shutdown(bool useJoin)660 void Timer::Shutdown(bool useJoin)
661 {
662     if (!thread_.joinable()) {
663         std::cout << "||" << gettid() << "||" << "Invalid operation. Already shutdown." << std::endl;
664         return;
665     }
666 
667     std::cout << "||" << gettid() << "||" << "Stop reactor." << std::endl;
668     reactor_->Terminate();
669 
670     if (!useJoin) {
671         thread_.detach();
672         return;
673     }
674     thread_.join();
675 }
676 
ScheduleTimer(const TimerEventCallback & callback,uint32_t interval,uint32_t timerId,int & timerFd,bool once)677 ErrCode Timer::ScheduleTimer(const TimerEventCallback& callback, uint32_t interval, uint32_t timerId,
678                              int& timerFd, bool once)
679 {
680     std::shared_ptr<TimerEventHandler> handler = std::make_shared<TimerEventHandler>(timerFd, interval, once);
681 
682     handler->SetTimerId(timerId);
683     handler->SetTimerEventCallback(callback);
684 
685     uint32_t ret = handler->Initialize();
686     if (ret != TIMER_ERR_OK) {
687         std::cout << "||" << gettid() << "||" << "Init timer handler failed." << std::endl;
688         return ret;
689     }
690     if (!handler->Start(reactor_.get())) {
691         std::cout << "||" << gettid() << "||" << "Start timer handler failed." << std::endl;
692         return TIMER_ERR_DEAL_FAILED;
693     }
694     timerHandlers_.emplace(timerId, handler); // Add to the id2handlers map
695     intervalToTimers_[interval].push_back(handler); // Add to interval2handlerlist map
696     timerFd = handler->GetTimerFd();
697     return TIMER_ERR_OK;
698 }
699 
700 
Register(const TimerCallback & callback,uint32_t interval,bool once)701 uint32_t Timer::Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once)
702 {
703     std::lock_guard<std::mutex> lock(mutex_);
704 
705     // wrap the callback in OnTiner
706     TimerEventCallback wrappedCb = std::bind(&Timer::OnTimer, this, std::placeholders::_1, callback);
707     int timerFd = once ? IO_EVENT_INVALID_FD : GetTimerFd(interval); // Get timerFd
708     uint32_t timerId = GetValidId();                        // Get timerId
709 
710     uint32_t ret = ScheduleTimer(wrappedCb, interval, timerId, timerFd, once);
711     if (ret != TIMER_ERR_OK) {
712         std::cout << "||" << gettid() << "||" << "Try schedule task failed. timer-id:" <<
713                   timerId << ", interval:" << interval << "timer-fd:" << timerFd << std::endl;
714         return TIMER_ERR_DEAL_FAILED;
715     }
716 
717     return timerId;
718 }
719 
EraseExistNode(TimerHandlerPtr target)720 void Timer::EraseExistNode(TimerHandlerPtr target)
721 {
722     auto handlerList = intervalToTimers_[target->interval_];
723     auto itor = std::find(handlerList.begin(), handlerList.end(), target);
724     if (itor != handlerList.end()) {
725         handlerList.erase(itor);
726     }
727 
728     if (handlerList.empty()) {
729         intervalToTimers_.erase(target->interval_);
730     }
731 }
732 
CancelTimer(TimerHandlerPtr target)733 ErrCode Timer::CancelTimer(TimerHandlerPtr target)
734 {
735     std::cout << "||" << gettid() << "||" << "Cancle timer handler with fd:" <<  target->GetTimerFd() << std::endl;
736     target->Uninitialize();
737     if (!target->Stop(reactor_.get())) {
738         std::cout << "||" << gettid() << "||" << "Stop timer handler failed." << std::endl;
739         return TIMER_ERR_DEAL_FAILED;
740     }
741     timerHandlers_.erase(target->timerId_);
742     EraseExistNode(target);
743     return TIMER_ERR_OK;
744 }
745 
Unregister(uint32_t timerId)746 void Timer::Unregister(uint32_t timerId)
747 {
748     std::lock_guard<std::mutex> lock(mutex_);
749 
750     if (timerHandlers_.find(timerId) == timerHandlers_.end()) {
751         std::cout << "||" << gettid() << "||" <<
752                   "Unregister failed. timer-id:" << timerId << " not found." << std::endl;
753         return;
754     }
755 
756     auto entry = timerHandlers_[timerId];
757     std::cout << "||" << gettid() << "||" << "Try remove timer handler from reactor. timerId:" << timerId <<
758               ", interval:" << entry->interval_ << std::endl;
759 
760     if (CancelTimer(entry) != TIMER_ERR_OK) {
761         std::cout << "||" << gettid() << "||" << "Unregister timer handler failed." << std::endl;
762     }
763 }
764 
OnTimer(TimerEventHandler * handler,const TimerCallback & callback)765 void Timer::OnTimer(TimerEventHandler* handler, const TimerCallback& callback)
766 {
767     callback();
768 
769     if (handler->once_) {
770         Unregister(handler->timerId_);
771     }
772 }
773 
GetValidId() const774 uint32_t Timer::GetValidId() const
775 {
776     static std::atomic_uint32_t timerId = 1;
777 
778     while (timerHandlers_.find(timerId) != timerHandlers_.end()) {
779         timerId = timerId + 1;
780         if (timerId == UINT32_MAX) {
781             timerId = 1;
782         }
783 
784         if (timerId == TIMER_ERR_DEAL_FAILED) {
785             timerId = timerId + 1;
786         }
787     }
788 
789     return timerId;
790 }
791 
GetTimerFd(uint32_t interval)792 int Timer::GetTimerFd(uint32_t interval /* ms */)
793 {
794     if (intervalToTimers_.find(interval) == intervalToTimers_.end()) {
795         return IO_EVENT_INVALID_FD;
796     }
797     auto &handlerList = intervalToTimers_[interval];
798     for (const TimerHandlerPtr &ptr : handlerList) {
799         if (!ptr->once_) {
800             return ptr->GetTimerFd();
801         }
802     }
803     return IO_EVENT_INVALID_FD;
804 }
805 
TimerEventHandler(int timerFd,uint32_t timeout,bool once)806 TimerEventHandler::TimerEventHandler(int timerFd, uint32_t timeout /* ms */, bool once)
807     : once_(once), interval_(timeout)
808 {
809     if (timerFd == IO_EVENT_INVALID_FD) {
810         handler_ = std::make_unique<IOEventHandler>(timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC));
811     } else {
812         handler_ = std::make_unique<IOEventHandler>(timerFd);
813     }
814 }
815 
~TimerEventHandler()816 TimerEventHandler::~TimerEventHandler()
817 {
818     if (close(handler_->GetFd()) != 0) {
819         std::cout << "||" << gettid() << "||" << "Close timer-fd failed. fd:" << handler_->GetFd() << ", interval:" <<
820                   interval_ << ", once:" << once_ << std::endl;
821     }
822     handler_->SetFd(IO_EVENT_INVALID_FD);
823 }
824 
Initialize()825 ErrCode TimerEventHandler::Initialize()
826 {
827     if (handler_->GetFd() == IO_EVENT_INVALID_FD) {
828         std::cout << "||" << gettid() << "||" << "Invalid timer-fd:" << handler_->GetFd() << ", interval:" <<
829                   interval_ << ", once:" << once_ << std::endl;
830         return TIMER_ERR_INVALID_VALUE;
831     }
832 
833     struct itimerspec newValue = {{0, 0}, {0, 0}};
834     timespec now{0, 0};
835     if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) {
836         std::cout << "||" << gettid() << "||" << "Get current time failed." << std::endl;
837         return TIMER_ERR_DEAL_FAILED;
838     }
839 
840     // next time out time is now + interval
841     newValue.it_value.tv_sec = now.tv_sec + interval_ / MILLI_TO_BASE;
842     newValue.it_value.tv_nsec = now.tv_nsec + (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO;
843     if (newValue.it_value.tv_nsec >= NANO_TO_BASE) {
844         newValue.it_value.tv_sec = newValue.it_value.tv_sec + 1;
845         newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE;
846     }
847 
848     if (once_) {
849         // interval, 0 means time out only once
850         newValue.it_interval.tv_sec  = 0;
851         newValue.it_interval.tv_nsec = 0;
852     } else {
853         // interval
854         newValue.it_interval.tv_sec  = interval_ / MILLI_TO_BASE;
855         newValue.it_interval.tv_nsec = (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO;
856     }
857 
858     if (timerfd_settime(handler_->GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == -1) {
859         std::cout << "||" << gettid() << "||" << "Set timer-fd failed. next:" <<
860                   static_cast<long long>(newValue.it_value.tv_sec) << "interval:" <<
861                   static_cast<long long>(newValue.it_interval.tv_sec) << std::endl;
862         return TIMER_ERR_DEAL_FAILED;
863     }
864 
865     handler_->SetCallback(std::bind(&TimerEventHandler::TimeOut, this));
866     handler_->EnableRead();
867 
868     return TIMER_ERR_OK;
869 }
870 
Uninitialize()871 void TimerEventHandler::Uninitialize()
872 {
873     handler_->DisableAll();
874 }
875 
Start(IOEventReactor * reactor)876 bool TimerEventHandler::Start(IOEventReactor* reactor)
877 {
878     if (handler_ == nullptr || !handler_->Start(reactor)) {
879         return false;
880     }
881 
882     return true;
883 }
884 
Stop(IOEventReactor * reactor)885 bool TimerEventHandler::Stop(IOEventReactor* reactor)
886 {
887     if (handler_ == nullptr || !handler_->Stop(reactor)) {
888         return false;
889     }
890 
891     return true;
892 }
893 
TimeOut()894 void TimerEventHandler::TimeOut()
895 {
896     if (handler_->GetFd() == IO_EVENT_INVALID_FD) {
897         std::cout << "||" << gettid() << "||" << "Invalid timerfd." << std::endl;
898         return;
899     }
900     uint64_t expirations = 0;
901     ssize_t n = ::read(handler_->GetFd(), &expirations, sizeof(expirations));
902     if (n != sizeof(expirations)) {
903         std::cout << "||" << gettid() << "||" << "Reads " << static_cast<int>(n) <<
904                   " bytes instead of 8 from timer fd." << std::endl;
905     }
906 
907     if (timerEventCallback_) {
908         timerEventCallback_(this);
909     }
910 }
911 
912 std::atomic<int> g_data1(0);
TimeOutCallback1()913 void TimeOutCallback1()
914 {
915     g_data1 += 1;
916 }
917 
918 std::atomic<int> g_data2(0);
TimeOutCallback2()919 void TimeOutCallback2()
920 {
921     g_data2 = g_data2 + 1;
922 }
923 
CurMs()924 int64_t CurMs()
925 {
926     struct timeval tpend;
927     gettimeofday(&tpend, nullptr);
928     return (tpend.tv_sec * 1000000 + tpend.tv_usec) / 1000; // 1000000: s to us, 1000: us to ms
929 }
930 
931 /*
932  * @tc.name: testNewTimer001
933  * @tc.desc: test basic function of timer implemented by new event-system.
934  */
935 HWTEST_F(UtilsEventTest, testNewTimer001, TestSize.Level0)
936 {
937     g_data1 = 0;
938     Timer timer("test_timer");
939     uint32_t ret = timer.Setup();
940     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
941     timer.Register(TimeOutCallback1, 1, true);
942     std::this_thread::sleep_for(std::chrono::milliseconds(15));
943     timer.Shutdown();
944     EXPECT_EQ(1, g_data1);
945 }
946 
947 /*
948  * @tc.name: testNewTimer002
949  * @tc.desc: test basic function of timer implemented by new event-system.
950  */
951 HWTEST_F(UtilsEventTest, testNewTimer002, TestSize.Level0)
952 {
953     g_data1 = 0;
954     g_data2 = 0;
955     Timer timer("test_timer");
956     uint32_t ret = timer.Setup();
957     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
958     timer.Register(TimeOutCallback1, 1);
959     timer.Register(TimeOutCallback2, 50);
960     std::this_thread::sleep_for(std::chrono::milliseconds(500));
961     timer.Shutdown();
962     EXPECT_GE(g_data1, 8);
963     EXPECT_GE(g_data2, 2);
964 }
965 
TestTimerEvent(Timer & timer)966 static void TestTimerEvent(Timer& timer)
967 {
968     uint32_t interval = 1;
969     timer.Register(TimeOutCallback1, interval);
970     uint32_t interval2 = 2;
971     timer.Register(TimeOutCallback1, interval2);
972     int sleepTime = 30;
973     std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
974     timer.Shutdown();
975 }
976 
977 /*
978  * @tc.name: testNewTimer003
979  * @tc.desc: test basic function of timer implemented by new event-system.
980  */
981 HWTEST_F(UtilsEventTest, testNewTimer003, TestSize.Level0)
982 {
983     g_data1 = 0;
984     Timer timer("test_timer");
985     uint32_t ret = timer.Setup();
986     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
987     TestTimerEvent(timer);
988     EXPECT_GE(g_data1, 5);
989 }
990 
991 class A {
992 public:
A(int data)993     explicit A(int data) : data_(data), timer_("ATimer") {}
994     ~A() = default;
995     bool Init();
GetData() const996     int GetData() const {return data_;}
997     bool StartTimer(int milliseconds, bool once);
998     void StopTimer();
999 private:
TimeOutProc()1000     void TimeOutProc()
1001     {
1002         data_ -= 1;
1003     };
1004     int data_;
1005     Timer timer_;
1006 };
1007 
Init()1008 bool A::Init()
1009 {
1010     return timer_.Setup() == Utils::TIMER_ERR_OK;
1011 }
1012 
StopTimer()1013 void A::StopTimer()
1014 {
1015     timer_.Shutdown();
1016 }
1017 
StartTimer(int milliseconds,bool once)1018 bool A::StartTimer(int milliseconds, bool once)
1019 {
1020     uint32_t timerId = timer_.Register(std::bind(&A::TimeOutProc, this), milliseconds, once);
1021     return timerId != Utils::TIMER_ERR_DEAL_FAILED;
1022 }
1023 
1024 /*
1025  * @tc.name: testNewTimer004
1026  * @tc.desc: test wrapper of the timer implemented by new event-system.
1027  */
1028 HWTEST_F(UtilsEventTest, testNewTimer004, TestSize.Level0)
1029 {
1030     A a(10);
1031     EXPECT_TRUE(a.Init());
1032     EXPECT_TRUE(a.StartTimer(1, true));
1033     std::this_thread::sleep_for(std::chrono::milliseconds(20));
1034     a.StopTimer();
1035     EXPECT_EQ(9, a.GetData());
1036 }
1037 
SleepLoop()1038 static void SleepLoop()
1039 {
1040     int loops = 11;
1041     int64_t desiredVal = 10;
1042     int sleepTime = 10;
1043     for (int i = 0; i < loops; i++) {
1044         int64_t pre = CurMs();
1045         std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
1046         int64_t cur = CurMs();
1047         EXPECT_GE(cur - pre, desiredVal);
1048     }
1049 }
1050 
TimerEvent(Timer & timer)1051 static void TimerEvent(Timer& timer)
1052 {
1053     uint32_t timerId = 0;
1054     uint32_t loops = 10;
1055     uint32_t interval = 7;
1056     int sleepTime = 10;
1057     for (uint32_t i = 0; i < loops; i++) {
1058         timerId = timer.Register(TimeOutCallback1, interval, true);
1059         std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
1060     }
1061     timer.Unregister(timerId);
1062     timer.Unregister(timerId);
1063 }
1064 
1065 /*
1066  * @tc.name: testNewTimer005
1067  * @tc.desc: test abnormal case of timer implemented by new event-system.
1068  */
1069 HWTEST_F(UtilsEventTest, testNewTimer005, TestSize.Level0)
1070 {
1071     g_data1 = 0;
1072     Timer timer("test_timer", -1);
1073     uint32_t ret = timer.Setup();
1074     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
1075     TimerEvent(timer);
1076     timer.Shutdown();
1077     timer.Shutdown(false);
1078     EXPECT_GE(g_data1, 5);
1079 }
1080 
1081 /*
1082  * @tc.name: testNewTimer006
1083  * @tc.desc: sleep test for ivi of timer implemented by new event-system.
1084  */
1085 HWTEST_F(UtilsEventTest, testNewTimer006, TestSize.Level0)
1086 {
1087     g_data1 = 0;
1088     Timer timer("test_timer");
1089     uint32_t ret = timer.Setup();
1090     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
1091     timer.Register(TimeOutCallback1, 10);
1092 
1093     SleepLoop();
1094     timer.Shutdown();
1095     EXPECT_GE(g_data1, 10);
1096 }
1097 
1098 /*
1099  * @tc.name: testNewTimer007
1100  * @tc.desc: recursive test of timer implemented by new event-system.
1101  */
DoFunc(Timer & timer,int & count)1102 void DoFunc(Timer &timer, int &count)
1103 {
1104     (void)timer.Register(
1105         [&timer, &count]() {
1106             count = count + 1;
1107             if (count > 9) { // 9: recursion depth
1108                 return;
1109             }
1110             DoFunc(timer, count);
1111         },
1112         10, true); // 10: interval
1113     g_data1++;
1114 }
1115 
DoFunc2(Timer & timer,int & count)1116 void DoFunc2(Timer &timer, int &count)
1117 {
1118     (void)timer.Register(
1119         [&timer, &count]() {
1120             count = count + 1;
1121             if (count > 9) { // 9: recursion depth
1122                 return;
1123             }
1124             DoFunc2(timer, count);
1125         },
1126         10, true); // 10: interval
1127     g_data1++;
1128 }
1129 
1130 HWTEST_F(UtilsEventTest, testNewTimer007, TestSize.Level0)
1131 {
1132     g_data1 = 0;
1133     Timer timer("test_timer");
1134     uint32_t ret = timer.Setup();
1135     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
1136 
1137     int cnt = 0;
1138     int cnt1 = 0;
1139     DoFunc(timer, cnt);
1140     DoFunc2(timer, cnt1);
1141     std::this_thread::sleep_for(std::chrono::milliseconds(50));
1142     EXPECT_GE(g_data1, 5);  /* 8 for max */
1143     EXPECT_GE(14, g_data1); /* 10 for min */
1144     std::this_thread::sleep_for(std::chrono::milliseconds(50));
1145     timer.Shutdown();
1146     EXPECT_GE(g_data1, 10); /* 18 for max */
1147 }
1148 
TimerRegisterMechanism(Timer & timer)1149 static void TimerRegisterMechanism(Timer& timer)
1150 {
1151     uint32_t interval = 10;
1152     timer.Register(TimeOutCallback1, interval, true);
1153     timer.Register(TimeOutCallback1, interval);
1154     timer.Register(TimeOutCallback1, interval, true);
1155     timer.Register(TimeOutCallback1, interval);
1156 }
1157 
1158 /*
1159  * @tc.name: testNewTimer008
1160  * @tc.desc: test execute-once and execute-periodly tasks.
1161  */
1162 HWTEST_F(UtilsEventTest, testNewTimer008, TestSize.Level0)
1163 {
1164     g_data1 = 0;
1165     Timer timer("test_timer");
1166     uint32_t ret = timer.Setup();
1167     EXPECT_EQ(Utils::TIMER_ERR_OK, ret);
1168     TimerRegisterMechanism(timer);
1169     std::this_thread::sleep_for(std::chrono::milliseconds(52));
1170     timer.Shutdown();
1171     EXPECT_GE(g_data1, 8); /* 12 for max */
1172 }
1173 
1174 
1175 }  // namespace
1176 }  // namespace OHOS