Properly update the Super Stereo width
[openal-soft.git] / core / context.cpp
blob39fd85221535f8a17a1d94eb4f3cfc06c4a35c4e
2 #include "config.h"
4 #include <memory>
6 #include "async_event.h"
7 #include "context.h"
8 #include "device.h"
9 #include "effectslot.h"
10 #include "logging.h"
11 #include "ringbuffer.h"
12 #include "voice.h"
13 #include "voice_change.h"
16 ContextBase::ContextBase(DeviceBase *device) : mDevice{device}
17 { }
19 ContextBase::~ContextBase()
21 size_t count{0};
22 ContextProps *cprops{mParams.ContextUpdate.exchange(nullptr, std::memory_order_relaxed)};
23 if(cprops)
25 ++count;
26 delete cprops;
28 cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire);
29 while(cprops)
31 std::unique_ptr<ContextProps> old{cprops};
32 cprops = old->next.load(std::memory_order_relaxed);
33 ++count;
35 TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s");
37 count = 0;
38 EffectSlotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)};
39 while(eprops)
41 std::unique_ptr<EffectSlotProps> old{eprops};
42 eprops = old->next.load(std::memory_order_relaxed);
43 ++count;
45 TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s");
47 if(EffectSlotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)})
49 al::destroy_n(curarray->end(), curarray->size());
50 delete curarray;
53 delete mVoices.exchange(nullptr, std::memory_order_relaxed);
55 if(mAsyncEvents)
57 count = 0;
58 auto evt_vec = mAsyncEvents->getReadVector();
59 if(evt_vec.first.len > 0)
61 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.first.buf), evt_vec.first.len);
62 count += evt_vec.first.len;
64 if(evt_vec.second.len > 0)
66 al::destroy_n(reinterpret_cast<AsyncEvent*>(evt_vec.second.buf), evt_vec.second.len);
67 count += evt_vec.second.len;
69 if(count > 0)
70 TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s");
71 mAsyncEvents->readAdvance(count);
76 void ContextBase::allocVoiceChanges()
78 constexpr size_t clustersize{128};
80 VoiceChangeCluster cluster{std::make_unique<VoiceChange[]>(clustersize)};
81 for(size_t i{1};i < clustersize;++i)
82 cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed);
83 cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed);
85 mVoiceChangeClusters.emplace_back(std::move(cluster));
86 mVoiceChangeTail = mVoiceChangeClusters.back().get();
89 void ContextBase::allocVoiceProps()
91 constexpr size_t clustersize{32};
93 TRACE("Increasing allocated voice properties to %zu\n",
94 (mVoicePropClusters.size()+1) * clustersize);
96 VoicePropsCluster cluster{std::make_unique<VoicePropsItem[]>(clustersize)};
97 for(size_t i{1};i < clustersize;++i)
98 cluster[i-1].next.store(std::addressof(cluster[i]), std::memory_order_relaxed);
99 mVoicePropClusters.emplace_back(std::move(cluster));
101 VoicePropsItem *oldhead{mFreeVoiceProps.load(std::memory_order_acquire)};
102 do {
103 mVoicePropClusters.back()[clustersize-1].next.store(oldhead, std::memory_order_relaxed);
104 } while(mFreeVoiceProps.compare_exchange_weak(oldhead, mVoicePropClusters.back().get(),
105 std::memory_order_acq_rel, std::memory_order_acquire) == false);
108 void ContextBase::allocVoices(size_t addcount)
110 constexpr size_t clustersize{32};
111 /* Convert element count to cluster count. */
112 addcount = (addcount+(clustersize-1)) / clustersize;
114 if(addcount >= std::numeric_limits<int>::max()/clustersize - mVoiceClusters.size())
115 throw std::runtime_error{"Allocating too many voices"};
116 const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize};
117 TRACE("Increasing allocated voices to %zu\n", totalcount);
119 auto newarray = VoiceArray::Create(totalcount);
120 while(addcount)
122 mVoiceClusters.emplace_back(std::make_unique<Voice[]>(clustersize));
123 --addcount;
126 auto voice_iter = newarray->begin();
127 for(VoiceCluster &cluster : mVoiceClusters)
129 for(size_t i{0};i < clustersize;++i)
130 *(voice_iter++) = &cluster[i];
133 if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel))
135 mDevice->waitForMix();
136 delete oldvoices;