How do I deallocate any heap allocated userdata I set?
// bank used here as an example, but this could be anything
Bank* bank;
UserData* userData = new UserData;
// how do I free this?
bank->setUserData(userData);
All the examples I can find involve setting userdata to a value on the stack, nothing that uses new or malloc.
Hello, if you don’t have access to userData when freeing, you could retrieve the pointer with Bank::getUserData and call delete on it after casting it back to UserData *.
Something like this should work:
UserData *data;
FMOD_RESULT result = bank->getUserData((void **)&data);
if (result == FMOD_OK)
{
delete data;
}
else
{
// error
}
How do I know when a bank (or any other object with associated userdata) is about to be released, so I can also deallocate the userdata associated with it?
You could add a callback with FMOD::System::setCallback that checks for the callback type FMOD_STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD.
This callback passes the handle of the bank where you can get and deallocate the user data.
Unless there’s a strong reason not to, I’d probably just make a class that wraps the bank + userdata and handles unloading/deallocating without needing callbacks.
Besides what @aishi1 has already mentioned with regards to knowing when to release user data - to safely deallocate user data, set the user data to nullptr or equivalent with setUserData(), and then free your memory. User data isn’t touched by FMOD, except for when using FMOD_STUDIO_BANK_INFO, where a non-zero userdatalength will cause FMOD to copy the data from your pointer to internal memory.
So far I’ve gotten this strategy to (mostly) work, until I tried deallocating userdata attached to event descriptions. My code roughly looks like this:
FMOD_RESULT deallocate_bank(Bank bank) {
void* userdata;
bank.get_userdata(&userdata);
// deallocate the userdata if it is not null
if userdata {
delete (InternalBankUserdata*) userdata;
bank.set_userdata(NULL);
}
std::vector<EventDescription> list = get_event_list(bank);
for (EventDescription event : list) {
event.get_userdata(&userdata);
// deallocate the userdata if it is not null
if userdata {
delete (InternalEventUserdata*) userdata;
event.set_userdata(NULL);
}
}
return FMOD_OK;
}
deallocate_bank is called from a system callback, per aishi1’s solution.
My get_event_list function uses Bank::get_event_count and Bank::get_event_list to get the list of all event descriptions. When I call either function though, they just return FMOD_ERR_NOTREADY. What should I do?
At the point where FMOD_STUDIO_SYSTEM_CALLBACK_BANK_UNLOAD fires, the bank has already been unloaded, and all resources freed. As a result, you won’t be able to iterate over the bank’s event descriptions from the callback - you’ll need to do that before unloading the bank.