<译文内容>
IApplication User Documentation¶
Quick Start¶
Creating Application Instance¶
To get started with IApplication, let's create a simple example:
Description:
- The constructor automatically parses command-line arguments and initializes the ASIO context.
run()starts the event loop, blocking until the application exits (e.g., receivingCtrl+C).
When the above code runs, the console output is as follows:
This outputs the IWebCore banner content in the console.
Adding Detailed Task Output¶
We add one line to the code as follows:
The $EnableTaskOutput(true) is a macro annotation. For details on macro annotations, refer to the specific documentation. After adding this line, the console output is as follows:
The additional content above is task information, which are all tasks pre-registered by default in ICore. Normally, they are not displayed unless the $EnableTaskOutput(true) macro annotation is present. The user can understand why we did not add any output statements and why IApplication does not contain any output related to IWebCore but the information is still outputted because IWebCore::IBannerTask is registered in the system and executed during task execution.
For details on macro annotations and tasks, we will delve deeper in the following sections.
About IApplication¶
Why Do We Need an Application¶
In many programs, the concept of an Application exists. The Application starts the program at the beginning, using exec() or run() to start the event loop, preventing the program from exiting unexpectedly. Before the event loop, the Application also initializes the necessary runtime environment for the entire program.
ICore is no different. It is the core framework of an application, providing the following core capabilities:
- Standardized Initialization Process: Automatically parses command-line arguments (
argc, argv), loads basic configurations (such as thread count, unit test switches), and creates a Qt environment compatibility layer (QCoreApplication). - Asynchronous Task Scheduling: Implements high-concurrency processing based on the ASIO event-driven model.
- Centralized Resource Management: Ensures the uniqueness of core resources such as ASIO context, timers, and asynchronous tasks through singleton patterns (
IAsioContext,ITaskManage), avoiding duplicate creation and resource leaks. - Cross-Platform Support: Encapsulates the handling of Windows
Ctrl+Csignals and LinuxSIGINT/SIGTERM, providing a unified graceful exit mechanism. - Infrastructure Integration: Provides ready-to-use components such as timers, configuration management, and unit testing.
- Event Loop Provision: Uses asio's event loop to prevent program exit and provides asynchronous execution capabilities.
IAsioApplication¶
In ICore, IAsioApplication is named as IApplication.
It is the core application class based on ASIO, inheriting from IApplicationInterface, providing complete event loop capabilities. The declaration is as follows:
IApplicationInterface¶
This is a template class defining the basic framework specifications. The declaration is as follows:
Features¶
Run Registered Tasks¶
The primary purpose of IApplication is to run tasks that have been registered in the program. These tasks are the main body of the program, providing individual functionality points, such as the IBannerTask mentioned above, which outputs IWebCore information to the console. For specific details, refer to the Task documentation. The way to run these tasks is simple: call the following code in the run function:
Through the fifth line of the above code, any functionality registered by the user can be invoked within the framework. For example, if a database is registered by the user, it will be initialized here; if a Controller object is registered, it will be mounted into the ControllerMapping for subsequent querying and invocation by HTTP requests; if a Bean is registered, it can be used for automatic JSON conversion; if a system task like IBannerTask is registered, the IWebCore banner will be outputted in the console.
Provide Asio-Based Event Loop¶
ICore's IApplication initially used QCoreApplication, which is provided by Qt for the event loop. During development, it gradually transitioned to an asio-based event loop. This provides a more robust multi-core event loop mechanism and is more universal.
If the user needs a Qt event loop or any other type of event loop, they can implement their own IApplication.
In ICore, the asio event loop is encapsulated in IAsioContext. In IAsioApplication, the asio event loop is invoked as follows:
On line 3, we add a signal handler to allow program exit via ctrl c. Lines 5-8 calculate an appropriate number of threads. On line 9, the event loop begins, and services registered in the program can now be provided.
Thread Count¶
If the user does not set the thread count, the default is std::thread::hardware_concurrency() * 2, which is twice the number of hardware-supported threads. The user can set the thread count using the following methods:
This example shows two ways to set thread count. On line 3, the thread count is set via a macro annotation: $SetAppThreadCount(5). On line 6, the thread count is set programmatically: app.setThreadCount(4);. The programmatically set value has higher priority, so the thread count is set to 4.
Additionally, the user can set the thread count via configuration. For details on configuration, refer to the Config module.
Parameters and Application Path¶
ICore automatically parses command-line arguments. The user can retrieve the input parameters using arguments, as follows:
ICore also provides an applicationPath to inform the user of the current executable path.
Provide Non-Precise Timestamp¶
For high-performance C++ programs, obtaining time is an expensive operation. However, programs often do not need precise time but rather a relative, approximate time. The concept of approximate time means the time is accurate to a certain granularity (e.g., seconds). The concept of relative time means that each retrieval must return a different time, and the time must be later than the previous one.
ICore's application provides such a timestamp. It is a 64-bit atomic integer, where a number represents 1 nanosecond. The time is relative to the epoch (January 1, 1970). This timestamp updates automatically every second. Each time the user requests it, the number increments by 1 and is returned.
The reason for using nanoseconds is that no program is expected to request 1 billion times per second (10^9 requests per second). If such a requirement exists, it is beyond the scope of ICore.
This timestamp can be obtained via IApplication::time(), suitable for non-high-precision needs such as logging timestamps.
Other Content¶
IAsioContext¶
A partial declaration of IAsioContext is as follows:
In this function, note the following:
- Line 6 provides an asynchronous task posting capability.
- Line 7 starts a timer and returns a handle.
- Line 8 stops the timer using the handle.
The reason for using std::ptrdiff_t is that we essentially create an object, convert its address to std::ptrdiff_t, and return it. The stopTimer function reconverts the std::ptrdiff_t back to a pointer for subsequent operations.
The example is as follows:
```c++ auto timerId = IAsioContext::startTimer(1000ms, { std::cout << "每秒触发" << std::endl; }); // Stop the timer IAsioContext::stopTimer(timerId);