13f4cbf05Sopenharmony_ci/* 23f4cbf05Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License. 53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at 63f4cbf05Sopenharmony_ci * 73f4cbf05Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83f4cbf05Sopenharmony_ci * 93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and 133f4cbf05Sopenharmony_ci * limitations under the License. 143f4cbf05Sopenharmony_ci */ 153f4cbf05Sopenharmony_ci 163f4cbf05Sopenharmony_ci#include <gtest/gtest.h> 173f4cbf05Sopenharmony_ci#include <sys/types.h> 183f4cbf05Sopenharmony_ci#include <sys/timerfd.h> 193f4cbf05Sopenharmony_ci#include <sys/prctl.h> 203f4cbf05Sopenharmony_ci#include "unistd.h" 213f4cbf05Sopenharmony_ci#include <cstdint> 223f4cbf05Sopenharmony_ci#include <cstring> 233f4cbf05Sopenharmony_ci#include <string> 243f4cbf05Sopenharmony_ci#include <thread> 253f4cbf05Sopenharmony_ci#include <mutex> 263f4cbf05Sopenharmony_ci#include <memory> 273f4cbf05Sopenharmony_ci#include <atomic> 283f4cbf05Sopenharmony_ci#include <algorithm> 293f4cbf05Sopenharmony_ci#include <list> 303f4cbf05Sopenharmony_ci#include <map> 313f4cbf05Sopenharmony_ci#include <functional> 323f4cbf05Sopenharmony_ci#include <iostream> 333f4cbf05Sopenharmony_ci#include "common_timer_errors.h" 343f4cbf05Sopenharmony_ci#include "common_event_sys_errors.h" 353f4cbf05Sopenharmony_ci#include "io_event_handler.h" 363f4cbf05Sopenharmony_ci#include "io_event_reactor.h" 373f4cbf05Sopenharmony_ci 383f4cbf05Sopenharmony_ciusing namespace testing::ext; 393f4cbf05Sopenharmony_ciusing namespace OHOS::Utils; 403f4cbf05Sopenharmony_ci 413f4cbf05Sopenharmony_cinamespace OHOS { 423f4cbf05Sopenharmony_cinamespace { 433f4cbf05Sopenharmony_ci 443f4cbf05Sopenharmony_ciclass UtilsEventTest : public testing::Test { 453f4cbf05Sopenharmony_cipublic: 463f4cbf05Sopenharmony_ci static void SetUpTestCase(void) {} 473f4cbf05Sopenharmony_ci static void TearDownTestCase(void) {} 483f4cbf05Sopenharmony_ci void SetUp() {} 493f4cbf05Sopenharmony_ci void TearDown() {} 503f4cbf05Sopenharmony_ci}; 513f4cbf05Sopenharmony_ci 523f4cbf05Sopenharmony_ciint g_data = 0; 533f4cbf05Sopenharmony_civoid TimerCallback1() 543f4cbf05Sopenharmony_ci{ 553f4cbf05Sopenharmony_ci std::cout << "timer callback1 invoked." << std::endl; 563f4cbf05Sopenharmony_ci g_data++; 573f4cbf05Sopenharmony_ci} 583f4cbf05Sopenharmony_ci 593f4cbf05Sopenharmony_cistatic const int MILLI_TO_BASE = 1000; 603f4cbf05Sopenharmony_cistatic const int NANO_TO_BASE = 1000000000; 613f4cbf05Sopenharmony_cistatic constexpr int MILLI_TO_NANO = NANO_TO_BASE / MILLI_TO_BASE; 623f4cbf05Sopenharmony_ciclass TimerFdHandler : public IOEventHandler { 633f4cbf05Sopenharmony_cipublic: 643f4cbf05Sopenharmony_ci using TimerEventCallback = std::function<void()>; 653f4cbf05Sopenharmony_ci TimerFdHandler(int fd, const TimerEventCallback& cb); 663f4cbf05Sopenharmony_ci ~TimerFdHandler() {} 673f4cbf05Sopenharmony_ci void TimeOut(); 683f4cbf05Sopenharmony_ci bool Initialize(uint32_t interval); 693f4cbf05Sopenharmony_ci void Uninitialize(); 703f4cbf05Sopenharmony_ci 713f4cbf05Sopenharmony_ciprivate: 723f4cbf05Sopenharmony_ci TimerEventCallback timerCallback_; 733f4cbf05Sopenharmony_ci}; 743f4cbf05Sopenharmony_ci 753f4cbf05Sopenharmony_civoid TestCallback() {} 763f4cbf05Sopenharmony_ci 773f4cbf05Sopenharmony_ci/* 783f4cbf05Sopenharmony_ci * @tc.name: testIOEventHandler001 793f4cbf05Sopenharmony_ci * @tc.desc: test basic interfaces of IOEventHandler. 803f4cbf05Sopenharmony_ci */ 813f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testIOEventHandler001, TestSize.Level0) 823f4cbf05Sopenharmony_ci{ 833f4cbf05Sopenharmony_ci g_data = 0; 843f4cbf05Sopenharmony_ci // 1. Create io event handler 853f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(-1); 863f4cbf05Sopenharmony_ci 873f4cbf05Sopenharmony_ci // 2. Set fd 883f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 893f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 903f4cbf05Sopenharmony_ci handler->SetFd(fd); 913f4cbf05Sopenharmony_ci EXPECT_EQ(handler->GetFd(), fd); 923f4cbf05Sopenharmony_ci 933f4cbf05Sopenharmony_ci // 3. Set callback 943f4cbf05Sopenharmony_ci handler->SetCallback(&TestCallback); 953f4cbf05Sopenharmony_ci EXPECT_NE(handler->GetCallback(), nullptr); 963f4cbf05Sopenharmony_ci 973f4cbf05Sopenharmony_ci // 4. Set interest events 983f4cbf05Sopenharmony_ci handler->SetEvents(Events::EVENT_READ | Events::EVENT_WRITE); 993f4cbf05Sopenharmony_ci EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ | Events::EVENT_WRITE); 1003f4cbf05Sopenharmony_ci 1013f4cbf05Sopenharmony_ci // 5. Check status 1023f4cbf05Sopenharmony_ci EXPECT_EQ(handler->Prev(), nullptr); 1033f4cbf05Sopenharmony_ci EXPECT_EQ(handler->Next(), nullptr); 1043f4cbf05Sopenharmony_ci EXPECT_EQ(handler->IsActive(), false); 1053f4cbf05Sopenharmony_ci 1063f4cbf05Sopenharmony_ci // 6. disable events 1073f4cbf05Sopenharmony_ci handler->DisableAll(); 1083f4cbf05Sopenharmony_ci EXPECT_EQ(handler->GetEvents(), Events::EVENT_NONE); 1093f4cbf05Sopenharmony_ci 1103f4cbf05Sopenharmony_ci // 7. enable events 1113f4cbf05Sopenharmony_ci handler->EnableRead(); 1123f4cbf05Sopenharmony_ci handler->EnableWrite(); 1133f4cbf05Sopenharmony_ci EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ | Events::EVENT_WRITE); 1143f4cbf05Sopenharmony_ci 1153f4cbf05Sopenharmony_ci // 8. disable one of the events 1163f4cbf05Sopenharmony_ci handler->DisableWrite(); 1173f4cbf05Sopenharmony_ci EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ); 1183f4cbf05Sopenharmony_ci} 1193f4cbf05Sopenharmony_ci 1203f4cbf05Sopenharmony_ci/* 1213f4cbf05Sopenharmony_ci * @tc.name: testIOEventHandler002 1223f4cbf05Sopenharmony_ci * @tc.desc: test reactor-related interfaces of IOEventHandler. 1233f4cbf05Sopenharmony_ci */ 1243f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testIOEventHandler002, TestSize.Level0) 1253f4cbf05Sopenharmony_ci{ 1263f4cbf05Sopenharmony_ci g_data = 0; 1273f4cbf05Sopenharmony_ci // 1. Create io event handler 1283f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler = std::make_shared<IOEventHandler>(-1); 1293f4cbf05Sopenharmony_ci 1303f4cbf05Sopenharmony_ci // 2. Set fd 1313f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 1323f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 1333f4cbf05Sopenharmony_ci handler->SetFd(fd); 1343f4cbf05Sopenharmony_ci EXPECT_EQ(handler->GetFd(), fd); 1353f4cbf05Sopenharmony_ci 1363f4cbf05Sopenharmony_ci // 3. Set callback 1373f4cbf05Sopenharmony_ci handler->SetCallback(&TestCallback); 1383f4cbf05Sopenharmony_ci EXPECT_NE(handler->GetCallback(), nullptr); 1393f4cbf05Sopenharmony_ci 1403f4cbf05Sopenharmony_ci // 4. Set interest events 1413f4cbf05Sopenharmony_ci handler->EnableRead(); 1423f4cbf05Sopenharmony_ci EXPECT_EQ(handler->GetEvents(), Events::EVENT_READ); 1433f4cbf05Sopenharmony_ci 1443f4cbf05Sopenharmony_ci // 5. Create a reactor but not run 1453f4cbf05Sopenharmony_ci std::shared_ptr<IOEventReactor> reactor = std::make_shared<IOEventReactor>(); 1463f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 1473f4cbf05Sopenharmony_ci 1483f4cbf05Sopenharmony_ci // 6. Start handler 1493f4cbf05Sopenharmony_ci handler->Start(reactor.get()); 1503f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_OK); 1513f4cbf05Sopenharmony_ci 1523f4cbf05Sopenharmony_ci // 7. Change setting and update handler to the reactor 1533f4cbf05Sopenharmony_ci handler->EnableWrite(); 1543f4cbf05Sopenharmony_ci EXPECT_TRUE(handler->Update(reactor.get())); 1553f4cbf05Sopenharmony_ci 1563f4cbf05Sopenharmony_ci // 8. Remove the handler 1573f4cbf05Sopenharmony_ci handler->Stop(reactor.get()); 1583f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->FindHandler(handler.get()), EVENT_SYS_ERR_NOT_FOUND); 1593f4cbf05Sopenharmony_ci 1603f4cbf05Sopenharmony_ci // 9. Add handler, then delete handler. handler will remove itself from the reactor during deconstruction. 1613f4cbf05Sopenharmony_ci ASSERT_TRUE(handler->Start(reactor.get())); 1623f4cbf05Sopenharmony_ci handler.reset(); 1633f4cbf05Sopenharmony_ci} 1643f4cbf05Sopenharmony_ci 1653f4cbf05Sopenharmony_ci/* 1663f4cbf05Sopenharmony_ci * @tc.name: testIOEventReactor001 1673f4cbf05Sopenharmony_ci * @tc.desc: test basic interfaces of IOEventReactor. 1683f4cbf05Sopenharmony_ci */ 1693f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testIOEventReactor001, TestSize.Level0) 1703f4cbf05Sopenharmony_ci{ 1713f4cbf05Sopenharmony_ci g_data = 0; 1723f4cbf05Sopenharmony_ci // Get fd 1733f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 1743f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 1753f4cbf05Sopenharmony_ci 1763f4cbf05Sopenharmony_ci // 1. Create io event handlers 1773f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler1 = std::make_shared<IOEventHandler>(fd); 1783f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler2 = std::make_shared<IOEventHandler>(fd); 1793f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler3 = std::make_shared<IOEventHandler>(-1); // -1: invalid fd 1803f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler4 = std::make_shared<IOEventHandler>(fd); 1813f4cbf05Sopenharmony_ci 1823f4cbf05Sopenharmony_ci // 2. Create a reactor but not run 1833f4cbf05Sopenharmony_ci std::shared_ptr<IOEventReactor> reactor = std::make_shared<IOEventReactor>(); 1843f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 1853f4cbf05Sopenharmony_ci 1863f4cbf05Sopenharmony_ci // 3. Add handler 1873f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK); 1883f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK); 1893f4cbf05Sopenharmony_ci EXPECT_NE(reactor->AddHandler(handler3.get()), EVENT_SYS_ERR_OK); 1903f4cbf05Sopenharmony_ci EXPECT_NE(reactor->AddHandler(nullptr), EVENT_SYS_ERR_OK); 1913f4cbf05Sopenharmony_ci 1923f4cbf05Sopenharmony_ci // 4. Add handler from the handler side. 1933f4cbf05Sopenharmony_ci EXPECT_NE(handler1->Start(reactor.get()), EVENT_SYS_ERR_OK); // already started. 1943f4cbf05Sopenharmony_ci EXPECT_NE(handler3->Start(reactor.get()), EVENT_SYS_ERR_OK); // Bad fd. 1953f4cbf05Sopenharmony_ci 1963f4cbf05Sopenharmony_ci // 5. Remove handler 1973f4cbf05Sopenharmony_ci EXPECT_NE(reactor->RemoveHandler(nullptr), EVENT_SYS_ERR_OK); 1983f4cbf05Sopenharmony_ci EXPECT_NE(reactor->RemoveHandler(handler3.get()), EVENT_SYS_ERR_OK); // Bad fd. 1993f4cbf05Sopenharmony_ci EXPECT_NE(reactor->RemoveHandler(handler4.get()), EVENT_SYS_ERR_OK); 2003f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->RemoveHandler(handler2.get()), EVENT_SYS_ERR_OK); 2013f4cbf05Sopenharmony_ci 2023f4cbf05Sopenharmony_ci // 6. Remove handler from the handler side. 2033f4cbf05Sopenharmony_ci EXPECT_NE(handler2->Stop(reactor.get()), EVENT_SYS_ERR_OK); // Not found. 2043f4cbf05Sopenharmony_ci 2053f4cbf05Sopenharmony_ci // 7. Update handler 2063f4cbf05Sopenharmony_ci EXPECT_NE(reactor->UpdateHandler(nullptr), EVENT_SYS_ERR_OK); 2073f4cbf05Sopenharmony_ci EXPECT_NE(reactor->UpdateHandler(handler3.get()), EVENT_SYS_ERR_OK); 2083f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->UpdateHandler(handler1.get()), EVENT_SYS_ERR_OK); 2093f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->UpdateHandler(handler4.get()), EVENT_SYS_ERR_OK); 2103f4cbf05Sopenharmony_ci 2113f4cbf05Sopenharmony_ci // 8. Update handler from the handler side. 2123f4cbf05Sopenharmony_ci EXPECT_NE(handler2->Update(reactor.get()), EVENT_SYS_ERR_OK); // Not found. 2133f4cbf05Sopenharmony_ci EXPECT_NE(handler3->Update(reactor.get()), EVENT_SYS_ERR_OK); // Bad fd. 2143f4cbf05Sopenharmony_ci 2153f4cbf05Sopenharmony_ci // 9. Find handler 2163f4cbf05Sopenharmony_ci EXPECT_NE(reactor->FindHandler(nullptr), EVENT_SYS_ERR_OK); 2173f4cbf05Sopenharmony_ci EXPECT_NE(reactor->FindHandler(handler3.get()), EVENT_SYS_ERR_OK); 2183f4cbf05Sopenharmony_ci 2193f4cbf05Sopenharmony_ci // 10. Clean handler 2203f4cbf05Sopenharmony_ci EXPECT_NE(reactor->Clean(-1), EVENT_SYS_ERR_OK); 2213f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->Clean(fd), EVENT_SYS_ERR_OK); 2223f4cbf05Sopenharmony_ci} 2233f4cbf05Sopenharmony_ci 2243f4cbf05Sopenharmony_ci/* 2253f4cbf05Sopenharmony_ci * @tc.name: testIOEventReactor002 2263f4cbf05Sopenharmony_ci * @tc.desc: test change event but not update. 2273f4cbf05Sopenharmony_ci */ 2283f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testIOEventReactor002, TestSize.Level0) 2293f4cbf05Sopenharmony_ci{ 2303f4cbf05Sopenharmony_ci g_data = 0; 2313f4cbf05Sopenharmony_ci // 1. Open timer 2323f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 2333f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 2343f4cbf05Sopenharmony_ci 2353f4cbf05Sopenharmony_ci // 2. Create io event handlers 2363f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler1 = std::make_shared<IOEventHandler>(fd); 2373f4cbf05Sopenharmony_ci std::shared_ptr<IOEventHandler> handler2 = std::make_shared<IOEventHandler>(fd); 2383f4cbf05Sopenharmony_ci 2393f4cbf05Sopenharmony_ci // 3. Create a reactor but not run 2403f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 2413f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 2423f4cbf05Sopenharmony_ci 2433f4cbf05Sopenharmony_ci // 4. Add handler 2443f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->AddHandler(handler1.get()), EVENT_SYS_ERR_OK); 2453f4cbf05Sopenharmony_ci EXPECT_EQ(reactor->AddHandler(handler2.get()), EVENT_SYS_ERR_OK); 2463f4cbf05Sopenharmony_ci 2473f4cbf05Sopenharmony_ci // 5. release one handler 2483f4cbf05Sopenharmony_ci handler2.reset(); // will be removed from the inner list. 2493f4cbf05Sopenharmony_ci} 2503f4cbf05Sopenharmony_ci 2513f4cbf05Sopenharmony_ciTimerFdHandler::TimerFdHandler(int fd, const TimerEventCallback& cb) 2523f4cbf05Sopenharmony_ci : IOEventHandler(fd), timerCallback_(cb) {} 2533f4cbf05Sopenharmony_ci 2543f4cbf05Sopenharmony_cibool TimerFdHandler::Initialize(uint32_t interval) 2553f4cbf05Sopenharmony_ci{ 2563f4cbf05Sopenharmony_ci if ((GetFd() == -1)) { 2573f4cbf05Sopenharmony_ci return false; 2583f4cbf05Sopenharmony_ci } 2593f4cbf05Sopenharmony_ci 2603f4cbf05Sopenharmony_ci struct itimerspec newValue = {{0, 0}, {0, 0}}; 2613f4cbf05Sopenharmony_ci timespec now{0, 0}; 2623f4cbf05Sopenharmony_ci if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) { 2633f4cbf05Sopenharmony_ci return false; 2643f4cbf05Sopenharmony_ci } 2653f4cbf05Sopenharmony_ci 2663f4cbf05Sopenharmony_ci // next time out time is now + interval 2673f4cbf05Sopenharmony_ci newValue.it_value.tv_sec = now.tv_sec + interval / MILLI_TO_BASE; 2683f4cbf05Sopenharmony_ci newValue.it_value.tv_nsec = now.tv_nsec + (interval % MILLI_TO_BASE) * MILLI_TO_NANO; 2693f4cbf05Sopenharmony_ci if (newValue.it_value.tv_nsec >= NANO_TO_BASE) { 2703f4cbf05Sopenharmony_ci newValue.it_value.tv_sec = newValue.it_value.tv_sec + 1; 2713f4cbf05Sopenharmony_ci newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE; 2723f4cbf05Sopenharmony_ci } 2733f4cbf05Sopenharmony_ci 2743f4cbf05Sopenharmony_ci // interval 2753f4cbf05Sopenharmony_ci newValue.it_interval.tv_sec = interval / MILLI_TO_BASE; 2763f4cbf05Sopenharmony_ci newValue.it_interval.tv_nsec = (interval % MILLI_TO_BASE) * MILLI_TO_NANO; 2773f4cbf05Sopenharmony_ci 2783f4cbf05Sopenharmony_ci if (timerfd_settime(GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == -1) { 2793f4cbf05Sopenharmony_ci std::cout << "Set timerFd failed-" << strerror(errno) << "timer_fd:" << GetFd() << ", next_time:" << 2803f4cbf05Sopenharmony_ci newValue.it_value.tv_sec << ", interval:" << newValue.it_interval.tv_sec << std::endl; 2813f4cbf05Sopenharmony_ci return false; 2823f4cbf05Sopenharmony_ci } 2833f4cbf05Sopenharmony_ci 2843f4cbf05Sopenharmony_ci EnableRead(); 2853f4cbf05Sopenharmony_ci SetCallback(std::bind(&TimerFdHandler::TimeOut, this)); 2863f4cbf05Sopenharmony_ci 2873f4cbf05Sopenharmony_ci return true; 2883f4cbf05Sopenharmony_ci} 2893f4cbf05Sopenharmony_ci 2903f4cbf05Sopenharmony_civoid TimerFdHandler::Uninitialize() 2913f4cbf05Sopenharmony_ci{ 2923f4cbf05Sopenharmony_ci DisableAll(); 2933f4cbf05Sopenharmony_ci} 2943f4cbf05Sopenharmony_ci 2953f4cbf05Sopenharmony_civoid TimerFdHandler::TimeOut() 2963f4cbf05Sopenharmony_ci{ 2973f4cbf05Sopenharmony_ci if (GetFd() == -1) { 2983f4cbf05Sopenharmony_ci std::cout << "Invalid timer_fd." << std::endl; 2993f4cbf05Sopenharmony_ci return; 3003f4cbf05Sopenharmony_ci } 3013f4cbf05Sopenharmony_ci uint64_t expirations = 0; 3023f4cbf05Sopenharmony_ci ssize_t n = ::read(GetFd(), &expirations, sizeof(expirations)); 3033f4cbf05Sopenharmony_ci if (n != sizeof(expirations)) { 3043f4cbf05Sopenharmony_ci std::cout << "reads " << static_cast<int>(n) << "bytes instead of 8." << std::endl; 3053f4cbf05Sopenharmony_ci } 3063f4cbf05Sopenharmony_ci 3073f4cbf05Sopenharmony_ci if (timerCallback_) { 3083f4cbf05Sopenharmony_ci timerCallback_(); 3093f4cbf05Sopenharmony_ci } 3103f4cbf05Sopenharmony_ci} 3113f4cbf05Sopenharmony_ci 3123f4cbf05Sopenharmony_cistatic void InitAndRun(std::shared_ptr<TimerFdHandler>& handler, const uint32_t interval, 3133f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor>& reactor, std::thread& loopThread) 3143f4cbf05Sopenharmony_ci{ 3153f4cbf05Sopenharmony_ci // Initialize timer handler and add it to reactor 3163f4cbf05Sopenharmony_ci ASSERT_TRUE(handler->Initialize(interval)); 3173f4cbf05Sopenharmony_ci ASSERT_TRUE(handler->Start(reactor.get())); 3183f4cbf05Sopenharmony_ci 3193f4cbf05Sopenharmony_ci // Run event loop 3203f4cbf05Sopenharmony_ci loopThread = std::thread([&reactor] { 3213f4cbf05Sopenharmony_ci reactor->Run(-1); 3223f4cbf05Sopenharmony_ci } 3233f4cbf05Sopenharmony_ci ); 3243f4cbf05Sopenharmony_ci} 3253f4cbf05Sopenharmony_ci 3263f4cbf05Sopenharmony_ci/* 3273f4cbf05Sopenharmony_ci * @tc.name: testEvent001 3283f4cbf05Sopenharmony_ci * @tc.desc: test handling event of timerfd. 3293f4cbf05Sopenharmony_ci */ 3303f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testEvent001, TestSize.Level0) 3313f4cbf05Sopenharmony_ci{ 3323f4cbf05Sopenharmony_ci g_data = 0; 3333f4cbf05Sopenharmony_ci // 1. Open timer 3343f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 3353f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 3363f4cbf05Sopenharmony_ci // 2. Create timer event handler 3373f4cbf05Sopenharmony_ci std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1); 3383f4cbf05Sopenharmony_ci 3393f4cbf05Sopenharmony_ci // 3. Create reactor for event loop 3403f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 3413f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 3423f4cbf05Sopenharmony_ci reactor->EnableHandling(); 3433f4cbf05Sopenharmony_ci 3443f4cbf05Sopenharmony_ci // 4. Initialize timer handler and add it to reactor. Run event loop 3453f4cbf05Sopenharmony_ci uint32_t interval = 10; 3463f4cbf05Sopenharmony_ci std::thread loopThread; 3473f4cbf05Sopenharmony_ci InitAndRun(handler, interval, reactor, loopThread); 3483f4cbf05Sopenharmony_ci 3493f4cbf05Sopenharmony_ci // 5. Wait for event handling 3503f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(16)); 3513f4cbf05Sopenharmony_ci 3523f4cbf05Sopenharmony_ci // 6. Check result, execute once at least 3533f4cbf05Sopenharmony_ci EXPECT_GE(g_data, 1); 3543f4cbf05Sopenharmony_ci 3553f4cbf05Sopenharmony_ci // 7. terminate the event-loop (aka Run()) 3563f4cbf05Sopenharmony_ci reactor->Terminate(); 3573f4cbf05Sopenharmony_ci loopThread.join(); 3583f4cbf05Sopenharmony_ci} 3593f4cbf05Sopenharmony_ci 3603f4cbf05Sopenharmony_ci/* 3613f4cbf05Sopenharmony_ci * @tc.name: testEvent002 3623f4cbf05Sopenharmony_ci * @tc.desc: test changing event to EVENT_NONE. 3633f4cbf05Sopenharmony_ci */ 3643f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testEvent002, TestSize.Level0) 3653f4cbf05Sopenharmony_ci{ 3663f4cbf05Sopenharmony_ci g_data = 0; 3673f4cbf05Sopenharmony_ci // 1. Open timer 3683f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 3693f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 3703f4cbf05Sopenharmony_ci // 2. Create timer event handler 3713f4cbf05Sopenharmony_ci std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1); 3723f4cbf05Sopenharmony_ci 3733f4cbf05Sopenharmony_ci // 3. Create reactor for event loop 3743f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 3753f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 3763f4cbf05Sopenharmony_ci 3773f4cbf05Sopenharmony_ci // 4. Initialize timer handler and add it to reactor. Run event loop 3783f4cbf05Sopenharmony_ci uint32_t interval = 10; 3793f4cbf05Sopenharmony_ci std::thread loopThread; 3803f4cbf05Sopenharmony_ci InitAndRun(handler, interval, reactor, loopThread); 3813f4cbf05Sopenharmony_ci 3823f4cbf05Sopenharmony_ci // 5. Change settings 3833f4cbf05Sopenharmony_ci reactor->DisableHandling(); 3843f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(1)); 3853f4cbf05Sopenharmony_ci reactor->EnableHandling(); 3863f4cbf05Sopenharmony_ci handler->SetEvents(Events::EVENT_NONE); 3873f4cbf05Sopenharmony_ci 3883f4cbf05Sopenharmony_ci // 6. Wait for event handling 3893f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(16)); 3903f4cbf05Sopenharmony_ci 3913f4cbf05Sopenharmony_ci // 7. Check result, no execution 3923f4cbf05Sopenharmony_ci EXPECT_EQ(g_data, 0); 3933f4cbf05Sopenharmony_ci 3943f4cbf05Sopenharmony_ci // 8. terminate the event-loop (aka Run()) 3953f4cbf05Sopenharmony_ci reactor->Terminate(); 3963f4cbf05Sopenharmony_ci loopThread.join(); 3973f4cbf05Sopenharmony_ci} 3983f4cbf05Sopenharmony_ci 3993f4cbf05Sopenharmony_ci/* 4003f4cbf05Sopenharmony_ci * @tc.name: testEvent003 4013f4cbf05Sopenharmony_ci * @tc.desc: test disable single event. 4023f4cbf05Sopenharmony_ci */ 4033f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testEvent003, TestSize.Level0) 4043f4cbf05Sopenharmony_ci{ 4053f4cbf05Sopenharmony_ci g_data = 0; 4063f4cbf05Sopenharmony_ci // 1. Open timer 4073f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 4083f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 4093f4cbf05Sopenharmony_ci // 2. Create timer event handler 4103f4cbf05Sopenharmony_ci std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1); 4113f4cbf05Sopenharmony_ci 4123f4cbf05Sopenharmony_ci // 3. Create reactor for event loop 4133f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 4143f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 4153f4cbf05Sopenharmony_ci 4163f4cbf05Sopenharmony_ci // 4. Initialize timer handler and add it to reactor. Run event loop 4173f4cbf05Sopenharmony_ci uint32_t interval = 10; 4183f4cbf05Sopenharmony_ci std::thread loopThread; 4193f4cbf05Sopenharmony_ci InitAndRun(handler, interval, reactor, loopThread); 4203f4cbf05Sopenharmony_ci 4213f4cbf05Sopenharmony_ci // 5. Change settings 4223f4cbf05Sopenharmony_ci reactor->EnableHandling(); 4233f4cbf05Sopenharmony_ci ASSERT_TRUE(handler->Stop(reactor.get())); // block to get lock, so no need to wait. 4243f4cbf05Sopenharmony_ci 4253f4cbf05Sopenharmony_ci // 6. Check result, no execution 4263f4cbf05Sopenharmony_ci EXPECT_EQ(g_data, 0); 4273f4cbf05Sopenharmony_ci 4283f4cbf05Sopenharmony_ci // 7. terminate the event-loop (aka Run()) 4293f4cbf05Sopenharmony_ci reactor->Terminate(); 4303f4cbf05Sopenharmony_ci loopThread.join(); 4313f4cbf05Sopenharmony_ci} 4323f4cbf05Sopenharmony_ci 4333f4cbf05Sopenharmony_ci/* 4343f4cbf05Sopenharmony_ci * @tc.name: testEvent004 4353f4cbf05Sopenharmony_ci * @tc.desc: test removing callback. 4363f4cbf05Sopenharmony_ci */ 4373f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testEvent004, TestSize.Level0) 4383f4cbf05Sopenharmony_ci{ 4393f4cbf05Sopenharmony_ci g_data = 0; 4403f4cbf05Sopenharmony_ci // 1. Open timer 4413f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 4423f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 4433f4cbf05Sopenharmony_ci // 2. Create timer event handler 4443f4cbf05Sopenharmony_ci std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1); 4453f4cbf05Sopenharmony_ci 4463f4cbf05Sopenharmony_ci // 3. Create reactor for event loop 4473f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 4483f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 4493f4cbf05Sopenharmony_ci 4503f4cbf05Sopenharmony_ci // 4. Initialize timer handler and add it to reactor. Run event loop 4513f4cbf05Sopenharmony_ci uint32_t interval = 10; 4523f4cbf05Sopenharmony_ci std::thread loopThread; 4533f4cbf05Sopenharmony_ci InitAndRun(handler, interval, reactor, loopThread); 4543f4cbf05Sopenharmony_ci 4553f4cbf05Sopenharmony_ci // 5. Change settings 4563f4cbf05Sopenharmony_ci reactor->EnableHandling(); 4573f4cbf05Sopenharmony_ci handler->SetCallback(nullptr); 4583f4cbf05Sopenharmony_ci 4593f4cbf05Sopenharmony_ci // 6. Wait for event handling 4603f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(16)); 4613f4cbf05Sopenharmony_ci 4623f4cbf05Sopenharmony_ci // 7. Check result, no execution 4633f4cbf05Sopenharmony_ci EXPECT_EQ(g_data, 0); 4643f4cbf05Sopenharmony_ci 4653f4cbf05Sopenharmony_ci // 8. terminate the event-loop (aka Run()) 4663f4cbf05Sopenharmony_ci reactor->Terminate(); 4673f4cbf05Sopenharmony_ci loopThread.join(); 4683f4cbf05Sopenharmony_ci} 4693f4cbf05Sopenharmony_ci 4703f4cbf05Sopenharmony_ci/* 4713f4cbf05Sopenharmony_ci * @tc.name: testEvent005 4723f4cbf05Sopenharmony_ci * @tc.desc: test change event but not update. 4733f4cbf05Sopenharmony_ci */ 4743f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testEvent005, TestSize.Level0) 4753f4cbf05Sopenharmony_ci{ 4763f4cbf05Sopenharmony_ci g_data = 0; 4773f4cbf05Sopenharmony_ci // 1. Open timer 4783f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 4793f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 4803f4cbf05Sopenharmony_ci // 2. Create timer event handler 4813f4cbf05Sopenharmony_ci std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1); 4823f4cbf05Sopenharmony_ci 4833f4cbf05Sopenharmony_ci // 3. Create reactor for event loop 4843f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 4853f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 4863f4cbf05Sopenharmony_ci 4873f4cbf05Sopenharmony_ci // 4. Initialize timer handler and add it to reactor. Run event loop 4883f4cbf05Sopenharmony_ci uint32_t interval = 15; 4893f4cbf05Sopenharmony_ci std::thread loopThread; 4903f4cbf05Sopenharmony_ci InitAndRun(handler, interval, reactor, loopThread); 4913f4cbf05Sopenharmony_ci 4923f4cbf05Sopenharmony_ci // 5. Change settings but not update 4933f4cbf05Sopenharmony_ci handler->SetEvents(Events::EVENT_WRITE); 4943f4cbf05Sopenharmony_ci reactor->EnableHandling(); 4953f4cbf05Sopenharmony_ci 4963f4cbf05Sopenharmony_ci // 6. Wait for event handling 4973f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(16)); 4983f4cbf05Sopenharmony_ci 4993f4cbf05Sopenharmony_ci // 7. Check result, no execution 5003f4cbf05Sopenharmony_ci EXPECT_EQ(g_data, 0); 5013f4cbf05Sopenharmony_ci 5023f4cbf05Sopenharmony_ci // 8. terminate the event-loop (aka Run()) 5033f4cbf05Sopenharmony_ci reactor->Terminate(); 5043f4cbf05Sopenharmony_ci loopThread.join(); 5053f4cbf05Sopenharmony_ci} 5063f4cbf05Sopenharmony_ci 5073f4cbf05Sopenharmony_ci/* 5083f4cbf05Sopenharmony_ci * @tc.name: testEvent006 5093f4cbf05Sopenharmony_ci * @tc.desc: test release the handler when started. 5103f4cbf05Sopenharmony_ci */ 5113f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testEvent006, TestSize.Level0) 5123f4cbf05Sopenharmony_ci{ 5133f4cbf05Sopenharmony_ci g_data = 0; 5143f4cbf05Sopenharmony_ci // 1. Open timer 5153f4cbf05Sopenharmony_ci int fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC); 5163f4cbf05Sopenharmony_ci ASSERT_NE(fd, -1); 5173f4cbf05Sopenharmony_ci // 2. Create timer event handler 5183f4cbf05Sopenharmony_ci std::shared_ptr<TimerFdHandler> handler = std::make_shared<TimerFdHandler>(fd, &TimerCallback1); 5193f4cbf05Sopenharmony_ci 5203f4cbf05Sopenharmony_ci // 3. Create reactor for event loop 5213f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor = std::make_unique<IOEventReactor>(); 5223f4cbf05Sopenharmony_ci ASSERT_EQ(reactor->SetUp(), EVENT_SYS_ERR_OK); 5233f4cbf05Sopenharmony_ci 5243f4cbf05Sopenharmony_ci // 4. Initialize timer handler and add it to reactor. Run event loop 5253f4cbf05Sopenharmony_ci uint32_t interval = 15; 5263f4cbf05Sopenharmony_ci std::thread loopThread; 5273f4cbf05Sopenharmony_ci InitAndRun(handler, interval, reactor, loopThread); 5283f4cbf05Sopenharmony_ci 5293f4cbf05Sopenharmony_ci // 5. release eventhandler 5303f4cbf05Sopenharmony_ci handler.reset(); 5313f4cbf05Sopenharmony_ci reactor->EnableHandling(); 5323f4cbf05Sopenharmony_ci 5333f4cbf05Sopenharmony_ci // 6. Wait for event handling 5343f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(16)); 5353f4cbf05Sopenharmony_ci 5363f4cbf05Sopenharmony_ci // 7. Check result, no execution 5373f4cbf05Sopenharmony_ci EXPECT_EQ(g_data, 0); 5383f4cbf05Sopenharmony_ci 5393f4cbf05Sopenharmony_ci // 8. terminate the event-loop (aka Run()) 5403f4cbf05Sopenharmony_ci reactor->Terminate(); 5413f4cbf05Sopenharmony_ci loopThread.join(); 5423f4cbf05Sopenharmony_ci} 5433f4cbf05Sopenharmony_ci 5443f4cbf05Sopenharmony_ci// Try to substitue underlying implementation of OHOS::UTILS::TIMER 5453f4cbf05Sopenharmony_ciclass TimerEventHandler { 5463f4cbf05Sopenharmony_cipublic: 5473f4cbf05Sopenharmony_ci using TimerEventCallback = std::function<void(TimerEventHandler*)>; 5483f4cbf05Sopenharmony_ci TimerEventHandler(int timerFd, uint32_t timeout, bool once); 5493f4cbf05Sopenharmony_ci TimerEventHandler(uint32_t timeout /* ms */, bool once); 5503f4cbf05Sopenharmony_ci ~TimerEventHandler(); 5513f4cbf05Sopenharmony_ci 5523f4cbf05Sopenharmony_ci TimerEventHandler(const TimerEventHandler&&) = delete; 5533f4cbf05Sopenharmony_ci TimerEventHandler& operator=(const TimerEventHandler&&) = delete; 5543f4cbf05Sopenharmony_ci TimerEventHandler(const TimerEventHandler&) = delete; 5553f4cbf05Sopenharmony_ci TimerEventHandler& operator=(const TimerEventHandler&) = delete; 5563f4cbf05Sopenharmony_ci 5573f4cbf05Sopenharmony_ci ErrCode Initialize(); 5583f4cbf05Sopenharmony_ci void Uninitialize(); 5593f4cbf05Sopenharmony_ci 5603f4cbf05Sopenharmony_ci bool Start(IOEventReactor* reactor); 5613f4cbf05Sopenharmony_ci bool Stop(IOEventReactor* reactor); 5623f4cbf05Sopenharmony_ci 5633f4cbf05Sopenharmony_ci inline void SetTimerId(const uint32_t& id) { timerId_ = id; } 5643f4cbf05Sopenharmony_ci 5653f4cbf05Sopenharmony_ci inline void SetTimerEventCallback(const TimerEventCallback& callback) { timerEventCallback_ = callback; } 5663f4cbf05Sopenharmony_ci 5673f4cbf05Sopenharmony_ci inline uint32_t GetInterval() const { return interval_; } 5683f4cbf05Sopenharmony_ci inline int GetTimerFd() const { return handler_->GetFd(); } 5693f4cbf05Sopenharmony_ci inline uint32_t GetTimerId() const { return timerId_; } 5703f4cbf05Sopenharmony_ci 5713f4cbf05Sopenharmony_ciprivate: 5723f4cbf05Sopenharmony_ci void TimeOut(); 5733f4cbf05Sopenharmony_ci 5743f4cbf05Sopenharmony_ciprivate: 5753f4cbf05Sopenharmony_ci bool once_; 5763f4cbf05Sopenharmony_ci uint32_t timerId_; 5773f4cbf05Sopenharmony_ci uint32_t interval_; 5783f4cbf05Sopenharmony_ci std::unique_ptr<IOEventHandler> handler_; 5793f4cbf05Sopenharmony_ci TimerEventCallback timerEventCallback_; 5803f4cbf05Sopenharmony_ci 5813f4cbf05Sopenharmony_ci friend class Timer; 5823f4cbf05Sopenharmony_ci}; 5833f4cbf05Sopenharmony_ci 5843f4cbf05Sopenharmony_ciclass Timer { 5853f4cbf05Sopenharmony_cipublic: 5863f4cbf05Sopenharmony_ci using TimerCallback = std::function<void ()>; 5873f4cbf05Sopenharmony_ci using TimerCallbackPtr = std::shared_ptr<TimerCallback>; 5883f4cbf05Sopenharmony_ci using TimerEventCallback = TimerEventHandler::TimerEventCallback; 5893f4cbf05Sopenharmony_ci 5903f4cbf05Sopenharmony_ci explicit Timer(const std::string& name, int timeoutMs = 1000); 5913f4cbf05Sopenharmony_ci virtual ~Timer() 5923f4cbf05Sopenharmony_ci { 5933f4cbf05Sopenharmony_ci } 5943f4cbf05Sopenharmony_ci virtual uint32_t Setup(); 5953f4cbf05Sopenharmony_ci virtual void Shutdown(bool useJoin = true); 5963f4cbf05Sopenharmony_ci uint32_t Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once = false); 5973f4cbf05Sopenharmony_ci void Unregister(uint32_t timerId); 5983f4cbf05Sopenharmony_ci 5993f4cbf05Sopenharmony_ciprivate: 6003f4cbf05Sopenharmony_ci void MainLoop(); 6013f4cbf05Sopenharmony_ci void OnTimer(TimerEventHandler* handler, const TimerCallback& callback); 6023f4cbf05Sopenharmony_ci int GetTimerFd(uint32_t interval /* ms */); 6033f4cbf05Sopenharmony_ci uint32_t GetValidId() const; 6043f4cbf05Sopenharmony_ci void EraseUnusedTimerId(uint32_t interval, const std::vector<uint32_t>& unusedIds); 6053f4cbf05Sopenharmony_ci 6063f4cbf05Sopenharmony_ciprivate: 6073f4cbf05Sopenharmony_ci using TimerHandlerPtr = std::shared_ptr<TimerEventHandler>; 6083f4cbf05Sopenharmony_ci using TimerHandlerList = std::list<TimerHandlerPtr>; 6093f4cbf05Sopenharmony_ci 6103f4cbf05Sopenharmony_ci ErrCode ScheduleTimer(const TimerEventCallback& callback, uint32_t interval, uint32_t timerId, int& timerFd, 6113f4cbf05Sopenharmony_ci bool once); 6123f4cbf05Sopenharmony_ci void EraseExistNode(TimerHandlerPtr target); 6133f4cbf05Sopenharmony_ci ErrCode CancelTimer(TimerHandlerPtr target); 6143f4cbf05Sopenharmony_ci 6153f4cbf05Sopenharmony_ci std::map<uint32_t, TimerHandlerList> intervalToTimers_; 6163f4cbf05Sopenharmony_ci std::map<uint32_t, TimerHandlerPtr> timerHandlers_; 6173f4cbf05Sopenharmony_ci 6183f4cbf05Sopenharmony_ci std::string name_; 6193f4cbf05Sopenharmony_ci int timeoutMs_; 6203f4cbf05Sopenharmony_ci std::thread thread_; 6213f4cbf05Sopenharmony_ci std::unique_ptr<IOEventReactor> reactor_; 6223f4cbf05Sopenharmony_ci std::mutex mutex_; 6233f4cbf05Sopenharmony_ci}; 6243f4cbf05Sopenharmony_ci 6253f4cbf05Sopenharmony_ciTimer::Timer(const std::string& name, int timeoutMs) : name_(name), timeoutMs_(timeoutMs), 6263f4cbf05Sopenharmony_ci reactor_(new IOEventReactor()) {} 6273f4cbf05Sopenharmony_ci 6283f4cbf05Sopenharmony_civoid Timer::MainLoop() 6293f4cbf05Sopenharmony_ci{ 6303f4cbf05Sopenharmony_ci prctl(PR_SET_NAME, name_.c_str(), 0, 0, 0); 6313f4cbf05Sopenharmony_ci 6323f4cbf05Sopenharmony_ci reactor_->Run(timeoutMs_); 6333f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Loop finished" << std::endl; 6343f4cbf05Sopenharmony_ci 6353f4cbf05Sopenharmony_ci if (reactor_->CleanUp() != EVENT_SYS_ERR_OK) { 6363f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << 6373f4cbf05Sopenharmony_ci "Reactor Clean Failed. It will clean during deconstruction" << std::endl; 6383f4cbf05Sopenharmony_ci } 6393f4cbf05Sopenharmony_ci} 6403f4cbf05Sopenharmony_ci 6413f4cbf05Sopenharmony_ciuint32_t Timer::Setup() 6423f4cbf05Sopenharmony_ci{ 6433f4cbf05Sopenharmony_ci if (thread_.joinable()) { // avoid double assign to an active thread 6443f4cbf05Sopenharmony_ci return TIMER_ERR_INVALID_VALUE; 6453f4cbf05Sopenharmony_ci } 6463f4cbf05Sopenharmony_ci 6473f4cbf05Sopenharmony_ci if (reactor_->SetUp() != EVENT_SYS_ERR_OK) { 6483f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Setup reactor failed." << std::endl; 6493f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 6503f4cbf05Sopenharmony_ci } 6513f4cbf05Sopenharmony_ci 6523f4cbf05Sopenharmony_ci reactor_->EnableHandling(); 6533f4cbf05Sopenharmony_ci 6543f4cbf05Sopenharmony_ci std::thread loopThread(std::bind(&Timer::MainLoop, this)); 6553f4cbf05Sopenharmony_ci thread_.swap(loopThread); 6563f4cbf05Sopenharmony_ci 6573f4cbf05Sopenharmony_ci return TIMER_ERR_OK; 6583f4cbf05Sopenharmony_ci} 6593f4cbf05Sopenharmony_ci 6603f4cbf05Sopenharmony_civoid Timer::Shutdown(bool useJoin) 6613f4cbf05Sopenharmony_ci{ 6623f4cbf05Sopenharmony_ci if (!thread_.joinable()) { 6633f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Invalid operation. Already shutdown." << std::endl; 6643f4cbf05Sopenharmony_ci return; 6653f4cbf05Sopenharmony_ci } 6663f4cbf05Sopenharmony_ci 6673f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Stop reactor." << std::endl; 6683f4cbf05Sopenharmony_ci reactor_->Terminate(); 6693f4cbf05Sopenharmony_ci 6703f4cbf05Sopenharmony_ci if (!useJoin) { 6713f4cbf05Sopenharmony_ci thread_.detach(); 6723f4cbf05Sopenharmony_ci return; 6733f4cbf05Sopenharmony_ci } 6743f4cbf05Sopenharmony_ci thread_.join(); 6753f4cbf05Sopenharmony_ci} 6763f4cbf05Sopenharmony_ci 6773f4cbf05Sopenharmony_ciErrCode Timer::ScheduleTimer(const TimerEventCallback& callback, uint32_t interval, uint32_t timerId, 6783f4cbf05Sopenharmony_ci int& timerFd, bool once) 6793f4cbf05Sopenharmony_ci{ 6803f4cbf05Sopenharmony_ci std::shared_ptr<TimerEventHandler> handler = std::make_shared<TimerEventHandler>(timerFd, interval, once); 6813f4cbf05Sopenharmony_ci 6823f4cbf05Sopenharmony_ci handler->SetTimerId(timerId); 6833f4cbf05Sopenharmony_ci handler->SetTimerEventCallback(callback); 6843f4cbf05Sopenharmony_ci 6853f4cbf05Sopenharmony_ci uint32_t ret = handler->Initialize(); 6863f4cbf05Sopenharmony_ci if (ret != TIMER_ERR_OK) { 6873f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Init timer handler failed." << std::endl; 6883f4cbf05Sopenharmony_ci return ret; 6893f4cbf05Sopenharmony_ci } 6903f4cbf05Sopenharmony_ci if (!handler->Start(reactor_.get())) { 6913f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Start timer handler failed." << std::endl; 6923f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 6933f4cbf05Sopenharmony_ci } 6943f4cbf05Sopenharmony_ci timerHandlers_.emplace(timerId, handler); // Add to the id2handlers map 6953f4cbf05Sopenharmony_ci intervalToTimers_[interval].push_back(handler); // Add to interval2handlerlist map 6963f4cbf05Sopenharmony_ci timerFd = handler->GetTimerFd(); 6973f4cbf05Sopenharmony_ci return TIMER_ERR_OK; 6983f4cbf05Sopenharmony_ci} 6993f4cbf05Sopenharmony_ci 7003f4cbf05Sopenharmony_ci 7013f4cbf05Sopenharmony_ciuint32_t Timer::Register(const TimerCallback& callback, uint32_t interval /* ms */, bool once) 7023f4cbf05Sopenharmony_ci{ 7033f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 7043f4cbf05Sopenharmony_ci 7053f4cbf05Sopenharmony_ci // wrap the callback in OnTiner 7063f4cbf05Sopenharmony_ci TimerEventCallback wrappedCb = std::bind(&Timer::OnTimer, this, std::placeholders::_1, callback); 7073f4cbf05Sopenharmony_ci int timerFd = once ? IO_EVENT_INVALID_FD : GetTimerFd(interval); // Get timerFd 7083f4cbf05Sopenharmony_ci uint32_t timerId = GetValidId(); // Get timerId 7093f4cbf05Sopenharmony_ci 7103f4cbf05Sopenharmony_ci uint32_t ret = ScheduleTimer(wrappedCb, interval, timerId, timerFd, once); 7113f4cbf05Sopenharmony_ci if (ret != TIMER_ERR_OK) { 7123f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Try schedule task failed. timer-id:" << 7133f4cbf05Sopenharmony_ci timerId << ", interval:" << interval << "timer-fd:" << timerFd << std::endl; 7143f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 7153f4cbf05Sopenharmony_ci } 7163f4cbf05Sopenharmony_ci 7173f4cbf05Sopenharmony_ci return timerId; 7183f4cbf05Sopenharmony_ci} 7193f4cbf05Sopenharmony_ci 7203f4cbf05Sopenharmony_civoid Timer::EraseExistNode(TimerHandlerPtr target) 7213f4cbf05Sopenharmony_ci{ 7223f4cbf05Sopenharmony_ci auto handlerList = intervalToTimers_[target->interval_]; 7233f4cbf05Sopenharmony_ci auto itor = std::find(handlerList.begin(), handlerList.end(), target); 7243f4cbf05Sopenharmony_ci if (itor != handlerList.end()) { 7253f4cbf05Sopenharmony_ci handlerList.erase(itor); 7263f4cbf05Sopenharmony_ci } 7273f4cbf05Sopenharmony_ci 7283f4cbf05Sopenharmony_ci if (handlerList.empty()) { 7293f4cbf05Sopenharmony_ci intervalToTimers_.erase(target->interval_); 7303f4cbf05Sopenharmony_ci } 7313f4cbf05Sopenharmony_ci} 7323f4cbf05Sopenharmony_ci 7333f4cbf05Sopenharmony_ciErrCode Timer::CancelTimer(TimerHandlerPtr target) 7343f4cbf05Sopenharmony_ci{ 7353f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Cancle timer handler with fd:" << target->GetTimerFd() << std::endl; 7363f4cbf05Sopenharmony_ci target->Uninitialize(); 7373f4cbf05Sopenharmony_ci if (!target->Stop(reactor_.get())) { 7383f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Stop timer handler failed." << std::endl; 7393f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 7403f4cbf05Sopenharmony_ci } 7413f4cbf05Sopenharmony_ci timerHandlers_.erase(target->timerId_); 7423f4cbf05Sopenharmony_ci EraseExistNode(target); 7433f4cbf05Sopenharmony_ci return TIMER_ERR_OK; 7443f4cbf05Sopenharmony_ci} 7453f4cbf05Sopenharmony_ci 7463f4cbf05Sopenharmony_civoid Timer::Unregister(uint32_t timerId) 7473f4cbf05Sopenharmony_ci{ 7483f4cbf05Sopenharmony_ci std::lock_guard<std::mutex> lock(mutex_); 7493f4cbf05Sopenharmony_ci 7503f4cbf05Sopenharmony_ci if (timerHandlers_.find(timerId) == timerHandlers_.end()) { 7513f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << 7523f4cbf05Sopenharmony_ci "Unregister failed. timer-id:" << timerId << " not found." << std::endl; 7533f4cbf05Sopenharmony_ci return; 7543f4cbf05Sopenharmony_ci } 7553f4cbf05Sopenharmony_ci 7563f4cbf05Sopenharmony_ci auto entry = timerHandlers_[timerId]; 7573f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Try remove timer handler from reactor. timerId:" << timerId << 7583f4cbf05Sopenharmony_ci ", interval:" << entry->interval_ << std::endl; 7593f4cbf05Sopenharmony_ci 7603f4cbf05Sopenharmony_ci if (CancelTimer(entry) != TIMER_ERR_OK) { 7613f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Unregister timer handler failed." << std::endl; 7623f4cbf05Sopenharmony_ci } 7633f4cbf05Sopenharmony_ci} 7643f4cbf05Sopenharmony_ci 7653f4cbf05Sopenharmony_civoid Timer::OnTimer(TimerEventHandler* handler, const TimerCallback& callback) 7663f4cbf05Sopenharmony_ci{ 7673f4cbf05Sopenharmony_ci callback(); 7683f4cbf05Sopenharmony_ci 7693f4cbf05Sopenharmony_ci if (handler->once_) { 7703f4cbf05Sopenharmony_ci Unregister(handler->timerId_); 7713f4cbf05Sopenharmony_ci } 7723f4cbf05Sopenharmony_ci} 7733f4cbf05Sopenharmony_ci 7743f4cbf05Sopenharmony_ciuint32_t Timer::GetValidId() const 7753f4cbf05Sopenharmony_ci{ 7763f4cbf05Sopenharmony_ci static std::atomic_uint32_t timerId = 1; 7773f4cbf05Sopenharmony_ci 7783f4cbf05Sopenharmony_ci while (timerHandlers_.find(timerId) != timerHandlers_.end()) { 7793f4cbf05Sopenharmony_ci timerId = timerId + 1; 7803f4cbf05Sopenharmony_ci if (timerId == UINT32_MAX) { 7813f4cbf05Sopenharmony_ci timerId = 1; 7823f4cbf05Sopenharmony_ci } 7833f4cbf05Sopenharmony_ci 7843f4cbf05Sopenharmony_ci if (timerId == TIMER_ERR_DEAL_FAILED) { 7853f4cbf05Sopenharmony_ci timerId = timerId + 1; 7863f4cbf05Sopenharmony_ci } 7873f4cbf05Sopenharmony_ci } 7883f4cbf05Sopenharmony_ci 7893f4cbf05Sopenharmony_ci return timerId; 7903f4cbf05Sopenharmony_ci} 7913f4cbf05Sopenharmony_ci 7923f4cbf05Sopenharmony_ciint Timer::GetTimerFd(uint32_t interval /* ms */) 7933f4cbf05Sopenharmony_ci{ 7943f4cbf05Sopenharmony_ci if (intervalToTimers_.find(interval) == intervalToTimers_.end()) { 7953f4cbf05Sopenharmony_ci return IO_EVENT_INVALID_FD; 7963f4cbf05Sopenharmony_ci } 7973f4cbf05Sopenharmony_ci auto &handlerList = intervalToTimers_[interval]; 7983f4cbf05Sopenharmony_ci for (const TimerHandlerPtr &ptr : handlerList) { 7993f4cbf05Sopenharmony_ci if (!ptr->once_) { 8003f4cbf05Sopenharmony_ci return ptr->GetTimerFd(); 8013f4cbf05Sopenharmony_ci } 8023f4cbf05Sopenharmony_ci } 8033f4cbf05Sopenharmony_ci return IO_EVENT_INVALID_FD; 8043f4cbf05Sopenharmony_ci} 8053f4cbf05Sopenharmony_ci 8063f4cbf05Sopenharmony_ciTimerEventHandler::TimerEventHandler(int timerFd, uint32_t timeout /* ms */, bool once) 8073f4cbf05Sopenharmony_ci : once_(once), interval_(timeout) 8083f4cbf05Sopenharmony_ci{ 8093f4cbf05Sopenharmony_ci if (timerFd == IO_EVENT_INVALID_FD) { 8103f4cbf05Sopenharmony_ci handler_ = std::make_unique<IOEventHandler>(timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC)); 8113f4cbf05Sopenharmony_ci } else { 8123f4cbf05Sopenharmony_ci handler_ = std::make_unique<IOEventHandler>(timerFd); 8133f4cbf05Sopenharmony_ci } 8143f4cbf05Sopenharmony_ci} 8153f4cbf05Sopenharmony_ci 8163f4cbf05Sopenharmony_ciTimerEventHandler::~TimerEventHandler() 8173f4cbf05Sopenharmony_ci{ 8183f4cbf05Sopenharmony_ci if (close(handler_->GetFd()) != 0) { 8193f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Close timer-fd failed. fd:" << handler_->GetFd() << ", interval:" << 8203f4cbf05Sopenharmony_ci interval_ << ", once:" << once_ << std::endl; 8213f4cbf05Sopenharmony_ci } 8223f4cbf05Sopenharmony_ci handler_->SetFd(IO_EVENT_INVALID_FD); 8233f4cbf05Sopenharmony_ci} 8243f4cbf05Sopenharmony_ci 8253f4cbf05Sopenharmony_ciErrCode TimerEventHandler::Initialize() 8263f4cbf05Sopenharmony_ci{ 8273f4cbf05Sopenharmony_ci if (handler_->GetFd() == IO_EVENT_INVALID_FD) { 8283f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Invalid timer-fd:" << handler_->GetFd() << ", interval:" << 8293f4cbf05Sopenharmony_ci interval_ << ", once:" << once_ << std::endl; 8303f4cbf05Sopenharmony_ci return TIMER_ERR_INVALID_VALUE; 8313f4cbf05Sopenharmony_ci } 8323f4cbf05Sopenharmony_ci 8333f4cbf05Sopenharmony_ci struct itimerspec newValue = {{0, 0}, {0, 0}}; 8343f4cbf05Sopenharmony_ci timespec now{0, 0}; 8353f4cbf05Sopenharmony_ci if (clock_gettime(CLOCK_MONOTONIC, &now) == -1) { 8363f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Get current time failed." << std::endl; 8373f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 8383f4cbf05Sopenharmony_ci } 8393f4cbf05Sopenharmony_ci 8403f4cbf05Sopenharmony_ci // next time out time is now + interval 8413f4cbf05Sopenharmony_ci newValue.it_value.tv_sec = now.tv_sec + interval_ / MILLI_TO_BASE; 8423f4cbf05Sopenharmony_ci newValue.it_value.tv_nsec = now.tv_nsec + (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO; 8433f4cbf05Sopenharmony_ci if (newValue.it_value.tv_nsec >= NANO_TO_BASE) { 8443f4cbf05Sopenharmony_ci newValue.it_value.tv_sec = newValue.it_value.tv_sec + 1; 8453f4cbf05Sopenharmony_ci newValue.it_value.tv_nsec = newValue.it_value.tv_nsec % NANO_TO_BASE; 8463f4cbf05Sopenharmony_ci } 8473f4cbf05Sopenharmony_ci 8483f4cbf05Sopenharmony_ci if (once_) { 8493f4cbf05Sopenharmony_ci // interval, 0 means time out only once 8503f4cbf05Sopenharmony_ci newValue.it_interval.tv_sec = 0; 8513f4cbf05Sopenharmony_ci newValue.it_interval.tv_nsec = 0; 8523f4cbf05Sopenharmony_ci } else { 8533f4cbf05Sopenharmony_ci // interval 8543f4cbf05Sopenharmony_ci newValue.it_interval.tv_sec = interval_ / MILLI_TO_BASE; 8553f4cbf05Sopenharmony_ci newValue.it_interval.tv_nsec = (interval_ % MILLI_TO_BASE) * MILLI_TO_NANO; 8563f4cbf05Sopenharmony_ci } 8573f4cbf05Sopenharmony_ci 8583f4cbf05Sopenharmony_ci if (timerfd_settime(handler_->GetFd(), TFD_TIMER_ABSTIME, &newValue, nullptr) == -1) { 8593f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Set timer-fd failed. next:" << 8603f4cbf05Sopenharmony_ci static_cast<long long>(newValue.it_value.tv_sec) << "interval:" << 8613f4cbf05Sopenharmony_ci static_cast<long long>(newValue.it_interval.tv_sec) << std::endl; 8623f4cbf05Sopenharmony_ci return TIMER_ERR_DEAL_FAILED; 8633f4cbf05Sopenharmony_ci } 8643f4cbf05Sopenharmony_ci 8653f4cbf05Sopenharmony_ci handler_->SetCallback(std::bind(&TimerEventHandler::TimeOut, this)); 8663f4cbf05Sopenharmony_ci handler_->EnableRead(); 8673f4cbf05Sopenharmony_ci 8683f4cbf05Sopenharmony_ci return TIMER_ERR_OK; 8693f4cbf05Sopenharmony_ci} 8703f4cbf05Sopenharmony_ci 8713f4cbf05Sopenharmony_civoid TimerEventHandler::Uninitialize() 8723f4cbf05Sopenharmony_ci{ 8733f4cbf05Sopenharmony_ci handler_->DisableAll(); 8743f4cbf05Sopenharmony_ci} 8753f4cbf05Sopenharmony_ci 8763f4cbf05Sopenharmony_cibool TimerEventHandler::Start(IOEventReactor* reactor) 8773f4cbf05Sopenharmony_ci{ 8783f4cbf05Sopenharmony_ci if (handler_ == nullptr || !handler_->Start(reactor)) { 8793f4cbf05Sopenharmony_ci return false; 8803f4cbf05Sopenharmony_ci } 8813f4cbf05Sopenharmony_ci 8823f4cbf05Sopenharmony_ci return true; 8833f4cbf05Sopenharmony_ci} 8843f4cbf05Sopenharmony_ci 8853f4cbf05Sopenharmony_cibool TimerEventHandler::Stop(IOEventReactor* reactor) 8863f4cbf05Sopenharmony_ci{ 8873f4cbf05Sopenharmony_ci if (handler_ == nullptr || !handler_->Stop(reactor)) { 8883f4cbf05Sopenharmony_ci return false; 8893f4cbf05Sopenharmony_ci } 8903f4cbf05Sopenharmony_ci 8913f4cbf05Sopenharmony_ci return true; 8923f4cbf05Sopenharmony_ci} 8933f4cbf05Sopenharmony_ci 8943f4cbf05Sopenharmony_civoid TimerEventHandler::TimeOut() 8953f4cbf05Sopenharmony_ci{ 8963f4cbf05Sopenharmony_ci if (handler_->GetFd() == IO_EVENT_INVALID_FD) { 8973f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Invalid timerfd." << std::endl; 8983f4cbf05Sopenharmony_ci return; 8993f4cbf05Sopenharmony_ci } 9003f4cbf05Sopenharmony_ci uint64_t expirations = 0; 9013f4cbf05Sopenharmony_ci ssize_t n = ::read(handler_->GetFd(), &expirations, sizeof(expirations)); 9023f4cbf05Sopenharmony_ci if (n != sizeof(expirations)) { 9033f4cbf05Sopenharmony_ci std::cout << "||" << gettid() << "||" << "Reads " << static_cast<int>(n) << 9043f4cbf05Sopenharmony_ci " bytes instead of 8 from timer fd." << std::endl; 9053f4cbf05Sopenharmony_ci } 9063f4cbf05Sopenharmony_ci 9073f4cbf05Sopenharmony_ci if (timerEventCallback_) { 9083f4cbf05Sopenharmony_ci timerEventCallback_(this); 9093f4cbf05Sopenharmony_ci } 9103f4cbf05Sopenharmony_ci} 9113f4cbf05Sopenharmony_ci 9123f4cbf05Sopenharmony_cistd::atomic<int> g_data1(0); 9133f4cbf05Sopenharmony_civoid TimeOutCallback1() 9143f4cbf05Sopenharmony_ci{ 9153f4cbf05Sopenharmony_ci g_data1 += 1; 9163f4cbf05Sopenharmony_ci} 9173f4cbf05Sopenharmony_ci 9183f4cbf05Sopenharmony_cistd::atomic<int> g_data2(0); 9193f4cbf05Sopenharmony_civoid TimeOutCallback2() 9203f4cbf05Sopenharmony_ci{ 9213f4cbf05Sopenharmony_ci g_data2 = g_data2 + 1; 9223f4cbf05Sopenharmony_ci} 9233f4cbf05Sopenharmony_ci 9243f4cbf05Sopenharmony_ciint64_t CurMs() 9253f4cbf05Sopenharmony_ci{ 9263f4cbf05Sopenharmony_ci struct timeval tpend; 9273f4cbf05Sopenharmony_ci gettimeofday(&tpend, nullptr); 9283f4cbf05Sopenharmony_ci return (tpend.tv_sec * 1000000 + tpend.tv_usec) / 1000; // 1000000: s to us, 1000: us to ms 9293f4cbf05Sopenharmony_ci} 9303f4cbf05Sopenharmony_ci 9313f4cbf05Sopenharmony_ci/* 9323f4cbf05Sopenharmony_ci * @tc.name: testNewTimer001 9333f4cbf05Sopenharmony_ci * @tc.desc: test basic function of timer implemented by new event-system. 9343f4cbf05Sopenharmony_ci */ 9353f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer001, TestSize.Level0) 9363f4cbf05Sopenharmony_ci{ 9373f4cbf05Sopenharmony_ci g_data1 = 0; 9383f4cbf05Sopenharmony_ci Timer timer("test_timer"); 9393f4cbf05Sopenharmony_ci uint32_t ret = timer.Setup(); 9403f4cbf05Sopenharmony_ci EXPECT_EQ(Utils::TIMER_ERR_OK, ret); 9413f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, 1, true); 9423f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(15)); 9433f4cbf05Sopenharmony_ci timer.Shutdown(); 9443f4cbf05Sopenharmony_ci EXPECT_EQ(1, g_data1); 9453f4cbf05Sopenharmony_ci} 9463f4cbf05Sopenharmony_ci 9473f4cbf05Sopenharmony_ci/* 9483f4cbf05Sopenharmony_ci * @tc.name: testNewTimer002 9493f4cbf05Sopenharmony_ci * @tc.desc: test basic function of timer implemented by new event-system. 9503f4cbf05Sopenharmony_ci */ 9513f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer002, TestSize.Level0) 9523f4cbf05Sopenharmony_ci{ 9533f4cbf05Sopenharmony_ci g_data1 = 0; 9543f4cbf05Sopenharmony_ci g_data2 = 0; 9553f4cbf05Sopenharmony_ci Timer timer("test_timer"); 9563f4cbf05Sopenharmony_ci uint32_t ret = timer.Setup(); 9573f4cbf05Sopenharmony_ci EXPECT_EQ(Utils::TIMER_ERR_OK, ret); 9583f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, 1); 9593f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback2, 50); 9603f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(500)); 9613f4cbf05Sopenharmony_ci timer.Shutdown(); 9623f4cbf05Sopenharmony_ci EXPECT_GE(g_data1, 8); 9633f4cbf05Sopenharmony_ci EXPECT_GE(g_data2, 2); 9643f4cbf05Sopenharmony_ci} 9653f4cbf05Sopenharmony_ci 9663f4cbf05Sopenharmony_cistatic void TestTimerEvent(Timer& timer) 9673f4cbf05Sopenharmony_ci{ 9683f4cbf05Sopenharmony_ci uint32_t interval = 1; 9693f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, interval); 9703f4cbf05Sopenharmony_ci uint32_t interval2 = 2; 9713f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, interval2); 9723f4cbf05Sopenharmony_ci int sleepTime = 30; 9733f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); 9743f4cbf05Sopenharmony_ci timer.Shutdown(); 9753f4cbf05Sopenharmony_ci} 9763f4cbf05Sopenharmony_ci 9773f4cbf05Sopenharmony_ci/* 9783f4cbf05Sopenharmony_ci * @tc.name: testNewTimer003 9793f4cbf05Sopenharmony_ci * @tc.desc: test basic function of timer implemented by new event-system. 9803f4cbf05Sopenharmony_ci */ 9813f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer003, TestSize.Level0) 9823f4cbf05Sopenharmony_ci{ 9833f4cbf05Sopenharmony_ci g_data1 = 0; 9843f4cbf05Sopenharmony_ci Timer timer("test_timer"); 9853f4cbf05Sopenharmony_ci uint32_t ret = timer.Setup(); 9863f4cbf05Sopenharmony_ci EXPECT_EQ(Utils::TIMER_ERR_OK, ret); 9873f4cbf05Sopenharmony_ci TestTimerEvent(timer); 9883f4cbf05Sopenharmony_ci EXPECT_GE(g_data1, 5); 9893f4cbf05Sopenharmony_ci} 9903f4cbf05Sopenharmony_ci 9913f4cbf05Sopenharmony_ciclass A { 9923f4cbf05Sopenharmony_cipublic: 9933f4cbf05Sopenharmony_ci explicit A(int data) : data_(data), timer_("ATimer") {} 9943f4cbf05Sopenharmony_ci ~A() = default; 9953f4cbf05Sopenharmony_ci bool Init(); 9963f4cbf05Sopenharmony_ci int GetData() const {return data_;} 9973f4cbf05Sopenharmony_ci bool StartTimer(int milliseconds, bool once); 9983f4cbf05Sopenharmony_ci void StopTimer(); 9993f4cbf05Sopenharmony_ciprivate: 10003f4cbf05Sopenharmony_ci void TimeOutProc() 10013f4cbf05Sopenharmony_ci { 10023f4cbf05Sopenharmony_ci data_ -= 1; 10033f4cbf05Sopenharmony_ci }; 10043f4cbf05Sopenharmony_ci int data_; 10053f4cbf05Sopenharmony_ci Timer timer_; 10063f4cbf05Sopenharmony_ci}; 10073f4cbf05Sopenharmony_ci 10083f4cbf05Sopenharmony_cibool A::Init() 10093f4cbf05Sopenharmony_ci{ 10103f4cbf05Sopenharmony_ci return timer_.Setup() == Utils::TIMER_ERR_OK; 10113f4cbf05Sopenharmony_ci} 10123f4cbf05Sopenharmony_ci 10133f4cbf05Sopenharmony_civoid A::StopTimer() 10143f4cbf05Sopenharmony_ci{ 10153f4cbf05Sopenharmony_ci timer_.Shutdown(); 10163f4cbf05Sopenharmony_ci} 10173f4cbf05Sopenharmony_ci 10183f4cbf05Sopenharmony_cibool A::StartTimer(int milliseconds, bool once) 10193f4cbf05Sopenharmony_ci{ 10203f4cbf05Sopenharmony_ci uint32_t timerId = timer_.Register(std::bind(&A::TimeOutProc, this), milliseconds, once); 10213f4cbf05Sopenharmony_ci return timerId != Utils::TIMER_ERR_DEAL_FAILED; 10223f4cbf05Sopenharmony_ci} 10233f4cbf05Sopenharmony_ci 10243f4cbf05Sopenharmony_ci/* 10253f4cbf05Sopenharmony_ci * @tc.name: testNewTimer004 10263f4cbf05Sopenharmony_ci * @tc.desc: test wrapper of the timer implemented by new event-system. 10273f4cbf05Sopenharmony_ci */ 10283f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer004, TestSize.Level0) 10293f4cbf05Sopenharmony_ci{ 10303f4cbf05Sopenharmony_ci A a(10); 10313f4cbf05Sopenharmony_ci EXPECT_TRUE(a.Init()); 10323f4cbf05Sopenharmony_ci EXPECT_TRUE(a.StartTimer(1, true)); 10333f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(20)); 10343f4cbf05Sopenharmony_ci a.StopTimer(); 10353f4cbf05Sopenharmony_ci EXPECT_EQ(9, a.GetData()); 10363f4cbf05Sopenharmony_ci} 10373f4cbf05Sopenharmony_ci 10383f4cbf05Sopenharmony_cistatic void SleepLoop() 10393f4cbf05Sopenharmony_ci{ 10403f4cbf05Sopenharmony_ci int loops = 11; 10413f4cbf05Sopenharmony_ci int64_t desiredVal = 10; 10423f4cbf05Sopenharmony_ci int sleepTime = 10; 10433f4cbf05Sopenharmony_ci for (int i = 0; i < loops; i++) { 10443f4cbf05Sopenharmony_ci int64_t pre = CurMs(); 10453f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); 10463f4cbf05Sopenharmony_ci int64_t cur = CurMs(); 10473f4cbf05Sopenharmony_ci EXPECT_GE(cur - pre, desiredVal); 10483f4cbf05Sopenharmony_ci } 10493f4cbf05Sopenharmony_ci} 10503f4cbf05Sopenharmony_ci 10513f4cbf05Sopenharmony_cistatic void TimerEvent(Timer& timer) 10523f4cbf05Sopenharmony_ci{ 10533f4cbf05Sopenharmony_ci uint32_t timerId = 0; 10543f4cbf05Sopenharmony_ci uint32_t loops = 10; 10553f4cbf05Sopenharmony_ci uint32_t interval = 7; 10563f4cbf05Sopenharmony_ci int sleepTime = 10; 10573f4cbf05Sopenharmony_ci for (uint32_t i = 0; i < loops; i++) { 10583f4cbf05Sopenharmony_ci timerId = timer.Register(TimeOutCallback1, interval, true); 10593f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime)); 10603f4cbf05Sopenharmony_ci } 10613f4cbf05Sopenharmony_ci timer.Unregister(timerId); 10623f4cbf05Sopenharmony_ci timer.Unregister(timerId); 10633f4cbf05Sopenharmony_ci} 10643f4cbf05Sopenharmony_ci 10653f4cbf05Sopenharmony_ci/* 10663f4cbf05Sopenharmony_ci * @tc.name: testNewTimer005 10673f4cbf05Sopenharmony_ci * @tc.desc: test abnormal case of timer implemented by new event-system. 10683f4cbf05Sopenharmony_ci */ 10693f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer005, TestSize.Level0) 10703f4cbf05Sopenharmony_ci{ 10713f4cbf05Sopenharmony_ci g_data1 = 0; 10723f4cbf05Sopenharmony_ci Timer timer("test_timer", -1); 10733f4cbf05Sopenharmony_ci uint32_t ret = timer.Setup(); 10743f4cbf05Sopenharmony_ci EXPECT_EQ(Utils::TIMER_ERR_OK, ret); 10753f4cbf05Sopenharmony_ci TimerEvent(timer); 10763f4cbf05Sopenharmony_ci timer.Shutdown(); 10773f4cbf05Sopenharmony_ci timer.Shutdown(false); 10783f4cbf05Sopenharmony_ci EXPECT_GE(g_data1, 5); 10793f4cbf05Sopenharmony_ci} 10803f4cbf05Sopenharmony_ci 10813f4cbf05Sopenharmony_ci/* 10823f4cbf05Sopenharmony_ci * @tc.name: testNewTimer006 10833f4cbf05Sopenharmony_ci * @tc.desc: sleep test for ivi of timer implemented by new event-system. 10843f4cbf05Sopenharmony_ci */ 10853f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer006, TestSize.Level0) 10863f4cbf05Sopenharmony_ci{ 10873f4cbf05Sopenharmony_ci g_data1 = 0; 10883f4cbf05Sopenharmony_ci Timer timer("test_timer"); 10893f4cbf05Sopenharmony_ci uint32_t ret = timer.Setup(); 10903f4cbf05Sopenharmony_ci EXPECT_EQ(Utils::TIMER_ERR_OK, ret); 10913f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, 10); 10923f4cbf05Sopenharmony_ci 10933f4cbf05Sopenharmony_ci SleepLoop(); 10943f4cbf05Sopenharmony_ci timer.Shutdown(); 10953f4cbf05Sopenharmony_ci EXPECT_GE(g_data1, 10); 10963f4cbf05Sopenharmony_ci} 10973f4cbf05Sopenharmony_ci 10983f4cbf05Sopenharmony_ci/* 10993f4cbf05Sopenharmony_ci * @tc.name: testNewTimer007 11003f4cbf05Sopenharmony_ci * @tc.desc: recursive test of timer implemented by new event-system. 11013f4cbf05Sopenharmony_ci */ 11023f4cbf05Sopenharmony_civoid DoFunc(Timer &timer, int &count) 11033f4cbf05Sopenharmony_ci{ 11043f4cbf05Sopenharmony_ci (void)timer.Register( 11053f4cbf05Sopenharmony_ci [&timer, &count]() { 11063f4cbf05Sopenharmony_ci count = count + 1; 11073f4cbf05Sopenharmony_ci if (count > 9) { // 9: recursion depth 11083f4cbf05Sopenharmony_ci return; 11093f4cbf05Sopenharmony_ci } 11103f4cbf05Sopenharmony_ci DoFunc(timer, count); 11113f4cbf05Sopenharmony_ci }, 11123f4cbf05Sopenharmony_ci 10, true); // 10: interval 11133f4cbf05Sopenharmony_ci g_data1++; 11143f4cbf05Sopenharmony_ci} 11153f4cbf05Sopenharmony_ci 11163f4cbf05Sopenharmony_civoid DoFunc2(Timer &timer, int &count) 11173f4cbf05Sopenharmony_ci{ 11183f4cbf05Sopenharmony_ci (void)timer.Register( 11193f4cbf05Sopenharmony_ci [&timer, &count]() { 11203f4cbf05Sopenharmony_ci count = count + 1; 11213f4cbf05Sopenharmony_ci if (count > 9) { // 9: recursion depth 11223f4cbf05Sopenharmony_ci return; 11233f4cbf05Sopenharmony_ci } 11243f4cbf05Sopenharmony_ci DoFunc2(timer, count); 11253f4cbf05Sopenharmony_ci }, 11263f4cbf05Sopenharmony_ci 10, true); // 10: interval 11273f4cbf05Sopenharmony_ci g_data1++; 11283f4cbf05Sopenharmony_ci} 11293f4cbf05Sopenharmony_ci 11303f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer007, TestSize.Level0) 11313f4cbf05Sopenharmony_ci{ 11323f4cbf05Sopenharmony_ci g_data1 = 0; 11333f4cbf05Sopenharmony_ci Timer timer("test_timer"); 11343f4cbf05Sopenharmony_ci uint32_t ret = timer.Setup(); 11353f4cbf05Sopenharmony_ci EXPECT_EQ(Utils::TIMER_ERR_OK, ret); 11363f4cbf05Sopenharmony_ci 11373f4cbf05Sopenharmony_ci int cnt = 0; 11383f4cbf05Sopenharmony_ci int cnt1 = 0; 11393f4cbf05Sopenharmony_ci DoFunc(timer, cnt); 11403f4cbf05Sopenharmony_ci DoFunc2(timer, cnt1); 11413f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(50)); 11423f4cbf05Sopenharmony_ci EXPECT_GE(g_data1, 5); /* 8 for max */ 11433f4cbf05Sopenharmony_ci EXPECT_GE(14, g_data1); /* 10 for min */ 11443f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(50)); 11453f4cbf05Sopenharmony_ci timer.Shutdown(); 11463f4cbf05Sopenharmony_ci EXPECT_GE(g_data1, 10); /* 18 for max */ 11473f4cbf05Sopenharmony_ci} 11483f4cbf05Sopenharmony_ci 11493f4cbf05Sopenharmony_cistatic void TimerRegisterMechanism(Timer& timer) 11503f4cbf05Sopenharmony_ci{ 11513f4cbf05Sopenharmony_ci uint32_t interval = 10; 11523f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, interval, true); 11533f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, interval); 11543f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, interval, true); 11553f4cbf05Sopenharmony_ci timer.Register(TimeOutCallback1, interval); 11563f4cbf05Sopenharmony_ci} 11573f4cbf05Sopenharmony_ci 11583f4cbf05Sopenharmony_ci/* 11593f4cbf05Sopenharmony_ci * @tc.name: testNewTimer008 11603f4cbf05Sopenharmony_ci * @tc.desc: test execute-once and execute-periodly tasks. 11613f4cbf05Sopenharmony_ci */ 11623f4cbf05Sopenharmony_ciHWTEST_F(UtilsEventTest, testNewTimer008, TestSize.Level0) 11633f4cbf05Sopenharmony_ci{ 11643f4cbf05Sopenharmony_ci g_data1 = 0; 11653f4cbf05Sopenharmony_ci Timer timer("test_timer"); 11663f4cbf05Sopenharmony_ci uint32_t ret = timer.Setup(); 11673f4cbf05Sopenharmony_ci EXPECT_EQ(Utils::TIMER_ERR_OK, ret); 11683f4cbf05Sopenharmony_ci TimerRegisterMechanism(timer); 11693f4cbf05Sopenharmony_ci std::this_thread::sleep_for(std::chrono::milliseconds(52)); 11703f4cbf05Sopenharmony_ci timer.Shutdown(); 11713f4cbf05Sopenharmony_ci EXPECT_GE(g_data1, 8); /* 12 for max */ 11723f4cbf05Sopenharmony_ci} 11733f4cbf05Sopenharmony_ci 11743f4cbf05Sopenharmony_ci 11753f4cbf05Sopenharmony_ci} // namespace 11763f4cbf05Sopenharmony_ci} // namespace OHOS