Avoid using ATOMIC macros
[openal-soft.git] / Alc / alcontext.h
blobc9cfa98524ac562680807a5ee7e16f32237046be
1 #ifndef ALCONTEXT_H
2 #define ALCONTEXT_H
4 #include <mutex>
5 #include <atomic>
6 #include <memory>
7 #include <thread>
9 #include "AL/al.h"
10 #include "AL/alc.h"
11 #include "AL/alext.h"
12 #include "inprogext.h"
14 #include "atomic.h"
15 #include "vector.h"
16 #include "threads.h"
17 #include "almalloc.h"
19 #include "alListener.h"
22 struct ALsource;
23 struct ALeffectslot;
24 struct ALcontextProps;
25 struct ALlistenerProps;
26 struct ALvoiceProps;
27 struct ALeffectslotProps;
28 struct ALvoice;
29 struct ALeffectslotArray;
30 struct ll_ringbuffer;
32 enum class DistanceModel {
33 InverseClamped = AL_INVERSE_DISTANCE_CLAMPED,
34 LinearClamped = AL_LINEAR_DISTANCE_CLAMPED,
35 ExponentClamped = AL_EXPONENT_DISTANCE_CLAMPED,
36 Inverse = AL_INVERSE_DISTANCE,
37 Linear = AL_LINEAR_DISTANCE,
38 Exponent = AL_EXPONENT_DISTANCE,
39 Disable = AL_NONE,
41 Default = InverseClamped
44 struct SourceSubList {
45 uint64_t FreeMask{0u};
46 ALsource *Sources{nullptr}; /* 64 */
49 /* Effect slots are rather large, and apps aren't likely to have more than one
50 * or two (let alone 64), so hold them individually.
52 using ALeffectslotPtr = std::unique_ptr<ALeffectslot>;
54 struct ALCcontext_struct {
55 RefCount ref{1u};
57 al::vector<SourceSubList> SourceList;
58 ALuint NumSources{0};
59 almtx_t SourceLock;
61 al::vector<ALeffectslotPtr> EffectSlotList;
62 almtx_t EffectSlotLock;
64 ATOMIC(ALenum) LastError{AL_NO_ERROR};
66 DistanceModel mDistanceModel{DistanceModel::Default};
67 ALboolean SourceDistanceModel{AL_FALSE};
69 ALfloat DopplerFactor{1.0f};
70 ALfloat DopplerVelocity{1.0f};
71 ALfloat SpeedOfSound{};
72 ALfloat MetersPerUnit{1.0f};
74 std::atomic_flag PropsClean{true};
75 std::atomic<bool> DeferUpdates{false};
77 almtx_t PropLock;
79 /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit
80 * indicates if updates are currently happening).
82 RefCount UpdateCount{0u};
83 ATOMIC(ALenum) HoldUpdates{AL_FALSE};
85 ALfloat GainBoost{1.0f};
87 ATOMIC(ALcontextProps*) Update{nullptr};
89 /* Linked lists of unused property containers, free to use for future
90 * updates.
92 ATOMIC(ALcontextProps*) FreeContextProps{nullptr};
93 ATOMIC(ALlistenerProps*) FreeListenerProps{nullptr};
94 ATOMIC(ALvoiceProps*) FreeVoiceProps{nullptr};
95 ATOMIC(ALeffectslotProps*) FreeEffectslotProps{nullptr};
97 ALvoice **Voices{nullptr};
98 ALsizei VoiceCount{0};
99 ALsizei MaxVoices{0};
101 ATOMIC(ALeffectslotArray*) ActiveAuxSlots{nullptr};
103 std::thread EventThread;
104 alsem_t EventSem;
105 ll_ringbuffer *AsyncEvents{nullptr};
106 ATOMIC(ALbitfieldSOFT) EnabledEvts{0u};
107 std::mutex EventCbLock;
108 ALEVENTPROCSOFT EventCb{};
109 void *EventParam{nullptr};
111 /* Default effect slot */
112 std::unique_ptr<ALeffectslot> DefaultSlot;
114 ALCdevice *const Device;
115 const ALCchar *ExtensionList{nullptr};
117 ATOMIC(ALCcontext*) next{nullptr};
119 ALlistener Listener{};
122 ALCcontext_struct(ALCdevice *device);
123 ALCcontext_struct(const ALCcontext_struct&) = delete;
124 ALCcontext_struct& operator=(const ALCcontext_struct&) = delete;
125 ~ALCcontext_struct();
127 DEF_NEWDEL(ALCcontext)
130 ALCcontext *GetContextRef(void);
131 void ALCcontext_DecRef(ALCcontext *context);
133 void UpdateContextProps(ALCcontext *context);
135 void ALCcontext_DeferUpdates(ALCcontext *context);
136 void ALCcontext_ProcessUpdates(ALCcontext *context);
139 /* Simple RAII context reference. Takes the reference of the provided
140 * ALCcontext, and decrements it when leaving scope. Movable (transfer
141 * reference) but not copyable (no new references).
143 class ContextRef {
144 ALCcontext *mCtx{nullptr};
146 void reset() noexcept
148 if(mCtx)
149 ALCcontext_DecRef(mCtx);
150 mCtx = nullptr;
153 public:
154 ContextRef() noexcept = default;
155 ContextRef(ContextRef&& rhs) noexcept : mCtx{rhs.mCtx}
156 { rhs.mCtx = nullptr; }
157 explicit ContextRef(ALCcontext *ctx) noexcept : mCtx(ctx) { }
158 ~ContextRef() { reset(); }
160 ContextRef& operator=(const ContextRef&) = delete;
161 ContextRef& operator=(ContextRef&& rhs) noexcept
163 reset();
164 mCtx = rhs.mCtx;
165 rhs.mCtx = nullptr;
166 return *this;
169 operator bool() const noexcept { return mCtx != nullptr; }
171 ALCcontext* operator->() noexcept { return mCtx; }
172 ALCcontext* get() noexcept { return mCtx; }
174 ALCcontext* release() noexcept
176 ALCcontext *ret{mCtx};
177 mCtx = nullptr;
178 return ret;
183 struct ALcontextProps {
184 ALfloat DopplerFactor;
185 ALfloat DopplerVelocity;
186 ALfloat SpeedOfSound;
187 ALboolean SourceDistanceModel;
188 DistanceModel mDistanceModel;
189 ALfloat MetersPerUnit;
191 ATOMIC(struct ALcontextProps*) next;
194 #endif /* ALCONTEXT_H */