Use separate atomic macros for pointers
[openal-soft.git] / OpenAL32 / alAuxEffectSlot.c
blobde7de94365397a73a6863efc065a569730c517f2
1 /**
2 * OpenAL cross platform audio library
3 * Copyright (C) 1999-2007 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 <stdlib.h>
24 #include <math.h>
26 #include "AL/al.h"
27 #include "AL/alc.h"
28 #include "alMain.h"
29 #include "alAuxEffectSlot.h"
30 #include "alThunk.h"
31 #include "alError.h"
32 #include "alListener.h"
33 #include "alSource.h"
35 #include "almalloc.h"
38 extern inline void LockEffectSlotsRead(ALCcontext *context);
39 extern inline void UnlockEffectSlotsRead(ALCcontext *context);
40 extern inline void LockEffectSlotsWrite(ALCcontext *context);
41 extern inline void UnlockEffectSlotsWrite(ALCcontext *context);
42 extern inline struct ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id);
43 extern inline struct ALeffectslot *RemoveEffectSlot(ALCcontext *context, ALuint id);
45 static UIntMap EffectStateFactoryMap;
46 static inline ALeffectStateFactory *getFactoryByType(ALenum type)
48 ALeffectStateFactory* (*getFactory)(void) = LookupUIntMapKey(&EffectStateFactoryMap, type);
49 if(getFactory != NULL)
50 return getFactory();
51 return NULL;
54 static void ALeffectState_IncRef(ALeffectState *state);
55 static void ALeffectState_DecRef(ALeffectState *state);
57 #define DO_UPDATEPROPS() do { \
58 if(!ATOMIC_LOAD(&context->DeferUpdates, almemory_order_acquire)) \
59 UpdateEffectSlotProps(slot); \
60 else \
61 ATOMIC_FLAG_CLEAR(&slot->PropsClean, almemory_order_release); \
62 } while(0)
65 AL_API ALvoid AL_APIENTRY alGenAuxiliaryEffectSlots(ALsizei n, ALuint *effectslots)
67 ALCcontext *context;
68 ALeffectslot **tmpslots = NULL;
69 ALsizei cur;
70 ALenum err;
72 context = GetContextRef();
73 if(!context) return;
75 if(!(n >= 0))
76 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
77 tmpslots = al_malloc(DEF_ALIGN, sizeof(ALeffectslot*)*n);
79 LockEffectSlotsWrite(context);
80 for(cur = 0;cur < n;cur++)
82 ALeffectslot *slot = al_calloc(16, sizeof(ALeffectslot));
83 err = AL_OUT_OF_MEMORY;
84 if(!slot || (err=InitEffectSlot(slot)) != AL_NO_ERROR)
86 al_free(slot);
87 UnlockEffectSlotsWrite(context);
89 alDeleteAuxiliaryEffectSlots(cur, effectslots);
90 SET_ERROR_AND_GOTO(context, err, done);
93 err = NewThunkEntry(&slot->id);
94 if(err == AL_NO_ERROR)
95 err = InsertUIntMapEntryNoLock(&context->EffectSlotMap, slot->id, slot);
96 if(err != AL_NO_ERROR)
98 FreeThunkEntry(slot->id);
99 ALeffectState_DecRef(slot->Effect.State);
100 if(slot->Params.EffectState)
101 ALeffectState_DecRef(slot->Params.EffectState);
102 al_free(slot);
103 UnlockEffectSlotsWrite(context);
105 alDeleteAuxiliaryEffectSlots(cur, effectslots);
106 SET_ERROR_AND_GOTO(context, err, done);
109 aluInitEffectPanning(slot);
111 tmpslots[cur] = slot;
112 effectslots[cur] = slot->id;
114 if(n > 0)
116 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
117 struct ALeffectslotArray *newarray = NULL;
118 ALsizei newcount = curarray->count + n;
119 ALCdevice *device;
121 newarray = al_calloc(DEF_ALIGN,
122 offsetof(struct ALeffectslotArray, slot[newcount])
124 newarray->count = newcount;
125 memcpy(newarray->slot, tmpslots, sizeof(ALeffectslot*)*n);
126 if(curarray)
127 memcpy(newarray->slot+n, curarray->slot, sizeof(ALeffectslot*)*curarray->count);
129 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
130 almemory_order_acq_rel);
131 device = context->Device;
132 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
133 althrd_yield();
134 al_free(newarray);
136 UnlockEffectSlotsWrite(context);
138 done:
139 al_free(tmpslots);
140 ALCcontext_DecRef(context);
143 AL_API ALvoid AL_APIENTRY alDeleteAuxiliaryEffectSlots(ALsizei n, const ALuint *effectslots)
145 ALCcontext *context;
146 ALeffectslot *slot;
147 ALsizei i;
149 context = GetContextRef();
150 if(!context) return;
152 LockEffectSlotsWrite(context);
153 if(!(n >= 0))
154 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
155 for(i = 0;i < n;i++)
157 if((slot=LookupEffectSlot(context, effectslots[i])) == NULL)
158 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
159 if(ReadRef(&slot->ref) != 0)
160 SET_ERROR_AND_GOTO(context, AL_INVALID_OPERATION, done);
163 // All effectslots are valid
164 if(n > 0)
166 struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
167 struct ALeffectslotArray *newarray = NULL;
168 ALsizei newcount = curarray->count - n;
169 ALCdevice *device;
170 ALsizei j, k;
172 assert(newcount >= 0);
173 newarray = al_calloc(DEF_ALIGN,
174 offsetof(struct ALeffectslotArray, slot[newcount])
176 newarray->count = newcount;
177 for(i = j = 0;i < newarray->count;)
179 slot = curarray->slot[j++];
180 for(k = 0;k < n;k++)
182 if(slot->id == effectslots[k])
183 break;
185 if(k == n)
186 newarray->slot[i++] = slot;
189 newarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray,
190 almemory_order_acq_rel);
191 device = context->Device;
192 while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1))
193 althrd_yield();
194 al_free(newarray);
197 for(i = 0;i < n;i++)
199 if((slot=RemoveEffectSlot(context, effectslots[i])) == NULL)
200 continue;
201 FreeThunkEntry(slot->id);
203 DeinitEffectSlot(slot);
205 memset(slot, 0, sizeof(*slot));
206 al_free(slot);
209 done:
210 UnlockEffectSlotsWrite(context);
211 ALCcontext_DecRef(context);
214 AL_API ALboolean AL_APIENTRY alIsAuxiliaryEffectSlot(ALuint effectslot)
216 ALCcontext *context;
217 ALboolean ret;
219 context = GetContextRef();
220 if(!context) return AL_FALSE;
222 LockEffectSlotsRead(context);
223 ret = (LookupEffectSlot(context, effectslot) ? AL_TRUE : AL_FALSE);
224 UnlockEffectSlotsRead(context);
226 ALCcontext_DecRef(context);
228 return ret;
231 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint value)
233 ALCdevice *device;
234 ALCcontext *context;
235 ALeffectslot *slot;
236 ALeffect *effect = NULL;
237 ALenum err;
239 context = GetContextRef();
240 if(!context) return;
242 WriteLock(&context->PropLock);
243 LockEffectSlotsRead(context);
244 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
245 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
246 switch(param)
248 case AL_EFFECTSLOT_EFFECT:
249 device = context->Device;
251 LockEffectsRead(device);
252 effect = (value ? LookupEffect(device, value) : NULL);
253 if(!(value == 0 || effect != NULL))
255 UnlockEffectsRead(device);
256 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
258 err = InitializeEffect(device, slot, effect);
259 UnlockEffectsRead(device);
261 if(err != AL_NO_ERROR)
262 SET_ERROR_AND_GOTO(context, err, done);
263 break;
265 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
266 if(!(value == AL_TRUE || value == AL_FALSE))
267 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
268 slot->AuxSendAuto = value;
269 break;
271 default:
272 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
274 DO_UPDATEPROPS();
276 done:
277 UnlockEffectSlotsRead(context);
278 WriteUnlock(&context->PropLock);
279 ALCcontext_DecRef(context);
282 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, const ALint *values)
284 ALCcontext *context;
286 switch(param)
288 case AL_EFFECTSLOT_EFFECT:
289 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
290 alAuxiliaryEffectSloti(effectslot, param, values[0]);
291 return;
294 context = GetContextRef();
295 if(!context) return;
297 LockEffectSlotsRead(context);
298 if(LookupEffectSlot(context, effectslot) == NULL)
299 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
300 switch(param)
302 default:
303 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
306 done:
307 UnlockEffectSlotsRead(context);
308 ALCcontext_DecRef(context);
311 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat value)
313 ALCcontext *context;
314 ALeffectslot *slot;
316 context = GetContextRef();
317 if(!context) return;
319 WriteLock(&context->PropLock);
320 LockEffectSlotsRead(context);
321 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
322 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
323 switch(param)
325 case AL_EFFECTSLOT_GAIN:
326 if(!(value >= 0.0f && value <= 1.0f))
327 SET_ERROR_AND_GOTO(context, AL_INVALID_VALUE, done);
328 slot->Gain = value;
329 break;
331 default:
332 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
334 DO_UPDATEPROPS();
336 done:
337 UnlockEffectSlotsRead(context);
338 WriteUnlock(&context->PropLock);
339 ALCcontext_DecRef(context);
342 AL_API ALvoid AL_APIENTRY alAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, const ALfloat *values)
344 ALCcontext *context;
346 switch(param)
348 case AL_EFFECTSLOT_GAIN:
349 alAuxiliaryEffectSlotf(effectslot, param, values[0]);
350 return;
353 context = GetContextRef();
354 if(!context) return;
356 LockEffectSlotsRead(context);
357 if(LookupEffectSlot(context, effectslot) == NULL)
358 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
359 switch(param)
361 default:
362 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
365 done:
366 UnlockEffectSlotsRead(context);
367 ALCcontext_DecRef(context);
370 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSloti(ALuint effectslot, ALenum param, ALint *value)
372 ALCcontext *context;
373 ALeffectslot *slot;
375 context = GetContextRef();
376 if(!context) return;
378 LockEffectSlotsRead(context);
379 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
380 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
381 switch(param)
383 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
384 *value = slot->AuxSendAuto;
385 break;
387 default:
388 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
391 done:
392 UnlockEffectSlotsRead(context);
393 ALCcontext_DecRef(context);
396 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotiv(ALuint effectslot, ALenum param, ALint *values)
398 ALCcontext *context;
400 switch(param)
402 case AL_EFFECTSLOT_EFFECT:
403 case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO:
404 alGetAuxiliaryEffectSloti(effectslot, param, values);
405 return;
408 context = GetContextRef();
409 if(!context) return;
411 LockEffectSlotsRead(context);
412 if(LookupEffectSlot(context, effectslot) == NULL)
413 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
414 switch(param)
416 default:
417 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
420 done:
421 UnlockEffectSlotsRead(context);
422 ALCcontext_DecRef(context);
425 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotf(ALuint effectslot, ALenum param, ALfloat *value)
427 ALCcontext *context;
428 ALeffectslot *slot;
430 context = GetContextRef();
431 if(!context) return;
433 LockEffectSlotsRead(context);
434 if((slot=LookupEffectSlot(context, effectslot)) == NULL)
435 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
436 switch(param)
438 case AL_EFFECTSLOT_GAIN:
439 *value = slot->Gain;
440 break;
442 default:
443 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
446 done:
447 UnlockEffectSlotsRead(context);
448 ALCcontext_DecRef(context);
451 AL_API ALvoid AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum param, ALfloat *values)
453 ALCcontext *context;
455 switch(param)
457 case AL_EFFECTSLOT_GAIN:
458 alGetAuxiliaryEffectSlotf(effectslot, param, values);
459 return;
462 context = GetContextRef();
463 if(!context) return;
465 LockEffectSlotsRead(context);
466 if(LookupEffectSlot(context, effectslot) == NULL)
467 SET_ERROR_AND_GOTO(context, AL_INVALID_NAME, done);
468 switch(param)
470 default:
471 SET_ERROR_AND_GOTO(context, AL_INVALID_ENUM, done);
474 done:
475 UnlockEffectSlotsRead(context);
476 ALCcontext_DecRef(context);
480 void InitEffectFactoryMap(void)
482 InitUIntMap(&EffectStateFactoryMap, ~0);
484 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_NULL, ALnullStateFactory_getFactory);
485 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EAXREVERB, ALreverbStateFactory_getFactory);
486 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_REVERB, ALreverbStateFactory_getFactory);
487 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_CHORUS, ALchorusStateFactory_getFactory);
488 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_COMPRESSOR, ALcompressorStateFactory_getFactory);
489 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DISTORTION, ALdistortionStateFactory_getFactory);
490 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_ECHO, ALechoStateFactory_getFactory);
491 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_EQUALIZER, ALequalizerStateFactory_getFactory);
492 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_FLANGER, ALflangerStateFactory_getFactory);
493 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_RING_MODULATOR, ALmodulatorStateFactory_getFactory);
494 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_DIALOGUE, ALdedicatedStateFactory_getFactory);
495 InsertUIntMapEntry(&EffectStateFactoryMap, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, ALdedicatedStateFactory_getFactory);
498 void DeinitEffectFactoryMap(void)
500 ResetUIntMap(&EffectStateFactoryMap);
504 ALenum InitializeEffect(ALCdevice *Device, ALeffectslot *EffectSlot, ALeffect *effect)
506 ALenum newtype = (effect ? effect->type : AL_EFFECT_NULL);
507 struct ALeffectslotProps *props;
508 ALeffectState *State;
510 if(newtype != EffectSlot->Effect.Type)
512 ALeffectStateFactory *factory;
513 FPUCtl oldMode;
515 factory = getFactoryByType(newtype);
516 if(!factory)
518 ERR("Failed to find factory for effect type 0x%04x\n", newtype);
519 return AL_INVALID_ENUM;
521 State = V0(factory,create)();
522 if(!State) return AL_OUT_OF_MEMORY;
524 SetMixerFPUMode(&oldMode);
525 almtx_lock(&Device->BackendLock);
526 State->OutBuffer = Device->Dry.Buffer;
527 State->OutChannels = Device->Dry.NumChannels;
528 if(V(State,deviceUpdate)(Device) == AL_FALSE)
530 almtx_unlock(&Device->BackendLock);
531 RestoreFPUMode(&oldMode);
532 ALeffectState_DecRef(State);
533 return AL_OUT_OF_MEMORY;
535 almtx_unlock(&Device->BackendLock);
536 RestoreFPUMode(&oldMode);
538 if(!effect)
540 EffectSlot->Effect.Type = AL_EFFECT_NULL;
541 memset(&EffectSlot->Effect.Props, 0, sizeof(EffectSlot->Effect.Props));
543 else
545 EffectSlot->Effect.Type = effect->type;
546 EffectSlot->Effect.Props = effect->Props;
549 ALeffectState_DecRef(EffectSlot->Effect.State);
550 EffectSlot->Effect.State = State;
552 else if(effect)
553 EffectSlot->Effect.Props = effect->Props;
555 /* Remove state references from old effect slot property updates. */
556 props = ATOMIC_LOAD_SEQ(&EffectSlot->FreeList);
557 while(props)
559 if(props->State)
560 ALeffectState_DecRef(props->State);
561 props->State = NULL;
562 props = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
565 return AL_NO_ERROR;
569 static void ALeffectState_IncRef(ALeffectState *state)
571 uint ref;
572 ref = IncrementRef(&state->Ref);
573 TRACEREF("%p increasing refcount to %u\n", state, ref);
576 static void ALeffectState_DecRef(ALeffectState *state)
578 uint ref;
579 ref = DecrementRef(&state->Ref);
580 TRACEREF("%p decreasing refcount to %u\n", state, ref);
581 if(ref == 0) DELETE_OBJ(state);
585 void ALeffectState_Construct(ALeffectState *state)
587 InitRef(&state->Ref, 1);
589 state->OutBuffer = NULL;
590 state->OutChannels = 0;
593 void ALeffectState_Destruct(ALeffectState *UNUSED(state))
598 ALenum InitEffectSlot(ALeffectslot *slot)
600 ALeffectStateFactory *factory;
602 slot->Effect.Type = AL_EFFECT_NULL;
604 factory = getFactoryByType(AL_EFFECT_NULL);
605 if(!(slot->Effect.State=V0(factory,create)()))
606 return AL_OUT_OF_MEMORY;
608 slot->Gain = 1.0;
609 slot->AuxSendAuto = AL_TRUE;
610 ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_relaxed);
611 InitRef(&slot->ref, 0);
613 ATOMIC_INIT(&slot->Update, NULL);
614 ATOMIC_INIT(&slot->FreeList, NULL);
616 slot->Params.Gain = 1.0f;
617 slot->Params.AuxSendAuto = AL_TRUE;
618 ALeffectState_IncRef(slot->Effect.State);
619 slot->Params.EffectState = slot->Effect.State;
620 slot->Params.RoomRolloff = 0.0f;
621 slot->Params.DecayTime = 0.0f;
622 slot->Params.AirAbsorptionGainHF = 1.0f;
624 return AL_NO_ERROR;
627 void DeinitEffectSlot(ALeffectslot *slot)
629 struct ALeffectslotProps *props;
630 size_t count = 0;
632 props = ATOMIC_LOAD_SEQ(&slot->Update);
633 if(props)
635 if(props->State) ALeffectState_DecRef(props->State);
636 TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", props);
637 al_free(props);
639 props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
640 while(props)
642 struct ALeffectslotProps *next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
643 if(props->State) ALeffectState_DecRef(props->State);
644 al_free(props);
645 props = next;
646 ++count;
648 TRACE("Freed "SZFMT" AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
650 ALeffectState_DecRef(slot->Effect.State);
651 if(slot->Params.EffectState)
652 ALeffectState_DecRef(slot->Params.EffectState);
655 void UpdateEffectSlotProps(ALeffectslot *slot)
657 struct ALeffectslotProps *props;
658 ALeffectState *oldstate;
660 /* Get an unused property container, or allocate a new one as needed. */
661 props = ATOMIC_LOAD(&slot->FreeList, almemory_order_relaxed);
662 if(!props)
663 props = al_calloc(16, sizeof(*props));
664 else
666 struct ALeffectslotProps *next;
667 do {
668 next = ATOMIC_LOAD(&props->next, almemory_order_relaxed);
669 } while(ATOMIC_COMPARE_EXCHANGE_PTR_WEAK(&slot->FreeList, &props, next,
670 almemory_order_seq_cst, almemory_order_acquire) == 0);
673 /* Copy in current property values. */
674 props->Gain = slot->Gain;
675 props->AuxSendAuto = slot->AuxSendAuto;
677 props->Type = slot->Effect.Type;
678 props->Props = slot->Effect.Props;
679 /* Swap out any stale effect state object there may be in the container, to
680 * delete it.
682 ALeffectState_IncRef(slot->Effect.State);
683 oldstate = props->State;
684 props->State = slot->Effect.State;
686 /* Set the new container for updating internal parameters. */
687 props = ATOMIC_EXCHANGE_PTR(&slot->Update, props, almemory_order_acq_rel);
688 if(props)
690 /* If there was an unused update container, put it back in the
691 * freelist.
693 ATOMIC_REPLACE_HEAD(struct ALeffectslotProps*, &slot->FreeList, props);
696 if(oldstate)
697 ALeffectState_DecRef(oldstate);
700 void UpdateAllEffectSlotProps(ALCcontext *context)
702 struct ALeffectslotArray *auxslots;
703 ALsizei i;
705 LockEffectSlotsRead(context);
706 auxslots = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire);
707 for(i = 0;i < auxslots->count;i++)
709 ALeffectslot *slot = auxslots->slot[i];
710 if(!ATOMIC_FLAG_TEST_AND_SET(&slot->PropsClean, almemory_order_acq_rel))
711 UpdateEffectSlotProps(slot);
713 UnlockEffectSlotsRead(context);
716 ALvoid ReleaseALAuxiliaryEffectSlots(ALCcontext *Context)
718 ALsizei pos;
719 for(pos = 0;pos < Context->EffectSlotMap.size;pos++)
721 ALeffectslot *temp = Context->EffectSlotMap.values[pos];
722 Context->EffectSlotMap.values[pos] = NULL;
724 DeinitEffectSlot(temp);
726 FreeThunkEntry(temp->id);
727 memset(temp, 0, sizeof(ALeffectslot));
728 al_free(temp);