This file contains the working logic of the events. It starts the work of the input-output reactor (IO module), as well as the binding of processor cores to the processing threads (dap_worker_t).
FUNCTIONS
- dap_events_workers_init_status - worker initialization checkage
- dap_get_cpu_count - counting CPU cores
- dap_cpu_assign_thread_on - threads to cores assigning
- dap_events_init - events initialization
- dap_events_deinit - events deinitialization
- dap_events_start - events start (main loop of the server)
- dap_events_wait - waiting for events end
- dap_events_stop_all - events stop
- dap_events_worker_get_index_min - getting index of the worker with minimal loading
- dap_events_thread_get_count - counting threads
- dap_events_worker_get_auto - getting worker with minimal quantity of connected sockets
- dap_event_worker_get - getting worker by index
- dap_worker_print_all - printing workers
Worker initialization checkage
bool dap_events_workers_init_status()
---
Return: boolean
Arguments:
Function receives no arguments.
Description:
Returns true
if the workers are initialized, false
otherwise.
Counting CPU cores
uint32_t dap_get_cpu_count( )
---
Return: uint32_t (number of cores)
Arguments:
Function receives no arguments.
Description:
Uses system tools to count the number of processor cores. For each system, the count is made according to the system features.
Threads to cores assigning
void dap_cpu_assign_thread_on(uint32_t a_cpu_id)
---
Return: uint32_t a_cpu_id (number of cores, counted previously)
Arguments:
uint32_t a_cpu_id
: This is the ID of the CPU core to which the thread should be assigned. The core numbers are typically counted from 0 and represent the available CPU cores in the system.
Description:
The function assigns threads to individual cores.
The function body also provides a handler for errors that may occur during the function’s operation:
EFAULT
: Invalid memory address.EINVAL
: Invalid affinity mask.ESRCH
: Thread not found.EPFNOSUPPORT
: System doesn’t support thread affinity.default
: Unknown error.
The constructed error message is logged using the log_it
function, providing information about the error code, message, and the affected CPU ID (a_cpu_id
).
Events initialization
int dap_events_init( uint32_t a_threads_count, size_t a_conn_timeout )
---
Return: int (0 if everything is ok, others if not)
Arguments:
uint32_t a_threads_count
: This parameter specifies the number of threads to be created for event handling. It determines how many worker threads will be used to process events concurrently.size_t a_conn_timeout
: This parameter defines the connection timeout, in seconds. It sets the maximum amount of time to wait for a connection before considering it as timed out.
Description:
The function initializes event handlers using a pointer to a dap_worker_t structure, and as a result prints a message that the event reactor for a certain number of threads has been initialized.
Initialization of event handlers also leads to the initialization of the dap_context and dap_events_socket modules.
In case of an error, the handlers are deinitialized using the dap_events_deinit() function.
The function also checks the number of threads; if there are more than cores, the number of threads is limited by the number of cores.
Events deinitialization
void dap_events_deinit( )
---
Return: void
Arguments:
Function receives no arguments.
Description:
During the function’s operation, proc threads, event sockets, and workers are deinitialized using the dap_proc_thread_deinit, dap_events_socket_deinit(), and dap_worker_deinit functions, respectively.
The dap_event_wait() function is also called, which terminates the use of threads one by one, sequentially waiting for each of them to complete before moving on to the next.
Events start (main loop of the server)
int dap_events_start()
---
Return: int (0 if everyhting is ok, others if not)
Arguments:
Function receives no arguments.
Description:
This function is responsible for starting the server event loop.
- First, it checks whether the dap_events_init() event reactor is running; if not, it returns an error with the code
-1
. - Then, for all workers (the number of workers = the number of threads), a dap_worker_t structure is created; if the pointer to the structure is empty, the function returns the error
-6: memory allocation error
. - After memory allocation, the context creation functions are launched for each worker: dap_context_new(), dap_context_run(), dap_worker_context_callback_started() and dap_worker_context_callback_stopped(). If any of the functions does not work as expected, the system will notify that the handler could not be started.
Then, for all OS except Windows, intercontextual queues are created that control the input/output sequence:
- For each worker, memory is allocated in pointer structures to dap_events_socket_t, which represent different types of queues.
If the pointer to the structure is empty, the function will return the error -6: memory allocation error
.
- After initialization and memory allocation, event sockets of these queues are created for each handler using the functions dap_events_socket_queue_ptr_create_input() and dap_worker_add_events_socket_unsafe().
After all the above actions, the proc threads are initialized; if for some reason initialization is impossible, the system will return the error -4
.
At the end of the function, an error handler is provided that checks which of the workers has not been initialized. When this worker is found, the structure that contains it is completely deleted. Moreover, for all operating systems except Windows, all structures created for the implementation of queues are also deleted.
Waiting for events end
int dap_events_wait( )
---
Return: int (always 0)
Arguments:
Function receives no arguments.
Description:
This function waits for the end of the worker threads. Only after all workers have completed their work, they can be disabled.
Events stop
void dap_events_stop_all( )
---
Return: void
Arguments:
Function receives no arguments.
Description:
At the beginning, the function checks whether the event reactor dap_events_init() is initialized, if it is running, then in the loop each thread is turned off in turn (event_exit).
Getting index of the worker with minimal loading
uint32_t dap_events_worker_get_index_min()
---
Return: uint32_t (worker index with the minimum index, at the beginning of the function is 0)
Arguments:
Function receives no arguments.
Description:
At the beginning, the function checks whether the dap_events_init() event reactor is initialized; if it is not running, the error -1
is returned.
Then, in the loop, the threads of handlers are sorted out, and the handler with the fewest sockets connected is found.
Counting threads
uint32_t dap_events_thread_get_count()
---
Return: uint32_t (number of threads)
Arguments:
Function receives no arguments.
Description:
This function counts active threads.
Getting worker with minimal quantity of connected sockets
dap_worker_t *dap_events_worker_get_auto( )
---
Return: dap_worker_t* (worker)
Arguments:
Function receives no arguments.
Description:
The function first checks whether the dap_events_init() event reactor is running, if not, an error is displayed.
The function returns a worker thread (a pointer to a dap_worker_t structure) with a minimum load calculated using the dap_events_worker_get_index_min function().
Getting worker by index
dap_worker_t * dap_events_worker_get(uint8_t a_index)
---
Return: dap_worker_t * (worker, returns NULL if index is incorrect)
Arguments:
uint8_t a_index
: Index of the worker.
Description:
The function first checks whether the dap_events_init() event reactor is running, if not, an error is displayed.
The function returns a worker thread (a pointer to a dap_worker_t structure) with specified index.
Printing workers
void dap_worker_print_all( )
---
Return: void
Arguments:
Function receives no arguments.
Description:
The function first checks whether the dap_events_init() event reactor is running, if not, an error is displayed.
The function prints the number of event sockets for each handler thread.