Ansel 0.0
A darktable fork - bloat + design vision
Loading...
Searching...
No Matches
atomic.h
Go to the documentation of this file.
1/*
2 This file is part of darktable,
3 Copyright (C) 2020 darktable developers.
4
5 darktable 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 darktable 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 darktable. If not, see <http://www.gnu.org/licenses/>.
17*/
18
19#pragma once
20
21// implement an atomic variable for inter-thread signalling purposes
22// the manner in which we implement depends on the capabilities of the compiler:
23// 1. standard-compliant C++ compiler: use C++11 atomics in <atomic>
24// 2. standard-compliant C compiler: use C11 atomics in <stdatomic.h>
25// 3. GCC 4.8+: use intrinsics
26// 4. otherwise: fall back to using Posix mutex to serialize access
27
28#if defined(__cplusplus) && __cplusplus > 201100
29#include <atomic>
30
31typedef std::atomic<int> dt_atomic_int;
32inline void dt_atomic_set_int(dt_atomic_int *var, int value) { std::atomic_store(var,value); }
33inline int dt_atomic_get_int(dt_atomic_int *var) { return std::atomic_load(var); }
34inline int dt_atomic_add_int(dt_atomic_int *var, int incr) { return std::atomic_fetch_add(var,incr); }
35inline int dt_atomic_sub_int(dt_atomic_int *var, int decr) { return std::atomic_fetch_sub(var,decr); }
36inline int dt_atomic_exch_int(dt_atomic_int *var, int value) { return std::atomic_exchange(var,value); }
37inline int dt_atomic_CAS_int(dt_atomic_int *var, int *expected, int value)
38{ return std::atomic_compare_exchange_strong(var,expected,value); }
39
40#elif !defined(__STDC_NO_ATOMICS__)
41
42#include <stdatomic.h>
43
44typedef atomic_int dt_atomic_int;
45inline void dt_atomic_set_int(dt_atomic_int *var, int value) { atomic_store(var,value); }
46inline int dt_atomic_get_int(dt_atomic_int *var) { return atomic_load(var); }
47inline int dt_atomic_add_int(dt_atomic_int *var, int incr) { return atomic_fetch_add(var,incr); }
48inline int dt_atomic_sub_int(dt_atomic_int *var, int decr) { return atomic_fetch_sub(var,decr); }
49inline int dt_atomic_exch_int(dt_atomic_int *var, int value) { return atomic_exchange(var,value); }
50inline int dt_atomic_CAS_int(dt_atomic_int *var, int *expected, int value)
51{ return atomic_compare_exchange_strong(var,expected,value); }
52
53#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNU_MINOR__ >= 8))
54// we don't have or aren't supposed to use C11 atomics, but the compiler is a recent-enough version of GCC
55// that we can use GNU intrinsics corresponding to the C11 atomics
56
57typedef volatile int dt_atomic_int;
58inline void dt_atomic_set_int(dt_atomic_int *var, int value) { __atomic_store(var,&value,__ATOMIC_SEQ_CST); }
59inline int dt_atomic_get_int(dt_atomic_int *var)
60{ int value ; __atomic_load(var,&value,__ATOMIC_SEQ_CST); return value; }
61
62inline int dt_atomic_add_int(dt_atomic_int *var, int incr) { return __atomic_fetch_add(var,incr,__ATOMIC_SEQ_CST); }
63inline int dt_atomic_sub_int(dt_atomic_int *var, int decr) { return __atomic_fetch_sub(var,decr,__ATOMIC_SEQ_CST); }
64inline int dt_atomic_exch_int(dt_atomic_int *var, int value)
65{ int orig; __atomic_exchange(var,&value,&orig,__ATOMIC_SEQ_CST); return orig; }
66inline int dt_atomic_CAS_int(dt_atomic_int *var, int *expected, int value)
67{ return __atomic_compare_exchange(var,expected,&value,0,__ATOMIC_SEQ_CST,__ATOMIC_SEQ_CST); }
68
69#else
70// we don't have or aren't supposed to use C11 atomics, and don't have GNU intrinsics, so
71// fall back to using a mutex for synchronization
72#include <pthread.h>
73
74extern pthread_mutex_t dt_atom_mutex;
75
76typedef int dt_atomic_int;
77inline void dt_atomic_set_int(dt_atomic_int *var, int value)
78{
79 pthread_mutex_lock(&dt_atom_mutex);
80 *var = value;
81 pthread_mutex_unlock(&dt_atom_mutex);
82}
83
84inline int dt_atomic_get_int(const dt_atomic_int *const var)
85{
86 pthread_mutex_lock(&dt_atom_mutex);
87 int value = *var;
88 pthread_mutex_unlock(&dt_atom_mutex);
89 return value;
90}
91
92inline int dt_atomic_add_int(const dt_atomic_int *const var, int incr)
93{
94 pthread_mutex_lock(&dt_atom_mutex);
95 int value = *var;
96 *var += incr;
97 pthread_mutex_unlock(&dt_atom_mutex);
98 return value;
99}
100
101inline int dt_atomic_sub_int(const dt_atomic_int *const var, int decr)
102{
103 pthread_mutex_lock(&dt_atom_mutex);
104 int value = *var;
105 *var -= decr;
106 pthread_mutex_unlock(&dt_atom_mutex);
107 return value;
108}
109
110inline int dt_atomic_exch_int(dt_atomic_int *var, int value)
111{
112 pthread_mutex_lock(&dt_atom_mutex);
113 int origvalue = *var;
114 *var = value;
115 pthread_mutex_unlock(&dt_atom_mutex);
116 return origvalue;
117}
118
119inline int dt_atomic_CAS_int(dt_atomic_int *var, int *expected, int value)
120{
121 pthread_mutex_lock(&dt_atom_mutex);
122 int origvalue = *var;
123 int success = FALSE;
124 if (origvalue == *expected)
125 {
126 *var = value;
127 success = TRUE;
128 }
129 *expected = origvalue;
130 pthread_mutex_unlock(&dt_atom_mutex);
131 return success;
132}
133
134#endif // __STDC_NO_ATOMICS__
135
136// clang-format off
137// modelines: These editor modelines have been set for all relevant files by tools/update_modelines.py
138// vim: shiftwidth=2 expandtab tabstop=2 cindent
139// kate: tab-indents: off; indent-width 2; replace-tabs on; indent-mode cstyle; remove-trailing-spaces modified;
140// clang-format on
141
#define TRUE
Definition ashift_lsd.c:151
#define FALSE
Definition ashift_lsd.c:147
void dt_atomic_set_int(dt_atomic_int *var, int value)
Definition atomic.h:45
int dt_atomic_get_int(dt_atomic_int *var)
Definition atomic.h:46
atomic_int dt_atomic_int
Definition atomic.h:44
int dt_atomic_sub_int(dt_atomic_int *var, int decr)
Definition atomic.h:48
int dt_atomic_add_int(dt_atomic_int *var, int incr)
Definition atomic.h:47
int dt_atomic_CAS_int(dt_atomic_int *var, int *expected, int value)
Definition atomic.h:50
int dt_atomic_exch_int(dt_atomic_int *var, int value)
Definition atomic.h:49