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