CreateTimer
Principles
Figure 1 Process of invoking the interfaces for creating a timer shows the process of creating a timer.
- Initialize resources.
Before invoking the OpenHiva interface, invoke the OpenHiva::Init interface for initialization. If the return value is 0, the initialization is successful. Otherwise, the initialization fails.
Initialization includes timer node name registration, thread group creation, and resource application.- Node name registration:
- The names of different nodes must be unique. Otherwise, the nodes that are started later will fail to be initialized.
- If the initialization fails, the node cannot perform the publishing or subscription action.
- Thread group creation:
The thread group parameters need to be transferred when the OpenHiva::Init interface is invoked. Create a thread group (ScheduleGroup) as required in advance. Each thread group stores information about the callback function, including the thread group name (groupName) and thread group scheduling type (scheduleType).
The internal processing flow of OpenHiva varies according to the value of ThreadGroup.scheduleType in the thread group.
- UNBIND_AICPU (recommended): indicates threads in the non-deterministic domain. The thread group is not bound to cores. Each group starts a working thread waiting for the event to be activated. The operating system schedules the CPU on which the working thread runs.
- BIND_AICPU: indicates threads in the deterministic domain, and the thread group is bound to cores. A maximum of four working threads can be started in each group (depending on the number of CPU cores). Each working thread is bound to one core. The scheduling status is determined by the event scheduling mechanism. This mechanism provides high real-time performance, avoiding time jitter caused by kernel scheduling of the operating system to a large extent, and ensuring the determinism of thread switching from sleep to running.
- Node name registration:
- Create a timer.
- Before creating a timer, you must register a node, that is, create a node handle OpenHiva::Node n.
- Use the created node handle n to invoke the Hiva::CreateTimer interface to create a timer. After the interface is invoked, the Hiva::Timer object is returned.
When the CreateTimer interface is invoked, the input parameter groupName must be the same as that set in the OpenHiva::Init interface. In addition, the settings of the input parameters oneshot and autostart affect the number of times that the timer can be triggered and the startup mode of the timer.
- oneshot: indicates the number of times that the timer can be triggered.
- True: The timer uses the one-off oneshot mode. During the running time of the process, the timer is triggered only once.
- False (default value): indicates that the timer uses the periodic mode. During the running time of the process, the timer is triggered periodically until the process resources are cleared.
- autostart: indicates the startup mode of the timer.
- True (default value): indicates automatic startup. When the CreateTimer interface is returned, the timer is started.
- False: indicates that automatic startup is disabled. When the CreateTimer interface is returned, the timer is not started. You need to manually start the timer by invoking the Hiva::Timer::Start interface.
- oneshot: indicates the number of times that the timer can be triggered.
- You can use the Hiva::Timer object to start or stop the timer (Hiva::Timer::Start/Hiva::Timer::Stop) and set the timer triggering period (Hiva:Timer::SetPeriod).
The timer triggering period is the period for triggering the callback function. When the timer expires, the callback function of the user is executed.
- Release resources.
Before the process ends, invoke the OpenHiva::Shutdown interface to clear resources. After resources are released, the defined OpenHiva interfaces cannot be used.
Sample Code
The following is a code example of key steps for creating a timer (for reference only):
#include <cstdlib>
#include <chrono>
#include <thread>
#include <string>
#include <stdlib.h>
#include <Hiva.h>
#include "Hiva_time/Hiva_time.h"
#include "Hiva_timer/timer.h"
#include "open/init.h"
#include "open/node.h"
// Subfunction of the callback function, which is user-defined.
static void PrintEvent(const Hiva::TimerEvent &evt)
{
std::cout<<"\tlastExpected:"<<evt.lastExpected<<std::endl; // Time when the last callback should occur
std::cout<<"\tlastReal:"<<evt.lastReal<<std::endl; // Time when the last callback occurred
std::cout<<"\tlastExpired:"<<evt.lastExpired<<std::endl; // Time when the last timer expires on the timer server and a notification is sent to the application
std::cout<<"\tcurrentExpected:"<<evt.currentExpected<<std::endl; // Time when the current callback should occur
std::cout<<"\tcurrenReal:"<<evt.currentReal<<std::endl; // Time when the current callback occurred
std::cout<<"\tcurrenExpired:"<<evt.currentExpired<<std::endl; // Time when the current timer expires on the timer server and a notification is sent to the application
}
// Users define callback functions based on their own service logic for processing after the timer expires.
static void callback1(const Hiva::TimerEvent &evt)
{
HIVA_INFO("callback1 called:");
PrintEvent(evt);
}
int main(int argc, char **argv)
{
// 1. Initialize resources.
bool oneshot = false; // Indicates the triggering mode, which can be one-off triggering or periodic triggering.
bool autostart = true; // Indicates whether the timer is automatically started or manually started.
int32_t sec = 1; // Indicates timer triggering period.
int32_t sleepDuration = 60; // Indicates run time of the simulation process.
if (argc == 1) {
HIVA_INFO("Default: oneshot: %d, autostart: %d, duration: %d, process sleep time:%d",
(int)oneshot, (int)autostart, sec, sleepDuration);
} elseif (argc == 5) {
oneshot = (bool)strtol(argv[1], NULL, 10);
autostart = (bool)strtol(argv[2], NULL, 10);
sec = (int32_t)strtol(argv[3], NULL, 10);
sleepDuration = (int32_t)strtol(argv[4], NULL, 10);
HIVA_INFO("oneshot: %d, autostart: %d, duration: %d, process sleep time:%d", (int)oneshot, (int)autostart, sec, sleepDuration);
} else {
HIVA_ERROR("Input para is wrong, should be no input or 4 paras: oneshot, autostart, duration, process sleep time\n");
return -1;
}
// Define a thread group.
std::vector<OpenHiva::ScheduleGroup> threadGroup;
OpenHiva::ScheduleGroup testGroup;
testGroup.groupName = "timer";
testGroup.scheduleType = OpenHiva::ScheduleType::UNBIND_AICPU;
threadGroup.push_back(testGroup);
// Invoke the resource initialization interface.
OpenHiva::Init(argc,argv,threadGroup);
// 2. Create a timer.
// Construct the Node object.
OpenHiva::Node node("timer_client_test");
HIVA_INFO("timer test: Client test start timer");
// Use the CreateTimer interface to create a timer. The value of groupName must be the same as that of ThreadGroup.groupName in the Init interface.
Hiva::Timer t = Hiva::CreateTimer(Hiva::Duration(sec), callback1, "timer", oneshot, autostart);
HIVA_INFO("timer test: client test start to sleep");
std::this_thread::sleep_for(std::chrono::seconds(sleepDuration));
HIVA_INFO("timer test: finish sleep");
// 3. Release resources.
// When the process ends, invoke the ShutDown function to release resources.
OpenHiva::Shutdown();
return0;
}
