6 #include "async_event.h"
9 #include "effectslot.h"
11 #include "ringbuffer.h"
13 #include "voice_change.h"
16 ContextBase::ContextBase(DeviceBase
*device
) : mDevice
{device
}
19 ContextBase::~ContextBase()
22 ContextProps
*cprops
{mParams
.ContextUpdate
.exchange(nullptr, std::memory_order_relaxed
)};
28 cprops
= mFreeContextProps
.exchange(nullptr, std::memory_order_acquire
);
31 std::unique_ptr
<ContextProps
> old
{cprops
};
32 cprops
= old
->next
.load(std::memory_order_relaxed
);
35 TRACE("Freed %zu context property object%s\n", count
, (count
==1)?"":"s");
38 EffectSlotProps
*eprops
{mFreeEffectslotProps
.exchange(nullptr, std::memory_order_acquire
)};
41 std::unique_ptr
<EffectSlotProps
> old
{eprops
};
42 eprops
= old
->next
.load(std::memory_order_relaxed
);
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());
53 delete mVoices
.exchange(nullptr, std::memory_order_relaxed
);
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
;
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
)};
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
);
122 mVoiceClusters
.emplace_back(std::make_unique
<Voice
[]>(clustersize
));
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();