Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Merge branch 'public_smpi_func' into 'master'
[simgrid.git] / docs / source / The_XBT_toolbox.rst
1 .. _xbt:
2
3 The XBT toolbox
4 ###############
5
6 XBT is not an interface to describe your application, but rather a toolbox of features that are used everywhere in SimGrid. The code described in this page is not specific to any
7 of the existing interfaces, and it's used in all of them.
8
9 .. _logging_prog:
10
11 Logging API
12 ***********
13
14 As introduced in :ref:`outcome_logs`, the SimGrid logging mechanism allows to configure at runtime the messages that should be displayed and those that should be omitted. Each
15 message produced in the code is given a category (denoting its topic) and a priority. Then at runtime, each category is given a threshold (only messages of priority higher than
16 that threshold are displayed), a layout (deciding how the messages in this category are formatted), and an appender (deciding what to do with the message: either print on stderr or
17 to a file).
18
19 This section documents the provided API. To see how to configure these features at runtime, please refer to :ref:`logging_config`.
20
21 Declaring categories
22 ====================
23
24 Typically, there will be a category for each module of the implementation, so that users can independently control the logging for each module.
25 Refer to the :ref:`logging_categories` section for a list of all existing categories in SimGrid.
26
27 .. c:macro:: XBT_LOG_NEW_CATEGORY(category, description)
28
29    Creates a new category that is not within any existing categories. It will be located right below the ``root`` category.
30    ``category`` must be a valid identifier (such as ``mycat``) with no quote or anything. It should also be unique over the whole binary.
31    ``description`` must be a string, between quotes.
32
33 .. c:macro:: XBT_LOG_NEW_SUBCATEGORY(category, parent_category, description)
34
35    Creates a new category under the provided ``parent_category``.
36
37 .. c:macro:: XBT_LOG_NEW_DEFAULT_CATEGORY(category, description)
38
39    Similar to :c:macro:`XBT_LOG_NEW_CATEGORY`, and the created category is the default one in the current source file.
40
41 .. c:macro:: XBT_LOG_NEW_DEFAULT_SUBCATEGORY(category, parent_category, description)
42
43    Similar to :c:macro:`XBT_LOG_NEW_SUBCATEGORY`, and the created category is the default one in the current source file.
44
45 .. c:macro:: XBT_LOG_EXTERNAL_CATEGORY(category)
46
47    Make an external category (i.e., a category declared in another source file) visible from this source file. 
48    In each source file, at most one one category can be the default one.
49
50 .. c:macro:: XBT_LOG_EXTERNAL_DEFAULT_CATEGORY(category)
51
52    Use an external category as default category in this source file.
53
54 Logging messages
55 ================
56
57 Default category
58 ----------------
59
60 .. c:macro:: XBT_CRITICAL(format_string, parameters...)
61
62    Report a fatal error to the default category.
63
64 .. c:macro:: XBT_ERROR(format_string, parameters...)
65
66    Report an error to the default category.
67
68 .. c:macro:: XBT_WARN(format_string, parameters...)
69
70    Report a warning or an important information to the default category.
71
72 .. c:macro:: XBT_INFO(format_string, parameters...)
73
74    Report an information of regular importance to the default category.
75
76 .. c:macro:: XBT_VERB(format_string, parameters...)
77
78    Report a verbose information to the default category.
79
80 .. c:macro:: XBT_DEBUG(format_string, parameters...)
81
82    Report a debug-only information to the default category.
83
84 For each of the logging macros, the first parameter must be a printf-like format string, and the subsequent parameters must match this format. If you compile with the -Wall option,
85 the compiler will warn you for unmatched arguments, such as passing a pointer while the format string expects an integer. Using this option is usually a good idea.
86
87 Here is an example: ``XBT_WARN("Values are: %d and '%s'", 5, "oops");``
88
89 .. c:macro:: XBT_IN(format_string, parameters...)
90
91    Report that the execution flow enters a given function (which name is displayed automatically).
92
93 .. c:macro:: XBT_OUT(format_string, parameters...)
94
95    Report that the execution flow exits a given function (which name is displayed automatically).
96
97 .. c:macro:: XBT_HERE(format_string, parameters...)
98
99    Report that the execution flow reaches a given location.
100
101 Specific category
102 -----------------
103
104 .. c:macro:: XBT_CCRITICAL(category, format_string, parameters...)
105
106    Report a fatal error to the specified ``category``.
107
108 .. c:macro:: XBT_CERROR(category, format_string, parameters...)
109
110    Report an error to the specified ``category``.
111
112 .. c:macro:: XBT_CWARN(category, format_string, parameters...)
113
114    Report a warning or an important information to the specified ``category``.
115
116 .. c:macro:: XBT_CINFO(category, format_string, parameters...)
117
118    Report an information of regular importance to the specified ``category``.
119
120 .. c:macro:: XBT_CVERB(category, format_string, parameters...)
121
122    Report a verbose information to the specified ``category``.
123
124 .. c:macro:: XBT_CDEBUG(category, format_string, parameters...)
125
126    Report a debug-only information to the specified ``category``.
127
128 Of course, the specified category must be visible from this source file, either because it was created there (e.g. with :c:macro:`XBT_LOG_NEW_CATEGORY`) or because it was made
129 visible with :c:macro:`XBT_LOG_EXTERNAL_CATEGORY`.
130
131 Other functions
132 ===============
133
134 .. c:macro:: XBT_LOG_ISENABLED(category, priority)
135
136    Returns true if that category displays the messages of that priority. It's useful to compute a value that is used only in the logging, such as the textual representation of a
137    non-trivial object.
138
139    The specified priority must be one of ``xbt_log_priority_trace``, ``xbt_log_priority_debug``, ``xbt_log_priority_verbose``, ``xbt_log_priority_info``,
140    ``xbt_log_priority_warning``, ``xbt_log_priority_error`` or ``xbt_log_priority_critical``.
141
142 .. c:function:: void xbt_log_control_set(const char* setting)
143
144    Sets the provided ``setting`` as if it was passed in a ``--log`` command-line parameter.
145
146 You should not use any of the macros which name starts with '_'.
147
148 .. include:: ../build/log_categories.rst
149
150 Full example
151 ============
152
153 .. code-block:: C
154
155    #include "xbt/log.h"
156
157    /* create a category and a default subcategory */
158    XBT_LOG_NEW_CATEGORY(VSS);
159    XBT_LOG_NEW_DEFAULT_SUBCATEGORY(SA, VSS);
160
161    int main() {
162        /* Now set the parent's priority.  (the string would typically be a runtime option) */
163        xbt_log_control_set("SA.thresh:info");
164
165        /* This request is enabled, because WARNING >= INFO. */
166        XBT_CWARN(VSS, "Low fuel level.");
167
168        /* This request is disabled, because DEBUG < INFO. */
169        XBT_CDEBUG(VSS, "Starting search for nearest gas station.");
170
171        /* The default category SA inherits its priority from VSS. Thus,
172           the following request is enabled because INFO >= INFO.  */
173        XBT_INFO("Located nearest gas station.");
174
175        /* This request is disabled, because DEBUG < INFO. */
176        XBT_DEBUG("Exiting gas station search");
177    }
178
179 Performance concern
180 ===================
181
182 This module is highly optimized. Messages that will not be displayed are not even built. For example, using ``XBT_DEBUG`` in a category that turns debug messages off only costs a
183 single integer comparison at runtime, and the parameters are not even evaluated.
184
185 You can even specify a compile-time threshold that will completely remove every logging below the specified priority. Passing ``-DNDEBUG`` to cmake disables every logging of
186 priority below INFO while ``-DNLOG`` removes any logging at compile time. Note that using this feature may hinder the stability of SimGrid, as we consider the logs to be fast
187 enough to not thoughtfully test the case where they are removed at compile time.
188
189 Dynamic arrays
190 **************
191
192 As SimGrid used to be written in pure C, it used to rely on custom data containers such as dynamic arrays and dictionnaries. Nowadays, the standard library of
193 C++ is used internally, but some part of the interface still rely on the old containers, that are thus still available. 
194
195 .. warning:: 
196
197    You should probably not start a new project using these data structures,  as we will :ref:`deprecate them from SimGrid <deprecation_policy>` 
198    as soon as possible. Better implementations exist out there anyway, in particular if you're not writting pure C code.
199
200 .. doxygentypedef:: xbt_dynar_t
201 .. doxygentypedef:: const_xbt_dynar_t
202
203 Creation and destruction
204 ========================
205
206 .. doxygenfunction:: xbt_dynar_new
207 .. doxygenfunction:: xbt_dynar_free
208 .. doxygenfunction:: xbt_dynar_free_container
209 .. doxygenfunction:: xbt_dynar_shrink
210
211 Dynars as regular arrays
212 ========================
213    
214 .. doxygenfunction:: xbt_dynar_get_cpy
215 .. doxygenfunction:: xbt_dynar_insert_at
216 .. doxygenfunction:: xbt_dynar_remove_at
217 .. doxygenfunction:: xbt_dynar_member
218 .. doxygenfunction:: xbt_dynar_sort
219
220 Dynar size
221 ==========
222
223 .. doxygenfunction:: xbt_dynar_is_empty
224 .. doxygenfunction:: xbt_dynar_length
225 .. doxygenfunction:: xbt_dynar_reset
226    
227 Perl-like interface
228 ===================
229
230 .. doxygenfunction:: xbt_dynar_push
231 .. doxygenfunction:: xbt_dynar_pop
232 .. doxygenfunction:: xbt_dynar_unshift
233 .. doxygenfunction:: xbt_dynar_shift
234 .. doxygenfunction:: xbt_dynar_map
235
236 Direct content manipulation
237 ===========================
238
239 Those functions do not retrieve the content, but only their address.
240
241 .. doxygenfunction:: xbt_dynar_set_at_ptr
242 .. doxygenfunction:: xbt_dynar_get_ptr
243 .. doxygenfunction:: xbt_dynar_insert_at_ptr
244 .. doxygenfunction:: xbt_dynar_push_ptr
245 .. doxygenfunction:: xbt_dynar_pop_ptr
246
247 Dynars of scalars
248 =================
249
250 While the other functions use a memcpy to retrieve the content into the user provided area, those ones use a
251 regular affectation. It only works for scalar values, but should be a little faster.
252
253 .. doxygendefine:: xbt_dynar_get_as
254 .. doxygendefine:: xbt_dynar_set_as
255
256 .. doxygendefine:: xbt_dynar_getlast_as
257 .. doxygendefine:: xbt_dynar_getfirst_as
258 .. doxygendefine:: xbt_dynar_push_as
259 .. doxygendefine:: xbt_dynar_pop_as
260
261 Iterating over Dynars
262 =====================
263
264 .. doxygendefine:: xbt_dynar_foreach
265
266 Example with scalar values
267 ==========================
268
269 .. code-block:: c
270
271    xbt_dynar_t d = xbt_dynar_new(sizeof(int), nullptr);
272
273    /* 1. Populate the dynar */
274    xbt_dynar_t d = xbt_dynar_new(sizeof(int), nullptr);
275    for (int cpt = 0; cpt < NB_ELEM; cpt++) {
276      xbt_dynar_push_as(d, int, cpt);     /* This is faster (and possible only with scalars) */
277      /* xbt_dynar_push(d,&cpt);       This would also work */
278      xbt_test_log("Push %d, length=%lu", cpt, xbt_dynar_length(d));
279    }
280
281    /* 2. Traverse manually the dynar */
282    for (cursor = 0; cursor < NB_ELEM; cursor++) {
283      int* iptr = (int*)xbt_dynar_get_ptr(d, cursor);
284    /* 1. Populate further the dynar */
285    for (int cpt = 0; cpt < NB_ELEM; cpt++) {
286      xbt_dynar_insert_at(d, cpt, &cpt);
287      xbt_test_log("Push %d, length=%lu", cpt, xbt_dynar_length(d));
288    }
289
290    /* 3. Traverse the dynar */
291    int cpt;
292    xbt_dynar_foreach(d, cursor, cpt) {
293      xbt_test_assert(cursor == (unsigned int) cpt, "The retrieved value is not the same than the injected one (%u!=%d)", cursor, cpt);
294    }
295
296    /* 4. Reset the values */
297    for (int i = 0; i < NB_ELEM; i++)
298      *(int*)xbt_dynar_get_ptr(d, i) = i;
299
300    /* 5. Shift all the values */
301    for (int i = 0; i < NB_ELEM; i++) {
302       int val;
303       xbt_dynar_shift(d, &val);
304    }
305    // the dynar is empty after shifting all values
306
307    /* 5. Free the resources */
308    xbt_dynar_free(&d);
309
310 Example with pointed values
311 ===========================
312
313 .. code-block:: c
314
315    xbt_dynar_t d = xbt_dynar_new(sizeof(char*), &xbt_free_ref);
316
317    /// Push/shift example 
318    for (int i = 0; i < NB_ELEM; i++) {
319      char * val = xbt_strdup("hello");
320      xbt_dynar_push(d, &val);
321    }
322    for (int i = 0; i < NB_ELEM; i++) {
323      char *val;
324      xbt_dynar_shift(d, &val);
325      REQUIRE("hello" == val);
326      xbt_free(val);
327    }
328    xbt_dynar_free(&d);
329
330    /// Unshift, traverse and pop example
331    d = xbt_dynar_new(sizeof(char**), &xbt_free_ref);
332    for (int i = 0; i < NB_ELEM; i++) {
333      std::string val = std::to_string(i);
334      s1              = xbt_strdup(val.c_str());
335      xbt_dynar_unshift(d, &s1);
336    }
337    /* 2. Traverse the dynar with the macro */
338    xbt_dynar_foreach (d, iter, s1) {
339      std::string val = std::to_string(NB_ELEM - iter - 1);
340      REQUIRE(s1 == val); // The retrieved value is not the same than the injected one
341    }
342    /* 3. Traverse the dynar with the macro */
343    for (int i = 0; i < NB_ELEM; i++) {
344      std::string val = std::to_string(i);
345      xbt_dynar_pop(d, &s2);
346      REQUIRE(s2 == val); // The retrieved value is not the same than the injected one
347      xbt_free(s2);
348    }
349    /* 4. Free the resources */
350    xbt_dynar_free(&d);