optional: Add LTTNG_OPTIONAL_INIT_VALUE
[lttng-tools.git] / src / common / optional.h
CommitLineData
2c5ff4e4 1/*
ab5be9fa 2 * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
2c5ff4e4 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
2c5ff4e4 5 *
2c5ff4e4
JG
6 */
7
8#ifndef LTTNG_OPTIONAL_H
9#define LTTNG_OPTIONAL_H
10
11#include <stdint.h>
12#include <assert.h>
13
14/*
15 * Define wrapper structure representing an optional value.
16 *
17 * This macro defines an "is_set" boolean field that must be checked
18 * when accessing the optional field. This "is_set" field provides
19 * the semantics that would be expected of a typical "raw pointer" field
20 * which would be checked for NULL.
21 *
22 * Prefer using this macro where "special" values would be used, e.g.
23 * -1ULL for uint64_t types.
24 *
2c5ff4e4
JG
25 * Declaration example:
26 * struct my_struct {
27 * int a;
28 * LTTNG_OPTIONAL(int, b);
29 * };
30 *
31 * Usage example:
32 * struct my_struct foo = LTTNG_OPTIONAL_INIT;
33 *
34 * LTTNG_OPTIONAL_SET(&foo.b, 42);
35 * if (foo.b.is_set) {
36 * printf("%d", foo.b.value);
37 * }
38 *
39 * LTTNG_OPTIONAL_UNSET(&foo.b);
40 */
41#define LTTNG_OPTIONAL(type) \
42 struct { \
43 uint8_t is_set; \
44 type value; \
45 }
46
0a30bf9b
JG
47/*
48 * Alias used for communication structures. If the layout of an LTTNG_OPTIONAL
49 * is changed, the original layout should still be used for communication
50 * purposes.
51 *
52 * LTTNG_OPTIONAL_COMM should be combined with the LTTNG_PACKED macro when
53 * used for IPC / network communication.
54 */
55#define LTTNG_OPTIONAL_COMM LTTNG_OPTIONAL
56
2c5ff4e4
JG
57/*
58 * This macro is available as a 'convenience' to allow sites that assume
59 * an optional value is set to assert() that it is set when accessing it.
60 *
61 * Since this returns the 'optional' by value, it is not suitable for all
62 * wrapped optional types. It is meant to be used with PODs.
63 */
64#define LTTNG_OPTIONAL_GET(optional) \
a321667a 65 ({ \
bc2dc8d4
MD
66 assert((optional).is_set); \
67 (optional).value; \
2c5ff4e4
JG
68 })
69
3da864a9
JR
70/*
71 * This macro is available as a 'convenience' to allow sites that assume
72 * an optional value is set to assert() that it is set when fecthing the
73 * underlying value's address.
74 */
75#define LTTNG_OPTIONAL_GET_PTR(optional) \
76 ({ \
77 assert((optional).is_set); \
78 &(optional).value; \
79 })
80
2c5ff4e4 81/*
5747e45a 82 * Initialize an optional field as unset.
2c5ff4e4
JG
83 *
84 * The wrapped field is set to the value it would gave if it had static storage
85 * duration.
86 */
5747e45a
JG
87#define LTTNG_OPTIONAL_INIT_UNSET { .is_set = 0 }
88
89/*
90 * Initialize an optional field as 'set' with a given value.
91 */
92#define LTTNG_OPTIONAL_INIT_VALUE(val) { .value = val, .is_set = 1 }
2c5ff4e4
JG
93
94/* Set the value of an optional field. */
bc2dc8d4
MD
95#define LTTNG_OPTIONAL_SET(field_ptr, val) \
96 do { \
97 (field_ptr)->value = (val); \
98 (field_ptr)->is_set = 1; \
99 } while (0)
2c5ff4e4
JG
100
101/* Put an optional field in the "unset" (NULL-ed) state. */
bc2dc8d4
MD
102#define LTTNG_OPTIONAL_UNSET(field_ptr) \
103 do { \
104 (field_ptr)->is_set = 0; \
105 } while (0)
2c5ff4e4
JG
106
107#endif /* LTTNG_OPTIONAL_H */
This page took 0.04723 seconds and 4 git commands to generate.