static void RemoveActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *context) { struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire); struct ALeffectslotArray *newarray = NULL; ALCdevice *device = context->Device; ALsizei i, j; /* Don't shrink the allocated array size since we don't know how many (if * any) of the effect slots to remove are in the array. */ newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, curarray->count)); newarray->count = 0; for(i = 0;i < curarray->count;i++) { /* Insert this slot into the new array only if it's not one to remove. */ ALeffectslot *slot = curarray->slot[i]; for(j = count;j != 0;) { if(slot->id == slotids[--j]) goto skip_ins; } newarray->slot[newarray->count++] = slot; skip_ins: ; } /* TODO: Could reallocate newarray now that we know it's needed size. */ curarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, almemory_order_acq_rel); while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1)) althrd_yield(); al_free(curarray); }
int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) { int ret; #ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK ret = pthread_mutex_timedlock(mtx, ts); switch(ret) { case 0: return althrd_success; case ETIMEDOUT: return althrd_timedout; case EBUSY: return althrd_busy; } return althrd_error; #else if(!mtx || !ts) return althrd_error; while((ret=almtx_trylock(mtx)) == althrd_busy) { struct timespec now; if(ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000 || altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) return althrd_error; if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && now.tv_nsec >= ts->tv_nsec)) return althrd_timedout; althrd_yield(); } return ret; #endif }
void alcall_once(alonce_flag *once, void (*callback)(void)) { LONG ret; while((ret=InterlockedExchange(once, 1)) == 1) althrd_yield(); if(ret == 0) (*callback)(); InterlockedExchange(once, 2); }
static void AddActiveEffectSlots(const ALuint *slotids, ALsizei count, ALCcontext *context) { struct ALeffectslotArray *curarray = ATOMIC_LOAD(&context->ActiveAuxSlots, almemory_order_acquire); struct ALeffectslotArray *newarray = NULL; ALsizei newcount = curarray->count + count; ALCdevice *device = context->Device; ALsizei i, j; /* Insert the new effect slots into the head of the array, followed by the * existing ones. */ newarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount)); newarray->count = newcount; for(i = 0;i < count;i++) newarray->slot[i] = LookupEffectSlot(context, slotids[i]); for(j = 0;i < newcount;) newarray->slot[i++] = curarray->slot[j++]; /* Remove any duplicates (first instance of each will be kept). */ for(i = 1;i < newcount;i++) { for(j = i;j != 0;) { if(UNLIKELY(newarray->slot[i] == newarray->slot[--j])) { newcount--; for(j = i;j < newcount;j++) newarray->slot[j] = newarray->slot[j+1]; i--; break; } } } /* Reallocate newarray if the new size ended up smaller from duplicate * removal. */ if(UNLIKELY(newcount < newarray->count)) { struct ALeffectslotArray *tmpnewarray = al_calloc(DEF_ALIGN, FAM_SIZE(struct ALeffectslotArray, slot, newcount)); memcpy(tmpnewarray, newarray, FAM_SIZE(struct ALeffectslotArray, slot, newcount)); al_free(newarray); newarray = tmpnewarray; newarray->count = newcount; } curarray = ATOMIC_EXCHANGE_PTR(&context->ActiveAuxSlots, newarray, almemory_order_acq_rel); while((ATOMIC_LOAD(&device->MixCount, almemory_order_acquire)&1)) althrd_yield(); al_free(curarray); }
static void RemoveEffectSlotList(ALCcontext *context, const ALeffectslot *slot) { ALCdevice *device = context->Device; const ALeffectslot *root, *next; root = slot; next = ATOMIC_LOAD(&slot->next); if(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALeffectslot*, &context->ActiveAuxSlotList, &root, next)) { const ALeffectslot *cur; do { cur = root; root = slot; } while(!ATOMIC_COMPARE_EXCHANGE_STRONG(ALeffectslot*, &cur->next, &root, next)); } /* Wait for any mix that may be using these effect slots to finish. */ while((ReadRef(&device->MixCount)&1) != 0) althrd_yield(); }
int almtx_timedlock(almtx_t *mtx, const struct timespec *ts) { int ret; if(!mtx || !ts) return althrd_error; while((ret=almtx_trylock(mtx)) == althrd_busy) { struct timespec now; if(ts->tv_sec < 0 || ts->tv_nsec < 0 || ts->tv_nsec >= 1000000000 || altimespec_get(&now, AL_TIME_UTC) != AL_TIME_UTC) return althrd_error; if(now.tv_sec > ts->tv_sec || (now.tv_sec == ts->tv_sec && now.tv_nsec >= ts->tv_nsec)) return althrd_timedout; althrd_yield(); } return ret; }
static void opensl_stop_playback(ALCdevice *Device) { osl_data *data = Device->ExtraData; SLPlayItf player; SLAndroidSimpleBufferQueueItf bufferQueue; SLresult result; result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_PLAY, &player); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { result = VCALL(player,SetPlayState)(SL_PLAYSTATE_STOPPED); PRINTERR(result, "player->SetPlayState"); } result = VCALL(data->bufferQueueObject,GetInterface)(SL_IID_BUFFERQUEUE, &bufferQueue); PRINTERR(result, "bufferQueue->GetInterface"); if(SL_RESULT_SUCCESS == result) { result = VCALL0(bufferQueue,Clear)(); PRINTERR(result, "bufferQueue->Clear"); } if(SL_RESULT_SUCCESS == result) { SLAndroidSimpleBufferQueueState state; do { althrd_yield(); result = VCALL(bufferQueue,GetState)(&state); } while(SL_RESULT_SUCCESS == result && state.count > 0); PRINTERR(result, "bufferQueue->GetState"); } free(data->buffer); data->buffer = NULL; data->bufferSize = 0; }