1 /* dzl-macros.h
2  *
3  * Copyright (C) 2017 Christian Hergert <chergert@redhat.com>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifndef DZL_MACROS_H
20 #define DZL_MACROS_H
21 
22 #include <glib-object.h>
23 #include <string.h>
24 
25 #ifdef __linux__
26 # include <sys/types.h>
27 # include <sys/syscall.h>
28 # include <unistd.h>
29 #endif
30 
31 G_BEGIN_DECLS
32 
33 #if defined(_MSC_VER)
34 # define DZL_ALIGNED_BEGIN(_N) __declspec(align(_N))
35 # define DZL_ALIGNED_END(_N)
36 #else
37 # define DZL_ALIGNED_BEGIN(_N)
38 # define DZL_ALIGNED_END(_N) __attribute__((aligned(_N)))
39 #endif
40 
41 /* These were upstreamed into GLib, just use them */
42 #if GLIB_CHECK_VERSION(2,56,0)
43 # define dzl_clear_weak_pointer(ptr) g_clear_weak_pointer(ptr)
44 # define dzl_set_weak_pointer(ptr,obj) g_set_weak_pointer(ptr,obj)
45 #else
46 # define dzl_clear_weak_pointer(ptr) \
47   (*(ptr) ? (g_object_remove_weak_pointer((GObject*)*(ptr), (gpointer*)ptr),*(ptr)=NULL,1) : 0)
48 # define dzl_set_weak_pointer(ptr,obj) \
49   ((obj!=*(ptr))?(dzl_clear_weak_pointer(ptr),*(ptr)=obj,((obj)?g_object_add_weak_pointer((GObject*)obj,(gpointer*)ptr),NULL:NULL),1):0)
50 #endif
51 
52 /* A more type-correct form of g_clear_pointer(), to help find bugs.
53  * GLib ended up with a similar feature which we can rely on now.
54  */
55 #if GLIB_CHECK_VERSION(2,57,2)
56 # define dzl_clear_pointer g_clear_pointer
57 #else
58 # define dzl_clear_pointer(pptr, free_func)                   \
59   G_STMT_START {                                             \
60     G_STATIC_ASSERT (sizeof (*(pptr)) == sizeof (gpointer)); \
61     typeof(*(pptr)) _dzl_tmp_clear = *(pptr);                \
62     *(pptr) = NULL;                                          \
63     if (_dzl_tmp_clear)                                      \
64       free_func (_dzl_tmp_clear);                            \
65   } G_STMT_END
66 #endif
67 
68 /* strlen() gets hoisted out automatically at -O0 for everything but MSVC */
69 #define DZL_LITERAL_LENGTH(s) (strlen(s))
70 
71 static inline void
dzl_clear_signal_handler(gpointer object,gulong * location_of_handler)72 dzl_clear_signal_handler (gpointer  object,
73                           gulong   *location_of_handler)
74 {
75   if (*location_of_handler != 0)
76     {
77       gulong handler = *location_of_handler;
78       *location_of_handler = 0;
79       g_signal_handler_disconnect (object, handler);
80     }
81 }
82 
83 static inline gboolean
dzl_str_empty0(gconstpointer str)84 dzl_str_empty0 (gconstpointer str)
85 {
86   /* We use a gconstpointer to allow passing both
87    * signed and unsigned chars into this function */
88   return str == NULL || *(char*)str == '\0';
89 }
90 
91 static inline gboolean
dzl_str_equal0(gconstpointer str1,gconstpointer str2)92 dzl_str_equal0 (gconstpointer str1,
93                 gconstpointer str2)
94 {
95   /* We use gconstpointer so that we can allow
96    * both signed and unsigned chars here (such as xmlChar). */
97   return g_strcmp0 ((const gchar *)str1, (const gchar *)str2) == 0;
98 }
99 
100 static inline void
dzl_clear_source(guint * source_ptr)101 dzl_clear_source (guint *source_ptr)
102 {
103   guint source = *source_ptr;
104   *source_ptr = 0;
105   if (source != 0)
106     g_source_remove (source);
107 }
108 
109 static inline void
dzl_assert_is_main_thread(void)110 dzl_assert_is_main_thread (void)
111 {
112 #ifndef G_DISABLE_ASSERT
113 # ifdef __linux__
114   static GThread *main_thread;
115   GThread *self = g_thread_self ();
116 
117   if G_LIKELY (main_thread == self)
118     return;
119 
120   /* Slow path, rely on task id == process id */
121   if ((pid_t)syscall (SYS_gettid) == getpid ())
122     {
123       /* Allow for fast path next time */
124       main_thread = self;
125       return;
126     }
127 
128   g_assert_not_reached ();
129 # endif
130 #endif
131 }
132 
133 G_END_DECLS
134 
135 #endif /* DZL_MACROS_H */
136