PyPcre 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pypcre-0.2.2/MANIFEST.in +1 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/PKG-INFO +2 -2
- {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/PKG-INFO +2 -2
- {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/SOURCES.txt +5 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/top_level.txt +1 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/README.md +1 -1
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre/pcre.py +11 -10
- pypcre-0.2.2/pcre_ext/atomic_compat.h +365 -0
- pypcre-0.2.2/pcre_ext/pcre2.h +1069 -0
- pypcre-0.2.2/pcre_ext/pcre2_module.h +124 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pyproject.toml +2 -1
- pypcre-0.2.2/setup_utils.py +1111 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/LICENSE +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/dependency_links.txt +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre/__init__.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre/cache.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre/error.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre/flags.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre/re_compat.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre/threads.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/cache.c +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/error.c +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/flag.c +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/memory.c +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/pcre2.c +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/util.c +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/setup.cfg +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/setup.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_accuracy.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_api_parity.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_basic.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_bench_string.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_benchmark.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_bytes.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_cache.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_clobber.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_clobber_thread.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_core.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_errors.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_flags.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_jit.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_memory.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_module.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_pattern.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_simd.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_threaded_backend.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_transformers_regex.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_utf8.py +0 -0
- {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_version.py +0 -0
pypcre-0.2.2/MANIFEST.in
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include pcre_ext/*.h
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPcre
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Modern, GIL-friendly, Fast Python bindings for PCRE2 with auto caching and JIT of compiled patterns.
|
|
5
5
|
Author-email: ModelCloud <qubitium@modelcloud.ai>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -43,7 +43,7 @@ Python bindings for the system PCRE2 library with a familiar `re`-style API.
|
|
|
43
43
|
</p>
|
|
44
44
|
|
|
45
45
|
## Latest News
|
|
46
|
-
* 10/11/2025 [0.2.
|
|
46
|
+
* 10/11/2025 [0.2.1](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.1): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
|
|
47
47
|
* 10/09/2025 [0.1.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.1.0): 🎉 First release. Thread safe, auto JIT, auto pattern caching and optimistic linking to system library for fast install.
|
|
48
48
|
|
|
49
49
|
## Why PyPcre:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: PyPcre
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Modern, GIL-friendly, Fast Python bindings for PCRE2 with auto caching and JIT of compiled patterns.
|
|
5
5
|
Author-email: ModelCloud <qubitium@modelcloud.ai>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -43,7 +43,7 @@ Python bindings for the system PCRE2 library with a familiar `re`-style API.
|
|
|
43
43
|
</p>
|
|
44
44
|
|
|
45
45
|
## Latest News
|
|
46
|
-
* 10/11/2025 [0.2.
|
|
46
|
+
* 10/11/2025 [0.2.1](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.1): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
|
|
47
47
|
* 10/09/2025 [0.1.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.1.0): 🎉 First release. Thread safe, auto JIT, auto pattern caching and optimistic linking to system library for fast install.
|
|
48
48
|
|
|
49
49
|
## Why PyPcre:
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
2
3
|
README.md
|
|
3
4
|
pyproject.toml
|
|
4
5
|
setup.py
|
|
6
|
+
setup_utils.py
|
|
5
7
|
PyPcre.egg-info/PKG-INFO
|
|
6
8
|
PyPcre.egg-info/SOURCES.txt
|
|
7
9
|
PyPcre.egg-info/dependency_links.txt
|
|
@@ -13,11 +15,14 @@ pcre/flags.py
|
|
|
13
15
|
pcre/pcre.py
|
|
14
16
|
pcre/re_compat.py
|
|
15
17
|
pcre/threads.py
|
|
18
|
+
pcre_ext/atomic_compat.h
|
|
16
19
|
pcre_ext/cache.c
|
|
17
20
|
pcre_ext/error.c
|
|
18
21
|
pcre_ext/flag.c
|
|
19
22
|
pcre_ext/memory.c
|
|
20
23
|
pcre_ext/pcre2.c
|
|
24
|
+
pcre_ext/pcre2.h
|
|
25
|
+
pcre_ext/pcre2_module.h
|
|
21
26
|
pcre_ext/util.c
|
|
22
27
|
tests/test_accuracy.py
|
|
23
28
|
tests/test_api_parity.py
|
|
@@ -18,7 +18,7 @@ Python bindings for the system PCRE2 library with a familiar `re`-style API.
|
|
|
18
18
|
</p>
|
|
19
19
|
|
|
20
20
|
## Latest News
|
|
21
|
-
* 10/11/2025 [0.2.
|
|
21
|
+
* 10/11/2025 [0.2.1](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.1): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
|
|
22
22
|
* 10/09/2025 [0.1.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.1.0): 🎉 First release. Thread safe, auto JIT, auto pattern caching and optimistic linking to system library for fast install.
|
|
23
23
|
|
|
24
24
|
## Why PyPcre:
|
|
@@ -16,16 +16,17 @@ import pcre_ext_c as _pcre2
|
|
|
16
16
|
|
|
17
17
|
from .cache import cached_compile
|
|
18
18
|
from .cache import clear_cache as _clear_cache
|
|
19
|
-
from .flags import
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
19
|
+
from .flags import Flag, strip_py_only_flags
|
|
20
|
+
|
|
21
|
+
# Cache frequently used flag values as plain integers to avoid the overhead of
|
|
22
|
+
# IntFlag arithmetic in hot paths such as module-level search helpers.
|
|
23
|
+
COMPAT_UNICODE_ESCAPE: int = int(Flag.COMPAT_UNICODE_ESCAPE)
|
|
24
|
+
THREADS: int = int(Flag.THREADS)
|
|
25
|
+
NO_THREADS: int = int(Flag.NO_THREADS)
|
|
26
|
+
JIT: int = int(Flag.JIT)
|
|
27
|
+
NO_JIT: int = int(Flag.NO_JIT)
|
|
28
|
+
NO_UTF: int = int(Flag.NO_UTF)
|
|
29
|
+
NO_UCP: int = int(Flag.NO_UCP)
|
|
29
30
|
from .re_compat import (
|
|
30
31
|
Match,
|
|
31
32
|
TemplatePatternStub,
|
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
// SPDX-FileCopyrightText: 2025 ModelCloud.ai
|
|
2
|
+
// SPDX-FileCopyrightText: 2025 qubitium@modelcloud.ai
|
|
3
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
// Contact: qubitium@modelcloud.ai, x.com/qubitium
|
|
5
|
+
|
|
6
|
+
#ifndef ATOMIC_COMPAT_H
|
|
7
|
+
#define ATOMIC_COMPAT_H
|
|
8
|
+
|
|
9
|
+
#include <stddef.h>
|
|
10
|
+
#include <stdint.h>
|
|
11
|
+
|
|
12
|
+
#ifdef __cplusplus
|
|
13
|
+
extern "C" {
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
/* ===================================================================== */
|
|
17
|
+
/* MSVC IMPLEMENTATION */
|
|
18
|
+
/* ===================================================================== */
|
|
19
|
+
#if defined(_MSC_VER)
|
|
20
|
+
|
|
21
|
+
#if defined(__has_include)
|
|
22
|
+
# if !defined(__STDC_NO_ATOMICS__) && __has_include(<stdatomic.h>)
|
|
23
|
+
# include <stdatomic.h>
|
|
24
|
+
# define ATOMIC_COMPAT_USE_NATIVE_ATOMICS 1
|
|
25
|
+
# endif
|
|
26
|
+
#endif
|
|
27
|
+
|
|
28
|
+
#if defined(ATOMIC_COMPAT_USE_NATIVE_ATOMICS)
|
|
29
|
+
|
|
30
|
+
#define ATOMIC_COMPAT_HAVE_ATOMICS 1
|
|
31
|
+
#define ATOMIC_VAR(type) _Atomic(type)
|
|
32
|
+
#ifndef ATOMIC_VAR_INIT
|
|
33
|
+
# define ATOMIC_VAR_INIT(value) (value)
|
|
34
|
+
#endif
|
|
35
|
+
|
|
36
|
+
#else /* !ATOMIC_COMPAT_USE_NATIVE_ATOMICS */
|
|
37
|
+
|
|
38
|
+
#include <windows.h>
|
|
39
|
+
#include <intrin.h>
|
|
40
|
+
|
|
41
|
+
/* Feature flag & storage qualifier (GNU-style on MSVC). */
|
|
42
|
+
#define ATOMIC_COMPAT_HAVE_ATOMICS 1
|
|
43
|
+
#define ATOMIC_VAR(type) volatile type
|
|
44
|
+
#ifndef ATOMIC_VAR_INIT
|
|
45
|
+
# define ATOMIC_VAR_INIT(value) (value)
|
|
46
|
+
#endif
|
|
47
|
+
|
|
48
|
+
/* --------------------------------------------------------------------- */
|
|
49
|
+
/* 1) Nuke vcruntime <stdatomic.h> macros if they were included already. */
|
|
50
|
+
/* This prevents expansions to __c11_atomic_* builtins on MSVC. */
|
|
51
|
+
/* --------------------------------------------------------------------- */
|
|
52
|
+
|
|
53
|
+
#if defined(atomic_init)
|
|
54
|
+
# undef atomic_init
|
|
55
|
+
#endif
|
|
56
|
+
|
|
57
|
+
#if defined(atomic_thread_fence)
|
|
58
|
+
# undef atomic_thread_fence
|
|
59
|
+
#endif
|
|
60
|
+
#if defined(atomic_signal_fence)
|
|
61
|
+
# undef atomic_signal_fence
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
#if defined(atomic_load)
|
|
65
|
+
# undef atomic_load
|
|
66
|
+
#endif
|
|
67
|
+
#if defined(atomic_load_explicit)
|
|
68
|
+
# undef atomic_load_explicit
|
|
69
|
+
#endif
|
|
70
|
+
|
|
71
|
+
#if defined(atomic_store)
|
|
72
|
+
# undef atomic_store
|
|
73
|
+
#endif
|
|
74
|
+
#if defined(atomic_store_explicit)
|
|
75
|
+
# undef atomic_store_explicit
|
|
76
|
+
#endif
|
|
77
|
+
|
|
78
|
+
#if defined(atomic_exchange)
|
|
79
|
+
# undef atomic_exchange
|
|
80
|
+
#endif
|
|
81
|
+
#if defined(atomic_exchange_explicit)
|
|
82
|
+
# undef atomic_exchange_explicit
|
|
83
|
+
#endif
|
|
84
|
+
|
|
85
|
+
#if defined(atomic_fetch_add)
|
|
86
|
+
# undef atomic_fetch_add
|
|
87
|
+
#endif
|
|
88
|
+
#if defined(atomic_fetch_add_explicit)
|
|
89
|
+
# undef atomic_fetch_add_explicit
|
|
90
|
+
#endif
|
|
91
|
+
|
|
92
|
+
#if defined(atomic_fetch_sub)
|
|
93
|
+
# undef atomic_fetch_sub
|
|
94
|
+
#endif
|
|
95
|
+
#if defined(atomic_fetch_sub_explicit)
|
|
96
|
+
# undef atomic_fetch_sub_explicit
|
|
97
|
+
#endif
|
|
98
|
+
|
|
99
|
+
#if defined(atomic_compare_exchange_strong)
|
|
100
|
+
# undef atomic_compare_exchange_strong
|
|
101
|
+
#endif
|
|
102
|
+
#if defined(atomic_compare_exchange_strong_explicit)
|
|
103
|
+
# undef atomic_compare_exchange_strong_explicit
|
|
104
|
+
#endif
|
|
105
|
+
#if defined(atomic_compare_exchange_weak)
|
|
106
|
+
# undef atomic_compare_exchange_weak
|
|
107
|
+
#endif
|
|
108
|
+
#if defined(atomic_compare_exchange_weak_explicit)
|
|
109
|
+
# undef atomic_compare_exchange_weak_explicit
|
|
110
|
+
#endif
|
|
111
|
+
|
|
112
|
+
#if defined(atomic_flag_test_and_set)
|
|
113
|
+
# undef atomic_flag_test_and_set
|
|
114
|
+
#endif
|
|
115
|
+
#if defined(atomic_flag_test_and_set_explicit)
|
|
116
|
+
# undef atomic_flag_test_and_set_explicit
|
|
117
|
+
#endif
|
|
118
|
+
#if defined(atomic_flag_clear)
|
|
119
|
+
# undef atomic_flag_clear
|
|
120
|
+
#endif
|
|
121
|
+
#if defined(atomic_flag_clear_explicit)
|
|
122
|
+
# undef atomic_flag_clear_explicit
|
|
123
|
+
#endif
|
|
124
|
+
|
|
125
|
+
/* --------------------------------------------------------------------- */
|
|
126
|
+
/* 2) C11 memory orders (accepted, enforced >= seq_cst where relevant). */
|
|
127
|
+
/* --------------------------------------------------------------------- */
|
|
128
|
+
typedef enum {
|
|
129
|
+
memory_order_relaxed = 0,
|
|
130
|
+
memory_order_consume = 1, /* treat as acquire */
|
|
131
|
+
memory_order_acquire = 2,
|
|
132
|
+
memory_order_release = 3,
|
|
133
|
+
memory_order_acq_rel = 4,
|
|
134
|
+
memory_order_seq_cst = 5
|
|
135
|
+
} memory_order;
|
|
136
|
+
|
|
137
|
+
static __forceinline void atomic_thread_fence(memory_order order) {
|
|
138
|
+
(void)order;
|
|
139
|
+
/* Full fence (at-least seq_cst). */
|
|
140
|
+
MemoryBarrier();
|
|
141
|
+
}
|
|
142
|
+
static __forceinline void atomic_signal_fence(memory_order order) {
|
|
143
|
+
(void)order;
|
|
144
|
+
/* Compiler barrier only. */
|
|
145
|
+
_ReadWriteBarrier();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/* --------------------------------------------------------------------- */
|
|
149
|
+
/* 3) Low-level typed helpers backed by Interlocked primitives. */
|
|
150
|
+
/* (All provide at-least seq_cst.) */
|
|
151
|
+
/* --------------------------------------------------------------------- */
|
|
152
|
+
|
|
153
|
+
/* 32-bit */
|
|
154
|
+
static __forceinline int32_t ac_load_i32 (volatile int32_t *p) { return (int32_t)InterlockedCompareExchange((volatile LONG*)p, 0, 0); }
|
|
155
|
+
static __forceinline uint32_t ac_load_u32 (volatile uint32_t *p) { return (uint32_t)InterlockedCompareExchange((volatile LONG*)p, 0, 0); }
|
|
156
|
+
static __forceinline void ac_store_i32(volatile int32_t *p, int32_t v) { InterlockedExchange((volatile LONG*)p, (LONG)v); }
|
|
157
|
+
static __forceinline void ac_store_u32(volatile uint32_t *p, uint32_t v) { InterlockedExchange((volatile LONG*)p, (LONG)v); }
|
|
158
|
+
static __forceinline int32_t ac_xchg_i32 (volatile int32_t *p, int32_t v) { return (int32_t)InterlockedExchange((volatile LONG*)p, (LONG)v); }
|
|
159
|
+
static __forceinline uint32_t ac_xchg_u32 (volatile uint32_t *p, uint32_t v) { return (uint32_t)InterlockedExchange((volatile LONG*)p, (LONG)v); }
|
|
160
|
+
static __forceinline int32_t ac_fadd_i32 (volatile int32_t *p, int32_t v) { return (int32_t)InterlockedExchangeAdd((volatile LONG*)p, (LONG)v); }
|
|
161
|
+
static __forceinline uint32_t ac_fadd_u32 (volatile uint32_t *p, uint32_t v) { return (uint32_t)InterlockedExchangeAdd((volatile LONG*)p, (LONG)v); }
|
|
162
|
+
static __forceinline int ac_cas_i32 (volatile int32_t *p, int32_t *e, int32_t d) {
|
|
163
|
+
LONG orig = InterlockedCompareExchange((volatile LONG*)p, (LONG)d, (LONG)*e);
|
|
164
|
+
if ((int32_t)orig == *e) return 1;
|
|
165
|
+
*e = (int32_t)orig; return 0;
|
|
166
|
+
}
|
|
167
|
+
static __forceinline int ac_cas_u32 (volatile uint32_t *p, uint32_t *e, uint32_t d) {
|
|
168
|
+
LONG orig = InterlockedCompareExchange((volatile LONG*)p, (LONG)d, (LONG)*e);
|
|
169
|
+
if ((uint32_t)orig == *e) return 1;
|
|
170
|
+
*e = (uint32_t)orig; return 0;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/* 64-bit */
|
|
174
|
+
static __forceinline int64_t ac_load_i64 (volatile int64_t *p) { return (int64_t)InterlockedCompareExchange64((volatile LONGLONG*)p, 0, 0); }
|
|
175
|
+
static __forceinline uint64_t ac_load_u64 (volatile uint64_t *p) { return (uint64_t)InterlockedCompareExchange64((volatile LONGLONG*)p, 0, 0); }
|
|
176
|
+
static __forceinline void ac_store_i64(volatile int64_t *p, int64_t v) { InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
|
|
177
|
+
static __forceinline void ac_store_u64(volatile uint64_t *p, uint64_t v) { InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
|
|
178
|
+
static __forceinline int64_t ac_xchg_i64 (volatile int64_t *p, int64_t v) { return (int64_t)InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
|
|
179
|
+
static __forceinline uint64_t ac_xchg_u64 (volatile uint64_t *p, uint64_t v) { return (uint64_t)InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
|
|
180
|
+
static __forceinline int64_t ac_fadd_i64 (volatile int64_t *p, int64_t v) { return (int64_t)InterlockedExchangeAdd64((volatile LONGLONG*)p, (LONGLONG)v); }
|
|
181
|
+
static __forceinline uint64_t ac_fadd_u64 (volatile uint64_t *p, uint64_t v) { return (uint64_t)InterlockedExchangeAdd64((volatile LONGLONG*)p, (LONGLONG)v); }
|
|
182
|
+
static __forceinline int ac_cas_i64 (volatile int64_t *p, int64_t *e, int64_t d) {
|
|
183
|
+
LONGLONG orig = InterlockedCompareExchange64((volatile LONGLONG*)p, (LONGLONG)d, (LONGLONG)*e);
|
|
184
|
+
if ((int64_t)orig == *e) return 1;
|
|
185
|
+
*e = (int64_t)orig; return 0;
|
|
186
|
+
}
|
|
187
|
+
static __forceinline int ac_cas_u64 (volatile uint64_t *p, uint64_t *e, uint64_t d) {
|
|
188
|
+
LONGLONG orig = InterlockedCompareExchange64((volatile LONGLONG*)p, (LONGLONG)d, (LONGLONG)*e);
|
|
189
|
+
if ((uint64_t)orig == *e) return 1;
|
|
190
|
+
*e = (uint64_t)orig; return 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/* size_t */
|
|
194
|
+
static __forceinline size_t ac_load_size (volatile size_t *p) {
|
|
195
|
+
#if defined(_WIN64)
|
|
196
|
+
return (size_t)InterlockedCompareExchange64((volatile LONGLONG*)p, 0, 0);
|
|
197
|
+
#else
|
|
198
|
+
return (size_t)InterlockedCompareExchange((volatile LONG*)p, 0, 0);
|
|
199
|
+
#endif
|
|
200
|
+
}
|
|
201
|
+
static __forceinline void ac_store_size(volatile size_t *p, size_t v) {
|
|
202
|
+
#if defined(_WIN64)
|
|
203
|
+
InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v);
|
|
204
|
+
#else
|
|
205
|
+
InterlockedExchange((volatile LONG*)p, (LONG)v);
|
|
206
|
+
#endif
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/* pointers */
|
|
210
|
+
static __forceinline void *ac_load_ptr (void * volatile *p) { return InterlockedCompareExchangePointer(p, NULL, NULL); }
|
|
211
|
+
static __forceinline void ac_store_ptr(void * volatile *p, void *v) { InterlockedExchangePointer(p, v); }
|
|
212
|
+
static __forceinline void *ac_xchg_ptr (void * volatile *p, void *v) { return InterlockedExchangePointer(p, v); }
|
|
213
|
+
static __forceinline int ac_cas_ptr (void * volatile *p, void **e, void *d) {
|
|
214
|
+
void *orig = InterlockedCompareExchangePointer(p, d, *e);
|
|
215
|
+
if (orig == *e) return 1;
|
|
216
|
+
*e = orig; return 0;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* --------------------------------------------------------------------- */
|
|
220
|
+
/* 4) GNU-style, type-directed macros via _Generic (C mode on MSVC 2022).*/
|
|
221
|
+
/* These work on *plain* volatile T* (no _Atomic required). */
|
|
222
|
+
/* --------------------------------------------------------------------- */
|
|
223
|
+
|
|
224
|
+
/* Load */
|
|
225
|
+
#define atomic_compat_load(ptr) \
|
|
226
|
+
_Generic((ptr), \
|
|
227
|
+
/* signed */ volatile int32_t *: ac_load_i32((volatile int32_t*)(ptr)), \
|
|
228
|
+
int32_t *: ac_load_i32((volatile int32_t*)(ptr)), \
|
|
229
|
+
/* unsigned */ volatile uint32_t *: ac_load_u32((volatile uint32_t*)(ptr)), \
|
|
230
|
+
uint32_t *: ac_load_u32((volatile uint32_t*)(ptr)), \
|
|
231
|
+
/* size_t */ volatile size_t *: ac_load_size((volatile size_t*)(ptr)), \
|
|
232
|
+
size_t *: ac_load_size((volatile size_t*)(ptr)), \
|
|
233
|
+
/* pointer */ default: ac_load_ptr((void * volatile *)(ptr)) \
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
/* Store */
|
|
237
|
+
#define atomic_compat_store(ptr, value) \
|
|
238
|
+
_Generic((ptr), \
|
|
239
|
+
/* signed */ volatile int32_t *: ac_store_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
|
|
240
|
+
int32_t *: ac_store_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
|
|
241
|
+
/* unsigned */ volatile uint32_t *: ac_store_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
|
|
242
|
+
uint32_t *: ac_store_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
|
|
243
|
+
/* size_t */ volatile size_t *: ac_store_size((volatile size_t*)(ptr), (size_t)(value)), \
|
|
244
|
+
size_t *: ac_store_size((volatile size_t*)(ptr), (size_t)(value)), \
|
|
245
|
+
/* pointer */ default: ac_store_ptr((void * volatile *)(ptr), (void*)(value)) \
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
/* Exchange */
|
|
249
|
+
#define atomic_compat_exchange(ptr, value) \
|
|
250
|
+
_Generic((ptr), \
|
|
251
|
+
/* signed */ volatile int32_t *: (int32_t) ac_xchg_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
|
|
252
|
+
int32_t *: (int32_t) ac_xchg_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
|
|
253
|
+
/* unsigned */ volatile uint32_t *: (uint32_t)ac_xchg_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
|
|
254
|
+
uint32_t *: (uint32_t)ac_xchg_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
|
|
255
|
+
/* pointer */ default: ac_xchg_ptr((void * volatile *)(ptr), (void*)(value)) \
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
/* Fetch add / sub (integers only) */
|
|
259
|
+
#define atomic_compat_fetch_add(ptr, value) \
|
|
260
|
+
_Generic((ptr), \
|
|
261
|
+
volatile int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
|
|
262
|
+
int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
|
|
263
|
+
volatile uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
|
|
264
|
+
uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)(value)) \
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
#define atomic_compat_fetch_sub(ptr, value) \
|
|
268
|
+
_Generic((ptr), \
|
|
269
|
+
volatile int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)-(value)), \
|
|
270
|
+
int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)-(value)), \
|
|
271
|
+
volatile uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)-(value)), \
|
|
272
|
+
uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)-(value)) \
|
|
273
|
+
)
|
|
274
|
+
|
|
275
|
+
/* Compare-exchange (C11 rules: update *expected on failure) */
|
|
276
|
+
#define atomic_compat_compare_exchange(ptr, expected, desired) \
|
|
277
|
+
_Generic((ptr), \
|
|
278
|
+
volatile int32_t *: ac_cas_i32((volatile int32_t*)(ptr), (int32_t*)(expected), (int32_t)(desired)), \
|
|
279
|
+
int32_t *: ac_cas_i32((volatile int32_t*)(ptr), (int32_t*)(expected), (int32_t)(desired)), \
|
|
280
|
+
volatile uint32_t *: ac_cas_u32((volatile uint32_t*)(ptr), (uint32_t*)(expected), (uint32_t)(desired)), \
|
|
281
|
+
uint32_t *: ac_cas_u32((volatile uint32_t*)(ptr), (uint32_t*)(expected), (uint32_t)(desired)), \
|
|
282
|
+
default: ac_cas_ptr((void * volatile *)(ptr), (void**)(expected), (void*)(desired)) \
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
/* --------------------------------------------------------------------- */
|
|
286
|
+
/* 5) Public C11-like API (explicit + default seq_cst variants). */
|
|
287
|
+
/* These *do not* require _Atomic-qualified objects on MSVC. */
|
|
288
|
+
/* --------------------------------------------------------------------- */
|
|
289
|
+
|
|
290
|
+
#define atomic_init(obj, value) \
|
|
291
|
+
atomic_compat_store((obj), (value))
|
|
292
|
+
|
|
293
|
+
#define atomic_load_explicit(ptr, order) \
|
|
294
|
+
( (void)(order), atomic_compat_load(ptr) )
|
|
295
|
+
|
|
296
|
+
#define atomic_store_explicit(ptr, value, order) \
|
|
297
|
+
do { (void)(order); atomic_compat_store((ptr), (value)); } while (0)
|
|
298
|
+
|
|
299
|
+
#define atomic_exchange_explicit(ptr, value, order) \
|
|
300
|
+
( (void)(order), atomic_compat_exchange((ptr), (value)) )
|
|
301
|
+
|
|
302
|
+
#define atomic_fetch_add_explicit(ptr, value, order) \
|
|
303
|
+
( (void)(order), atomic_compat_fetch_add((ptr), (value)) )
|
|
304
|
+
|
|
305
|
+
#define atomic_fetch_sub_explicit(ptr, value, order) \
|
|
306
|
+
( (void)(order), atomic_compat_fetch_sub((ptr), (value)) )
|
|
307
|
+
|
|
308
|
+
#define atomic_compare_exchange_strong_explicit(ptr, expected, desired, success_order, failure_order) \
|
|
309
|
+
( (void)(success_order), (void)(failure_order), atomic_compat_compare_exchange((ptr), (expected), (desired)) )
|
|
310
|
+
|
|
311
|
+
#define atomic_compare_exchange_weak_explicit(ptr, expected, desired, success_order, failure_order) \
|
|
312
|
+
atomic_compare_exchange_strong_explicit(ptr, expected, desired, success_order, failure_order)
|
|
313
|
+
|
|
314
|
+
/* seq_cst defaults per C11 */
|
|
315
|
+
#define atomic_load(ptr) atomic_load_explicit((ptr), memory_order_seq_cst)
|
|
316
|
+
#define atomic_store(ptr, value) atomic_store_explicit((ptr), (value), memory_order_seq_cst)
|
|
317
|
+
#define atomic_exchange(ptr, value) atomic_exchange_explicit((ptr), (value), memory_order_seq_cst)
|
|
318
|
+
#define atomic_fetch_add(ptr, value) atomic_fetch_add_explicit((ptr), (value), memory_order_seq_cst)
|
|
319
|
+
#define atomic_fetch_sub(ptr, value) atomic_fetch_sub_explicit((ptr), (value), memory_order_seq_cst)
|
|
320
|
+
#define atomic_compare_exchange_strong(ptr,e,d) atomic_compare_exchange_strong_explicit((ptr),(e),(d), memory_order_acq_rel, memory_order_acquire)
|
|
321
|
+
#define atomic_compare_exchange_weak(ptr,e,d) atomic_compare_exchange_weak_explicit((ptr),(e),(d), memory_order_acq_rel, memory_order_acquire)
|
|
322
|
+
|
|
323
|
+
/* atomic_flag support:
|
|
324
|
+
- If vcruntime already typedefs atomic_flag, we only provide the API macros.
|
|
325
|
+
- If not, we provide a minimal struct + API. */
|
|
326
|
+
#ifndef ATOMIC_FLAG_INIT
|
|
327
|
+
# define ATOMIC_FLAG_INIT { 0 }
|
|
328
|
+
#endif
|
|
329
|
+
|
|
330
|
+
/* Minimal atomic_flag replacement for the compatibility path. */
|
|
331
|
+
typedef struct {
|
|
332
|
+
volatile LONG _v;
|
|
333
|
+
} atomic_flag;
|
|
334
|
+
|
|
335
|
+
static __forceinline int atomic_flag_test_and_set_explicit(atomic_flag *obj, memory_order order) {
|
|
336
|
+
(void)order;
|
|
337
|
+
/* Returns previous value (true if already set). */
|
|
338
|
+
LONG prev = InterlockedExchange(&obj->_v, 1);
|
|
339
|
+
return prev != 0;
|
|
340
|
+
}
|
|
341
|
+
static __forceinline void atomic_flag_clear_explicit(atomic_flag *obj, memory_order order) {
|
|
342
|
+
(void)order;
|
|
343
|
+
InterlockedExchange(&obj->_v, 0);
|
|
344
|
+
}
|
|
345
|
+
#define atomic_flag_test_and_set(obj) atomic_flag_test_and_set_explicit((obj), memory_order_seq_cst)
|
|
346
|
+
#define atomic_flag_clear(obj) atomic_flag_clear_explicit((obj), memory_order_seq_cst)
|
|
347
|
+
|
|
348
|
+
#endif /* ATOMIC_COMPAT_USE_NATIVE_ATOMICS */
|
|
349
|
+
|
|
350
|
+
/* ===================================================================== */
|
|
351
|
+
/* NON-MSVC (use real C11) */
|
|
352
|
+
/* ===================================================================== */
|
|
353
|
+
#else /* !_MSC_VER */
|
|
354
|
+
|
|
355
|
+
# include <stdatomic.h>
|
|
356
|
+
# define ATOMIC_COMPAT_HAVE_ATOMICS 1
|
|
357
|
+
# define ATOMIC_VAR(type) _Atomic(type)
|
|
358
|
+
|
|
359
|
+
#endif /* _MSC_VER */
|
|
360
|
+
|
|
361
|
+
#ifdef __cplusplus
|
|
362
|
+
} /* extern "C" */
|
|
363
|
+
#endif
|
|
364
|
+
|
|
365
|
+
#endif /* ATOMIC_COMPAT_H */
|