1+ /*
2+ * Copyright 2023 The Nodepp Project Authors. All Rights Reserved.
3+ *
4+ * Licensed under the MIT (the "License"). You may not use
5+ * this file except in compliance with the License. You can obtain a copy
6+ * in the file LICENSE in the source distribution or at
7+ * https://github.com/NodeppOfficial/nodepp/blob/main/LICENSE
8+ */
9+
10+ /* ────────────────────────────────────────────────────────────────────────────*/
11+
12+ #ifndef NODEPP_POSIX_ATOMIC
13+ #define NODEPP_POSIX_ATOMIC
14+
15+ /* ────────────────────────────────────────────────────────────────────────────*/
16+
17+ #include < stdbool.h>
18+
19+ /* ────────────────────────────────────────────────────────────────────────────*/
20+
21+ namespace nodepp { namespace atomic {
22+
23+ template < class T > struct is_atomic : type::false_type{};
24+
25+ template <> struct is_atomic <int > : type::true_type {};
26+ template <> struct is_atomic <uint> : type::true_type {};
27+ template <> struct is_atomic <bool > : type::true_type {};
28+ template <> struct is_atomic <char > : type::true_type {};
29+ template <> struct is_atomic <long > : type::true_type {};
30+ template <> struct is_atomic <short > : type::true_type {};
31+ template <> struct is_atomic <uchar> : type::true_type {};
32+ template <> struct is_atomic <llong> : type::true_type {};
33+ template <> struct is_atomic <ulong> : type::true_type {};
34+ template <> struct is_atomic <ushort> : type::true_type {};
35+ template <> struct is_atomic <ullong> : type::true_type {};
36+
37+ // template<> struct is_atomic<float> : type::true_type {};
38+ // template<> struct is_atomic<double> : type::true_type {};
39+
40+ template <> struct is_atomic <wchar_t > : type::true_type {};
41+ template <> struct is_atomic <char16_t > : type::true_type {};
42+ template <> struct is_atomic <char32_t > : type::true_type {};
43+
44+ template < class T > struct is_atomic <T*> : type::true_type{};
45+
46+ }}
47+
48+ /* ────────────────────────────────────────────────────────────────────────────*/
49+
50+ namespace nodepp {
51+ template < class T , class = typename type::enable_if<atomic::is_atomic<T>::value,T>::type >
52+ class atomic_t { private: T value; protected:
53+
54+ void cpy ( const atomic_t & other ) noexcept {
55+ memcpy ( &value, &other.value , sizeof ( T ) );
56+ }
57+
58+ void mve ( atomic_t && other ) noexcept {
59+ memmove ( &value, &other.value , sizeof ( T ) );
60+ }
61+
62+ public:
63+
64+ atomic_t ( atomic_t && other ) noexcept { mve (type::move (other)); }
65+
66+ atomic_t ( const atomic_t & other ) noexcept { cpy (other); }
67+
68+ atomic_t ( T _val_ ) noexcept : value( _val_ ) {}
69+
70+ atomic_t () noexcept : value( T{} ) {}
71+
72+ public:
73+
74+ T get () const noexcept {
75+ return __atomic_load_n ( &value, __ATOMIC_ACQUIRE );
76+ }
77+
78+ void set ( T new_val ) noexcept {
79+ __atomic_store_n ( &value, new_val, __ATOMIC_RELEASE );
80+ }
81+
82+ /* ─······································································─*/
83+
84+ T _and ( T new_val ) noexcept {
85+ return __atomic_fetch_and ( &value, new_val, __ATOMIC_SEQ_CST );
86+ }
87+
88+ T _xor ( T new_val ) noexcept {
89+ return __atomic_fetch_xor ( &value, new_val, __ATOMIC_SEQ_CST );
90+ }
91+
92+ T _or ( T new_val ) noexcept {
93+ return __atomic_fetch_or ( &value, new_val, __ATOMIC_SEQ_CST );
94+ }
95+
96+ /* ─······································································─*/
97+
98+ T add ( T new_val ) noexcept {
99+ size_t scale = 1 ; if ( type::is_pointer<T>::value )
100+ { scale = sizeof ( typename type::remove_pointer<T>::type ); }
101+ return __atomic_fetch_add ( &value, new_val * scale, __ATOMIC_SEQ_CST );
102+ }
103+
104+ T sub ( T new_val ) noexcept {
105+ size_t scale = 1 ; if ( type::is_pointer<T>::value )
106+ { scale = sizeof ( typename type::remove_pointer<T>::type ); }
107+ return __atomic_fetch_sub ( &value, new_val * scale, __ATOMIC_SEQ_CST );
108+ }
109+
110+ /* ─······································································─*/
111+
112+ T swap ( T new_val ) noexcept {
113+ return __atomic_exchange_n ( &value, new_val, __ATOMIC_SEQ_CST );
114+ }
115+
116+ bool compare ( T& expected, T desired ) const noexcept {
117+ return __atomic_compare_exchange_n ( &value, &expected, desired, false , __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST );
118+ }
119+
120+ public:
121+
122+ template < typename U = T >
123+ typename type::enable_if< !type::is_pointer<U>::value, atomic_t & >::type
124+ operator &=( T value ) noexcept { _and (value); return *this ; }
125+
126+ template < typename U = T >
127+ typename type::enable_if< !type::is_pointer<U>::value, atomic_t & >::type
128+ operator |=( T value ) noexcept { _or (value); return *this ; }
129+
130+ template < typename U = T >
131+ typename type::enable_if< !type::is_pointer<U>::value, atomic_t & >::type
132+ operator ^=( T value ) noexcept { _xor (value); return *this ; }
133+
134+ template < typename U = T >
135+ typename type::enable_if< !type::is_pointer<U>::value, atomic_t & >::type
136+ operator -=( T value ) noexcept { sub (value); return *this ; }
137+
138+ template < typename U = T >
139+ typename type::enable_if< !type::is_pointer<U>::value, atomic_t & >::type
140+ operator +=( T value ) noexcept { add (value); return *this ; }
141+
142+ /* ─······································································─*/
143+
144+ template < typename U = T >
145+ typename type::enable_if< !type::is_pointer<U>::value, T >::type
146+ operator --() /* -------------*/ noexcept { return sub (1 ) - 1 ; }
147+
148+ template < typename U = T >
149+ typename type::enable_if< !type::is_pointer<U>::value, T >::type
150+ operator ++() /* -------------*/ noexcept { return add (1 ) + 1 ; }
151+
152+ template < typename U = T >
153+ typename type::enable_if< !type::is_pointer<U>::value, T >::type
154+ operator --(int ) /* ----------*/ noexcept { return sub (1 ); }
155+
156+ template < typename U = T >
157+ typename type::enable_if< !type::is_pointer<U>::value, T >::type
158+ operator ++(int ) /* ----------*/ noexcept { return add (1 ); }
159+
160+ /* ─······································································─*/
161+
162+ atomic_t & operator =( T value ) noexcept { set (value); return *this ; }
163+
164+ /* ─······································································─*/
165+
166+ bool operator ==( T value ) const noexcept { return get () == value; }
167+ bool operator >=( T value ) const noexcept { return get () >= value; }
168+ bool operator <=( T value ) const noexcept { return get () <= value; }
169+ bool operator > ( T value ) const noexcept { return get () > value; }
170+ bool operator < ( T value ) const noexcept { return get () < value; }
171+ bool operator !=( T value ) const noexcept { return get () != value; }
172+
173+ explicit operator T () /* */ const noexcept { return get (); }
174+
175+ }; }
176+
177+ /* ────────────────────────────────────────────────────────────────────────────*/
178+
179+ #endif
180+
181+ /* ────────────────────────────────────────────────────────────────────────────*/
0 commit comments