Backport LTTNG_OPTIONAL util
authorJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 22 May 2020 22:04:31 +0000 (22:04 +0000)
committerJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Tue, 26 May 2020 18:29:52 +0000 (14:29 -0400)
A follow-up fix makes use of the LTTNG_OPTIONAL utility.

optional.h is identical to the version found in 3e778ab02.

Change-Id: I98a3efefe1ab6193e0d3c9c16d00f797551f36d9
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
src/common/Makefile.am
src/common/optional.h [new file with mode: 0644]

index 0feb0a0d1ad62ff8a88acc9fb63036270a9d7e4a..e3feaa38f5c639d58ed83070d1ad626410963f2f 100644 (file)
@@ -72,7 +72,8 @@ libcommon_la_SOURCES = error.h error.c utils.c utils.h runas.c runas.h \
                        dynamic-buffer.h dynamic-buffer.c \
                        buffer-view.h buffer-view.c \
                        unix.c unix.h \
-                       filter.c filter.h context.c context.h
+                       filter.c filter.h context.c context.h \
+                       optional.h
 
 libcommon_la_LIBADD = \
                $(top_builddir)/src/common/config/libconfig.la
diff --git a/src/common/optional.h b/src/common/optional.h
new file mode 100644 (file)
index 0000000..05f6054
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ *
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ */
+
+#ifndef LTTNG_OPTIONAL_H
+#define LTTNG_OPTIONAL_H
+
+#include <stdint.h>
+#include <assert.h>
+
+/*
+ * Define wrapper structure representing an optional value.
+ *
+ * This macro defines an "is_set" boolean field that must be checked
+ * when accessing the optional field. This "is_set" field provides
+ * the semantics that would be expected of a typical "raw pointer" field
+ * which would be checked for NULL.
+ *
+ * Prefer using this macro where "special" values would be used, e.g.
+ * -1ULL for uint64_t types.
+ *
+ * Declaration example:
+ * struct my_struct {
+ *     int a;
+ *     LTTNG_OPTIONAL(int, b);
+ * };
+ *
+ * Usage example:
+ * struct my_struct foo = LTTNG_OPTIONAL_INIT;
+ *
+ * LTTNG_OPTIONAL_SET(&foo.b, 42);
+ * if (foo.b.is_set) {
+ *     printf("%d", foo.b.value);
+ * }
+ *
+ * LTTNG_OPTIONAL_UNSET(&foo.b);
+ */
+#define LTTNG_OPTIONAL(type) \
+       struct {             \
+               uint8_t is_set; \
+               type value;  \
+       }
+
+/*
+ * Alias used for communication structures. If the layout of an LTTNG_OPTIONAL
+ * is changed, the original layout should still be used for communication
+ * purposes.
+ *
+ * LTTNG_OPTIONAL_COMM should be combined with the LTTNG_PACKED macro when
+ * used for IPC / network communication.
+ */
+#define LTTNG_OPTIONAL_COMM LTTNG_OPTIONAL
+
+/*
+ * This macro is available as a 'convenience' to allow sites that assume
+ * an optional value is set to assert() that it is set when accessing it.
+ *
+ * Since this returns the 'optional' by value, it is not suitable for all
+ * wrapped optional types. It is meant to be used with PODs.
+ */
+#define LTTNG_OPTIONAL_GET(optional)                   \
+        ({                                             \
+               assert((optional).is_set);              \
+               (optional).value;                       \
+       })
+
+/*
+ * Initialize an optional field.
+ *
+ * The wrapped field is set to the value it would gave if it had static storage
+ * duration.
+ */
+#define LTTNG_OPTIONAL_INIT { .is_set = 0 }
+
+/* Set the value of an optional field. */
+#define LTTNG_OPTIONAL_SET(field_ptr, val)     \
+       do {                                    \
+               (field_ptr)->value = (val);     \
+               (field_ptr)->is_set = 1;        \
+       } while (0)
+
+/* Put an optional field in the "unset" (NULL-ed) state. */
+#define LTTNG_OPTIONAL_UNSET(field_ptr)                \
+       do {                                    \
+               (field_ptr)->is_set = 0;        \
+       } while (0)
+
+#endif /* LTTNG_OPTIONAL_H */
This page took 0.027702 seconds and 5 git commands to generate.