Use a standard mutex for the event callback lock
[openal-soft.git] / OpenAL32 / alState.cpp
blob95a4fd9291c6179ed639e4027d29bfe9154d7325
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2000 by authors.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 * Or go to http://www.gnu.org/copyleft/lgpl.html
21 #include "config.h"
23 #include "version.h"
25 #include <stdlib.h>
26 #include <cmath>
28 #include "alMain.h"
29 #include "alcontext.h"
30 #include "alu.h"
31 #include "alError.h"
33 #include "backends/base.h"
36 namespace {
38 constexpr ALchar alVendor[] = "OpenAL Community";
39 constexpr ALchar alVersion[] = "1.1 ALSOFT " ALSOFT_VERSION;
40 constexpr ALchar alRenderer[] = "OpenAL Soft";
42 // Error Messages
43 constexpr ALchar alNoError[] = "No Error";
44 constexpr ALchar alErrInvalidName[] = "Invalid Name";
45 constexpr ALchar alErrInvalidEnum[] = "Invalid Enum";
46 constexpr ALchar alErrInvalidValue[] = "Invalid Value";
47 constexpr ALchar alErrInvalidOp[] = "Invalid Operation";
48 constexpr ALchar alErrOutOfMemory[] = "Out of Memory";
50 /* Resampler strings */
51 constexpr ALchar alPointResampler[] = "Nearest";
52 constexpr ALchar alLinearResampler[] = "Linear";
53 constexpr ALchar alCubicResampler[] = "Cubic";
54 constexpr ALchar alBSinc12Resampler[] = "11th order Sinc";
55 constexpr ALchar alBSinc24Resampler[] = "23rd order Sinc";
57 } // namespace
59 /* WARNING: Non-standard export! Not part of any extension, or exposed in the
60 * alcFunctions list.
62 extern "C" AL_API const ALchar* AL_APIENTRY alsoft_get_version(void)
64 const char *spoof{getenv("ALSOFT_SPOOF_VERSION")};
65 if(spoof && spoof[0] != '\0') return spoof;
66 return ALSOFT_VERSION;
69 #define DO_UPDATEPROPS() do { \
70 if(!context->DeferUpdates.load(std::memory_order_acquire)) \
71 UpdateContextProps(context.get()); \
72 else \
73 context->PropsClean.clear(std::memory_order_release); \
74 } while(0)
77 AL_API ALvoid AL_APIENTRY alEnable(ALenum capability)
79 ContextRef context{GetContextRef()};
80 if(UNLIKELY(!context)) return;
82 std::lock_guard<almtx_t> _{context->PropLock};
83 switch(capability)
85 case AL_SOURCE_DISTANCE_MODEL:
86 context->SourceDistanceModel = AL_TRUE;
87 DO_UPDATEPROPS();
88 break;
90 default:
91 alSetError(context.get(), AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability);
95 AL_API ALvoid AL_APIENTRY alDisable(ALenum capability)
97 ContextRef context{GetContextRef()};
98 if(UNLIKELY(!context)) return;
100 std::lock_guard<almtx_t> _{context->PropLock};
101 switch(capability)
103 case AL_SOURCE_DISTANCE_MODEL:
104 context->SourceDistanceModel = AL_FALSE;
105 DO_UPDATEPROPS();
106 break;
108 default:
109 alSetError(context.get(), AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability);
113 AL_API ALboolean AL_APIENTRY alIsEnabled(ALenum capability)
115 ContextRef context{GetContextRef()};
116 if(UNLIKELY(!context)) return AL_FALSE;
118 std::lock_guard<almtx_t> _{context->PropLock};
119 ALboolean value{AL_FALSE};
120 switch(capability)
122 case AL_SOURCE_DISTANCE_MODEL:
123 value = context->SourceDistanceModel;
124 break;
126 default:
127 alSetError(context.get(), AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability);
130 return value;
133 AL_API ALboolean AL_APIENTRY alGetBoolean(ALenum pname)
135 ContextRef context{GetContextRef()};
136 if(UNLIKELY(!context)) return AL_FALSE;
138 std::lock_guard<almtx_t> _{context->PropLock};
139 ALboolean value{AL_FALSE};
140 switch(pname)
142 case AL_DOPPLER_FACTOR:
143 if(context->DopplerFactor != 0.0f)
144 value = AL_TRUE;
145 break;
147 case AL_DOPPLER_VELOCITY:
148 if(context->DopplerVelocity != 0.0f)
149 value = AL_TRUE;
150 break;
152 case AL_DISTANCE_MODEL:
153 if(context->mDistanceModel == DistanceModel::Default)
154 value = AL_TRUE;
155 break;
157 case AL_SPEED_OF_SOUND:
158 if(context->SpeedOfSound != 0.0f)
159 value = AL_TRUE;
160 break;
162 case AL_DEFERRED_UPDATES_SOFT:
163 if(context->DeferUpdates.load(std::memory_order_acquire))
164 value = AL_TRUE;
165 break;
167 case AL_GAIN_LIMIT_SOFT:
168 if(GAIN_MIX_MAX/context->GainBoost != 0.0f)
169 value = AL_TRUE;
170 break;
172 case AL_NUM_RESAMPLERS_SOFT:
173 /* Always non-0. */
174 value = AL_TRUE;
175 break;
177 case AL_DEFAULT_RESAMPLER_SOFT:
178 value = ResamplerDefault ? AL_TRUE : AL_FALSE;
179 break;
181 default:
182 alSetError(context.get(), AL_INVALID_VALUE, "Invalid boolean property 0x%04x", pname);
185 return value;
188 AL_API ALdouble AL_APIENTRY alGetDouble(ALenum pname)
190 ContextRef context{GetContextRef()};
191 if(UNLIKELY(!context)) return 0.0;
193 std::lock_guard<almtx_t> _{context->PropLock};
194 ALdouble value{0.0};
195 switch(pname)
197 case AL_DOPPLER_FACTOR:
198 value = (ALdouble)context->DopplerFactor;
199 break;
201 case AL_DOPPLER_VELOCITY:
202 value = (ALdouble)context->DopplerVelocity;
203 break;
205 case AL_DISTANCE_MODEL:
206 value = (ALdouble)context->mDistanceModel;
207 break;
209 case AL_SPEED_OF_SOUND:
210 value = (ALdouble)context->SpeedOfSound;
211 break;
213 case AL_DEFERRED_UPDATES_SOFT:
214 if(context->DeferUpdates.load(std::memory_order_acquire))
215 value = (ALdouble)AL_TRUE;
216 break;
218 case AL_GAIN_LIMIT_SOFT:
219 value = (ALdouble)GAIN_MIX_MAX/context->GainBoost;
220 break;
222 case AL_NUM_RESAMPLERS_SOFT:
223 value = (ALdouble)(ResamplerMax + 1);
224 break;
226 case AL_DEFAULT_RESAMPLER_SOFT:
227 value = (ALdouble)ResamplerDefault;
228 break;
230 default:
231 alSetError(context.get(), AL_INVALID_VALUE, "Invalid double property 0x%04x", pname);
234 return value;
237 AL_API ALfloat AL_APIENTRY alGetFloat(ALenum pname)
239 ContextRef context{GetContextRef()};
240 if(UNLIKELY(!context)) return 0.0f;
242 std::lock_guard<almtx_t> _{context->PropLock};
243 ALfloat value{0.0f};
244 switch(pname)
246 case AL_DOPPLER_FACTOR:
247 value = context->DopplerFactor;
248 break;
250 case AL_DOPPLER_VELOCITY:
251 value = context->DopplerVelocity;
252 break;
254 case AL_DISTANCE_MODEL:
255 value = (ALfloat)context->mDistanceModel;
256 break;
258 case AL_SPEED_OF_SOUND:
259 value = context->SpeedOfSound;
260 break;
262 case AL_DEFERRED_UPDATES_SOFT:
263 if(context->DeferUpdates.load(std::memory_order_acquire))
264 value = (ALfloat)AL_TRUE;
265 break;
267 case AL_GAIN_LIMIT_SOFT:
268 value = GAIN_MIX_MAX/context->GainBoost;
269 break;
271 case AL_NUM_RESAMPLERS_SOFT:
272 value = (ALfloat)(ResamplerMax + 1);
273 break;
275 case AL_DEFAULT_RESAMPLER_SOFT:
276 value = (ALfloat)ResamplerDefault;
277 break;
279 default:
280 alSetError(context.get(), AL_INVALID_VALUE, "Invalid float property 0x%04x", pname);
283 return value;
286 AL_API ALint AL_APIENTRY alGetInteger(ALenum pname)
288 ContextRef context{GetContextRef()};
289 if(UNLIKELY(!context)) return 0;
291 std::lock_guard<almtx_t> _{context->PropLock};
292 ALint value{0};
293 switch(pname)
295 case AL_DOPPLER_FACTOR:
296 value = (ALint)context->DopplerFactor;
297 break;
299 case AL_DOPPLER_VELOCITY:
300 value = (ALint)context->DopplerVelocity;
301 break;
303 case AL_DISTANCE_MODEL:
304 value = (ALint)context->mDistanceModel;
305 break;
307 case AL_SPEED_OF_SOUND:
308 value = (ALint)context->SpeedOfSound;
309 break;
311 case AL_DEFERRED_UPDATES_SOFT:
312 if(context->DeferUpdates.load(std::memory_order_acquire))
313 value = (ALint)AL_TRUE;
314 break;
316 case AL_GAIN_LIMIT_SOFT:
317 value = (ALint)(GAIN_MIX_MAX/context->GainBoost);
318 break;
320 case AL_NUM_RESAMPLERS_SOFT:
321 value = ResamplerMax + 1;
322 break;
324 case AL_DEFAULT_RESAMPLER_SOFT:
325 value = ResamplerDefault;
326 break;
328 default:
329 alSetError(context.get(), AL_INVALID_VALUE, "Invalid integer property 0x%04x", pname);
332 return value;
335 extern "C" AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname)
337 ContextRef context{GetContextRef()};
338 if(UNLIKELY(!context)) return 0;
340 std::lock_guard<almtx_t> _{context->PropLock};
341 ALint64SOFT value{0};
342 switch(pname)
344 case AL_DOPPLER_FACTOR:
345 value = (ALint64SOFT)context->DopplerFactor;
346 break;
348 case AL_DOPPLER_VELOCITY:
349 value = (ALint64SOFT)context->DopplerVelocity;
350 break;
352 case AL_DISTANCE_MODEL:
353 value = (ALint64SOFT)context->mDistanceModel;
354 break;
356 case AL_SPEED_OF_SOUND:
357 value = (ALint64SOFT)context->SpeedOfSound;
358 break;
360 case AL_DEFERRED_UPDATES_SOFT:
361 if(context->DeferUpdates.load(std::memory_order_acquire))
362 value = (ALint64SOFT)AL_TRUE;
363 break;
365 case AL_GAIN_LIMIT_SOFT:
366 value = (ALint64SOFT)(GAIN_MIX_MAX/context->GainBoost);
367 break;
369 case AL_NUM_RESAMPLERS_SOFT:
370 value = (ALint64SOFT)(ResamplerMax + 1);
371 break;
373 case AL_DEFAULT_RESAMPLER_SOFT:
374 value = (ALint64SOFT)ResamplerDefault;
375 break;
377 default:
378 alSetError(context.get(), AL_INVALID_VALUE, "Invalid integer64 property 0x%04x", pname);
381 return value;
384 AL_API void* AL_APIENTRY alGetPointerSOFT(ALenum pname)
386 ContextRef context{GetContextRef()};
387 if(UNLIKELY(!context)) return nullptr;
389 std::lock_guard<almtx_t> _{context->PropLock};
390 void *value{nullptr};
391 switch(pname)
393 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
394 value = reinterpret_cast<void*>(context->EventCb);
395 break;
397 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
398 value = context->EventParam;
399 break;
401 default:
402 alSetError(context.get(), AL_INVALID_VALUE, "Invalid pointer property 0x%04x", pname);
405 return value;
408 AL_API ALvoid AL_APIENTRY alGetBooleanv(ALenum pname, ALboolean *values)
410 if(values)
412 switch(pname)
414 case AL_DOPPLER_FACTOR:
415 case AL_DOPPLER_VELOCITY:
416 case AL_DISTANCE_MODEL:
417 case AL_SPEED_OF_SOUND:
418 case AL_DEFERRED_UPDATES_SOFT:
419 case AL_GAIN_LIMIT_SOFT:
420 case AL_NUM_RESAMPLERS_SOFT:
421 case AL_DEFAULT_RESAMPLER_SOFT:
422 values[0] = alGetBoolean(pname);
423 return;
427 ContextRef context{GetContextRef()};
428 if(UNLIKELY(!context)) return;
430 if(!values)
431 alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
432 else switch(pname)
434 default:
435 alSetError(context.get(), AL_INVALID_VALUE, "Invalid boolean-vector property 0x%04x", pname);
439 AL_API ALvoid AL_APIENTRY alGetDoublev(ALenum pname, ALdouble *values)
441 if(values)
443 switch(pname)
445 case AL_DOPPLER_FACTOR:
446 case AL_DOPPLER_VELOCITY:
447 case AL_DISTANCE_MODEL:
448 case AL_SPEED_OF_SOUND:
449 case AL_DEFERRED_UPDATES_SOFT:
450 case AL_GAIN_LIMIT_SOFT:
451 case AL_NUM_RESAMPLERS_SOFT:
452 case AL_DEFAULT_RESAMPLER_SOFT:
453 values[0] = alGetDouble(pname);
454 return;
458 ContextRef context{GetContextRef()};
459 if(UNLIKELY(!context)) return;
461 if(!values)
462 alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
463 else switch(pname)
465 default:
466 alSetError(context.get(), AL_INVALID_VALUE, "Invalid double-vector property 0x%04x", pname);
470 AL_API ALvoid AL_APIENTRY alGetFloatv(ALenum pname, ALfloat *values)
472 if(values)
474 switch(pname)
476 case AL_DOPPLER_FACTOR:
477 case AL_DOPPLER_VELOCITY:
478 case AL_DISTANCE_MODEL:
479 case AL_SPEED_OF_SOUND:
480 case AL_DEFERRED_UPDATES_SOFT:
481 case AL_GAIN_LIMIT_SOFT:
482 case AL_NUM_RESAMPLERS_SOFT:
483 case AL_DEFAULT_RESAMPLER_SOFT:
484 values[0] = alGetFloat(pname);
485 return;
489 ContextRef context{GetContextRef()};
490 if(UNLIKELY(!context)) return;
492 if(!values)
493 alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
494 else switch(pname)
496 default:
497 alSetError(context.get(), AL_INVALID_VALUE, "Invalid float-vector property 0x%04x", pname);
501 AL_API ALvoid AL_APIENTRY alGetIntegerv(ALenum pname, ALint *values)
503 if(values)
505 switch(pname)
507 case AL_DOPPLER_FACTOR:
508 case AL_DOPPLER_VELOCITY:
509 case AL_DISTANCE_MODEL:
510 case AL_SPEED_OF_SOUND:
511 case AL_DEFERRED_UPDATES_SOFT:
512 case AL_GAIN_LIMIT_SOFT:
513 case AL_NUM_RESAMPLERS_SOFT:
514 case AL_DEFAULT_RESAMPLER_SOFT:
515 values[0] = alGetInteger(pname);
516 return;
520 ContextRef context{GetContextRef()};
521 if(UNLIKELY(!context)) return;
523 if(!values)
524 alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
525 else switch(pname)
527 default:
528 alSetError(context.get(), AL_INVALID_VALUE, "Invalid integer-vector property 0x%04x", pname);
532 extern "C" AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values)
534 if(values)
536 switch(pname)
538 case AL_DOPPLER_FACTOR:
539 case AL_DOPPLER_VELOCITY:
540 case AL_DISTANCE_MODEL:
541 case AL_SPEED_OF_SOUND:
542 case AL_DEFERRED_UPDATES_SOFT:
543 case AL_GAIN_LIMIT_SOFT:
544 case AL_NUM_RESAMPLERS_SOFT:
545 case AL_DEFAULT_RESAMPLER_SOFT:
546 values[0] = alGetInteger64SOFT(pname);
547 return;
551 ContextRef context{GetContextRef()};
552 if(UNLIKELY(!context)) return;
554 if(!values)
555 alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
556 else switch(pname)
558 default:
559 alSetError(context.get(), AL_INVALID_VALUE, "Invalid integer64-vector property 0x%04x", pname);
563 AL_API void AL_APIENTRY alGetPointervSOFT(ALenum pname, void **values)
565 if(values)
567 switch(pname)
569 case AL_EVENT_CALLBACK_FUNCTION_SOFT:
570 case AL_EVENT_CALLBACK_USER_PARAM_SOFT:
571 values[0] = alGetPointerSOFT(pname);
572 return;
576 ContextRef context{GetContextRef()};
577 if(UNLIKELY(!context)) return;
579 if(!values)
580 alSetError(context.get(), AL_INVALID_VALUE, "NULL pointer");
581 else switch(pname)
583 default:
584 alSetError(context.get(), AL_INVALID_VALUE, "Invalid pointer-vector property 0x%04x", pname);
588 AL_API const ALchar* AL_APIENTRY alGetString(ALenum pname)
590 ContextRef context{GetContextRef()};
591 if(UNLIKELY(!context)) return nullptr;
593 const ALchar *value{nullptr};
594 switch(pname)
596 case AL_VENDOR:
597 value = alVendor;
598 break;
600 case AL_VERSION:
601 value = alVersion;
602 break;
604 case AL_RENDERER:
605 value = alRenderer;
606 break;
608 case AL_EXTENSIONS:
609 value = context->ExtensionList;
610 break;
612 case AL_NO_ERROR:
613 value = alNoError;
614 break;
616 case AL_INVALID_NAME:
617 value = alErrInvalidName;
618 break;
620 case AL_INVALID_ENUM:
621 value = alErrInvalidEnum;
622 break;
624 case AL_INVALID_VALUE:
625 value = alErrInvalidValue;
626 break;
628 case AL_INVALID_OPERATION:
629 value = alErrInvalidOp;
630 break;
632 case AL_OUT_OF_MEMORY:
633 value = alErrOutOfMemory;
634 break;
636 default:
637 alSetError(context.get(), AL_INVALID_VALUE, "Invalid string property 0x%04x", pname);
639 return value;
642 AL_API ALvoid AL_APIENTRY alDopplerFactor(ALfloat value)
644 ContextRef context{GetContextRef()};
645 if(UNLIKELY(!context)) return;
647 if(!(value >= 0.0f && std::isfinite(value)))
648 alSetError(context.get(), AL_INVALID_VALUE, "Doppler factor %f out of range", value);
649 else
651 std::lock_guard<almtx_t> _{context->PropLock};
652 context->DopplerFactor = value;
653 DO_UPDATEPROPS();
657 AL_API ALvoid AL_APIENTRY alDopplerVelocity(ALfloat value)
659 ContextRef context{GetContextRef()};
660 if(UNLIKELY(!context)) return;
662 if((ATOMIC_LOAD(&context->EnabledEvts, almemory_order_relaxed)&EventType_Deprecated))
664 static constexpr ALCchar msg[] =
665 "alDopplerVelocity is deprecated in AL1.1, use alSpeedOfSound";
666 const ALsizei msglen = (ALsizei)strlen(msg);
667 std::lock_guard<std::mutex> _{context->EventCbLock};
668 ALbitfieldSOFT enabledevts{context->EnabledEvts.load(std::memory_order_relaxed)};
669 if((enabledevts&EventType_Deprecated) && context->EventCb)
670 (*context->EventCb)(AL_EVENT_TYPE_DEPRECATED_SOFT, 0, 0, msglen, msg,
671 context->EventParam);
674 if(!(value >= 0.0f && std::isfinite(value)))
675 alSetError(context.get(), AL_INVALID_VALUE, "Doppler velocity %f out of range", value);
676 else
678 std::lock_guard<almtx_t> _{context->PropLock};
679 context->DopplerVelocity = value;
680 DO_UPDATEPROPS();
684 AL_API ALvoid AL_APIENTRY alSpeedOfSound(ALfloat value)
686 ContextRef context{GetContextRef()};
687 if(UNLIKELY(!context)) return;
689 if(!(value > 0.0f && std::isfinite(value)))
690 alSetError(context.get(), AL_INVALID_VALUE, "Speed of sound %f out of range", value);
691 else
693 std::lock_guard<almtx_t> _{context->PropLock};
694 context->SpeedOfSound = value;
695 DO_UPDATEPROPS();
699 AL_API ALvoid AL_APIENTRY alDistanceModel(ALenum value)
701 ContextRef context{GetContextRef()};
702 if(UNLIKELY(!context)) return;
704 if(!(value == AL_INVERSE_DISTANCE || value == AL_INVERSE_DISTANCE_CLAMPED ||
705 value == AL_LINEAR_DISTANCE || value == AL_LINEAR_DISTANCE_CLAMPED ||
706 value == AL_EXPONENT_DISTANCE || value == AL_EXPONENT_DISTANCE_CLAMPED ||
707 value == AL_NONE))
708 alSetError(context.get(), AL_INVALID_VALUE, "Distance model 0x%04x out of range", value);
709 else
711 std::lock_guard<almtx_t> _{context->PropLock};
712 context->mDistanceModel = static_cast<DistanceModel>(value);
713 if(!context->SourceDistanceModel)
714 DO_UPDATEPROPS();
719 AL_API ALvoid AL_APIENTRY alDeferUpdatesSOFT(void)
721 ContextRef context{GetContextRef()};
722 if(UNLIKELY(!context)) return;
724 ALCcontext_DeferUpdates(context.get());
727 AL_API ALvoid AL_APIENTRY alProcessUpdatesSOFT(void)
729 ContextRef context{GetContextRef()};
730 if(UNLIKELY(!context)) return;
732 ALCcontext_ProcessUpdates(context.get());
736 AL_API const ALchar* AL_APIENTRY alGetStringiSOFT(ALenum pname, ALsizei index)
738 const char *ResamplerNames[] = {
739 alPointResampler, alLinearResampler,
740 alCubicResampler, alBSinc12Resampler,
741 alBSinc24Resampler,
743 static_assert(COUNTOF(ResamplerNames) == ResamplerMax+1, "Incorrect ResamplerNames list");
745 ContextRef context{GetContextRef()};
746 if(UNLIKELY(!context)) return nullptr;
748 const ALchar *value{nullptr};
749 switch(pname)
751 case AL_RESAMPLER_NAME_SOFT:
752 if(index < 0 || (size_t)index >= COUNTOF(ResamplerNames))
753 alSetError(context.get(), AL_INVALID_VALUE, "Resampler name index %d out of range",
754 index);
755 else
756 value = ResamplerNames[index];
757 break;
759 default:
760 alSetError(context.get(), AL_INVALID_VALUE, "Invalid string indexed property");
762 return value;
766 void UpdateContextProps(ALCcontext *context)
768 /* Get an unused proprty container, or allocate a new one as needed. */
769 struct ALcontextProps *props{context->FreeContextProps.load(std::memory_order_acquire)};
770 if(!props)
771 props = static_cast<ALcontextProps*>(al_calloc(16, sizeof(*props)));
772 else
774 struct ALcontextProps *next;
775 do {
776 next = props->next.load(std::memory_order_relaxed);
777 } while(context->FreeContextProps.compare_exchange_weak(props, next,
778 std::memory_order_seq_cst, std::memory_order_acquire) == 0);
781 /* Copy in current property values. */
782 props->MetersPerUnit = context->MetersPerUnit;
784 props->DopplerFactor = context->DopplerFactor;
785 props->DopplerVelocity = context->DopplerVelocity;
786 props->SpeedOfSound = context->SpeedOfSound;
788 props->SourceDistanceModel = context->SourceDistanceModel;
789 props->mDistanceModel = context->mDistanceModel;
791 /* Set the new container for updating internal parameters. */
792 props = context->Update.exchange(props, std::memory_order_acq_rel);
793 if(props)
795 /* If there was an unused update container, put it back in the
796 * freelist.
798 AtomicReplaceHead(context->FreeContextProps, props);