Nilorea Library
C utilities for networking, threading, graphics
Loading...
Searching...
No Matches
ex_threads.c
Go to the documentation of this file.
1/*
2 * Nilorea Library
3 * Copyright (C) 2005-2026 Castagnier Mickael
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14 * implied. See the License for the specific language governing
15 * permissions and limitations under the License.
16 *
17 * SPDX-License-Identifier: Apache-2.0
18 */
19
28#include <stdio.h>
29#include <errno.h>
30#include <string.h>
31
32#include "nilorea/n_log.h"
33#include "nilorea/n_time.h"
35
36void usage(void) {
37 fprintf(stderr,
38 " -v version\n"
39 " -h help\n"
40 " -V LOG_LEVEL (LOG_DEBUG,INFO,NOTICE,ERR)\n");
41}
42
43void process_args(int argc, char** argv) {
44 int getoptret = 0,
45 log_level = LOG_ERR; /* default log level */
46
47 while ((getoptret = getopt(argc, argv, "vhV:")) != EOF) {
48 switch (getoptret) {
49 case 'v':
50 fprintf(stderr, "Date de compilation : %s a %s.\n", __DATE__, __TIME__);
51 exit(1);
52 case 'V':
53 if (!strcmp("LOG_NULL", optarg))
55 else if (!strcmp("LOG_NOTICE", optarg))
57 else if (!strcmp("LOG_INFO", optarg))
59 else if (!strcmp("LOG_ERR", optarg))
61 else if (!strcmp("LOG_DEBUG", optarg))
63 else {
64 fprintf(stderr, "%s n'est pas un niveau de log valide.\n", optarg);
65 exit(-1);
66 }
67 break;
68 default:
69 case '?': {
70 if (optopt == 'V') {
71 fprintf(stderr, "\n Missing log level\n");
72 }
73 usage();
74 exit(1);
75 }
76 case 'h': {
77 usage();
78 exit(1);
79 }
80 } /* switch */
82 }
83} /* void process_args( ... ) */
84
85void* occupy_thread(void* rest) {
86 __n_assert(rest, return NULL);
87
88 intptr_t sleep_value = (intptr_t)(rest);
89
90 n_log(LOG_DEBUG, "Starting to sleep %d usecs on thread %lld", sleep_value, pthread_self());
91
92 if (sleep_value < 1000000) {
93 usleep((unsigned int)sleep_value);
94 } else {
95 usleep((unsigned int)((sleep_value) % 1000000));
96 sleep((unsigned int)(sleep_value / 1000000));
97 }
98
99 n_log(LOG_DEBUG, "End of sleep %d usecs on thread %lld", sleep_value, pthread_self());
100
101 return NULL;
102}
103
104int main(int argc, char** argv) {
105 long int cores = get_nb_cpu_cores();
106 int nb_active_threads = (cores > 0) ? (int)cores : 1;
107 int nb_waiting_threads = 2 * nb_active_threads;
108 int nb_total_threads = (nb_active_threads + nb_waiting_threads);
109
111
112 // processing args and set log_level
113 process_args(argc, argv);
114
115 n_log(LOG_INFO, "Creating a new thread pool of %d active and %d waiting threads", nb_active_threads, nb_waiting_threads);
116 THREAD_POOL* thread_pool = new_thread_pool((size_t)nb_active_threads, (size_t)nb_waiting_threads);
117
118 n_log(LOG_INFO, "Adding new %d new tasks...", nb_total_threads);
119 for (int it = 0; it < nb_total_threads; it++) {
120 n_log(LOG_INFO, "adding task %d", it);
121 // sleep time as a payload to the occupy_thread
122 int sleep_value = 1 + rand() % 1000000;
123 // add task and payload
124 if (add_threaded_process(thread_pool, &occupy_thread, (void*)(intptr_t)sleep_value, NORMAL_PROC) == FALSE) {
125 n_log(LOG_ERR, "Error adding client management to thread pool");
126 }
127 }
128 n_log(LOG_INFO, "Adding tasks done. Waiting for pool thread to complete the tasks...");
130
131 n_log(LOG_INFO, "Task completed. Destroying pool...");
133 n_log(LOG_INFO, "Destroyed.");
134
135 /* test SYNCED_PROC with start_threaded_pool and wait_for_synced_threaded_pool */
136 n_log(LOG_INFO, "--- Synced thread pool test ---");
137 thread_pool = new_thread_pool((size_t)nb_active_threads, (size_t)nb_waiting_threads);
138 for (int it = 0; it < nb_active_threads; it++) {
139 int sleep_value = 1 + rand() % 500000;
140 if (add_threaded_process(thread_pool, &occupy_thread, (void*)(intptr_t)sleep_value, SYNCED_PROC) == FALSE) {
141 n_log(LOG_ERR, "Error adding synced process %d", it);
142 }
143 }
144 n_log(LOG_INFO, "Starting synced pool...");
146
147 n_log(LOG_INFO, "Waiting for synced pool...");
149
150 n_log(LOG_INFO, "Synced pool done. Testing refresh_thread_pool...");
152
154 n_log(LOG_INFO, "All thread pool tests done.");
155
156 exit(0);
157} /* END_OF_MAIN() */
static void usage(void)
int main(void)
void process_args(int argc, char **argv)
Definition ex_common.c:48
THREAD_POOL * thread_pool
Definition ex_fluid.c:76
int getoptret
Definition ex_fluid.c:59
int log_level
Definition ex_fluid.c:60
void * occupy_thread(void *rest)
Definition ex_threads.c:85
#define __n_assert(__ptr, __ret)
macro to assert things
Definition n_common.h:279
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
Definition n_log.h:89
#define LOG_DEBUG
debug-level messages
Definition n_log.h:84
#define LOG_ERR
error conditions
Definition n_log.h:76
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition n_log.c:121
#define LOG_NOTICE
normal but significant condition
Definition n_log.h:80
#define LOG_NULL
no log output
Definition n_log.h:46
#define LOG_INFO
informational
Definition n_log.h:82
#define NORMAL_PROC
processing mode for added func, synced start, can be queued
int start_threaded_pool(THREAD_POOL *thread_pool)
Launch the process waiting for execution in the thread pool.
THREAD_POOL * new_thread_pool(size_t nbmaxthr, size_t nb_max_waiting)
Create a new pool of nbmaxthr threads.
#define SYNCED_PROC
processing mode for added func, synced start, not queued
int add_threaded_process(THREAD_POOL *thread_pool, void *(*func_ptr)(void *param), void *param, int mode)
add a function and params to a thread pool
int refresh_thread_pool(THREAD_POOL *thread_pool)
try to add some waiting DIRECT_PROCs on some free thread slots, else do nothing
int wait_for_threaded_pool(THREAD_POOL *thread_pool)
Wait for the thread pool to become idle (no active threads, empty waiting list), blocking without pol...
int destroy_threaded_pool(THREAD_POOL **pool, unsigned int delay)
delete a thread_pool, exit the threads and free the structs
int wait_for_synced_threaded_pool(THREAD_POOL *thread_pool)
wait for all the launched process, blocking but light on the CPU as there is no polling
long int get_nb_cpu_cores()
get number of core of current system
Structure of a thread pool.
Generic log system.
Thread pool declaration.
Timing utilities.