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
38using namespace testing::ext;
39using namespace OHOS::Utils;
40
41namespace OHOS {
42namespace {
43
44class UtilsEventTest : public testing::Test {
45public:
46    static void SetUpTestCase(void) {}
47    static void TearDownTestCase(void) {}
48    void SetUp() {}
49    void TearDown() {}
50};
51
52int g_data = 0;
53void TimerCallback1()
54{
55    std::cout << "timer callback1 invoked." << std::endl;
56    g_data++;
57}
58
59static const int MILLI_TO_BASE = 1000;
60static const int NANO_TO_BASE = 1000000000;
61static constexpr int MILLI_TO_NANO = NANO_TO_BASE / MILLI_TO_BASE;
62class TimerFdHandler : public IOEventHandler {
63public:
64    using TimerEventCallback = std::function<void()>;
65    TimerFdHandler(int fd, const TimerEventCallback& cb);
66    ~TimerFdHandler() {}
67    void TimeOut();
68    bool Initialize(uint32_t interval);
69    void Uninitialize();
70
71private:
72    TimerEventCallback timerCallback_;
73};
74
75void TestCallback() {}
76
77/*
78 * @tc.name: testIOEventHandler001
79 * @tc.desc: test basic interfaces of IOEventHandler.
80 */
81HWTEST_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 */
124HWTEST_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 */
169HWTEST_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 */
228HWTEST_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
251TimerFdHandler::TimerFdHandler(int fd, const TimerEventCallback& cb)
252    : IOEventHandler(fd),  timerCallback_(cb) {}
253
254bool 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
290void TimerFdHandler::Uninitialize()
291{
292    DisableAll();
293}
294
295void 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
312static 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 */
330HWTEST_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 */
364HWTEST_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 */
403HWTEST_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 */
437HWTEST_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 */
474HWTEST_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 */
511HWTEST_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
545class TimerEventHandler {
546public:
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
563    inline void SetTimerId(const uint32_t& id) { timerId_ = id; }
564
565    inline void SetTimerEventCallback(const TimerEventCallback& callback) { timerEventCallback_ = callback; }
566
567    inline uint32_t GetInterval() const { return interval_; }
568    inline int GetTimerFd() const { return handler_->GetFd(); }
569    inline uint32_t GetTimerId() const { return timerId_; }
570
571private:
572    void TimeOut();
573
574private:
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
584class Timer {
585public:
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);
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
599private:
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
606private:
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
625Timer::Timer(const std::string& name, int timeoutMs) : name_(name), timeoutMs_(timeoutMs),
626    reactor_(new IOEventReactor()) {}
627
628void 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
641uint32_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
660void 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
677ErrCode 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
701uint32_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
720void 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
733ErrCode 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
746void 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
765void Timer::OnTimer(TimerEventHandler* handler, const TimerCallback& callback)
766{
767    callback();
768
769    if (handler->once_) {
770        Unregister(handler->timerId_);
771    }
772}
773
774uint32_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
792int 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
806TimerEventHandler::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
816TimerEventHandler::~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
825ErrCode 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
871void TimerEventHandler::Uninitialize()
872{
873    handler_->DisableAll();
874}
875
876bool TimerEventHandler::Start(IOEventReactor* reactor)
877{
878    if (handler_ == nullptr || !handler_->Start(reactor)) {
879        return false;
880    }
881
882    return true;
883}
884
885bool TimerEventHandler::Stop(IOEventReactor* reactor)
886{
887    if (handler_ == nullptr || !handler_->Stop(reactor)) {
888        return false;
889    }
890
891    return true;
892}
893
894void 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
912std::atomic<int> g_data1(0);
913void TimeOutCallback1()
914{
915    g_data1 += 1;
916}
917
918std::atomic<int> g_data2(0);
919void TimeOutCallback2()
920{
921    g_data2 = g_data2 + 1;
922}
923
924int64_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 */
935HWTEST_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 */
951HWTEST_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
966static 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 */
981HWTEST_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
991class A {
992public:
993    explicit A(int data) : data_(data), timer_("ATimer") {}
994    ~A() = default;
995    bool Init();
996    int GetData() const {return data_;}
997    bool StartTimer(int milliseconds, bool once);
998    void StopTimer();
999private:
1000    void TimeOutProc()
1001    {
1002        data_ -= 1;
1003    };
1004    int data_;
1005    Timer timer_;
1006};
1007
1008bool A::Init()
1009{
1010    return timer_.Setup() == Utils::TIMER_ERR_OK;
1011}
1012
1013void A::StopTimer()
1014{
1015    timer_.Shutdown();
1016}
1017
1018bool 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 */
1028HWTEST_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
1038static 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
1051static 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 */
1069HWTEST_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 */
1085HWTEST_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 */
1102void 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
1116void 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
1130HWTEST_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
1149static 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 */
1162HWTEST_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