Fix RT cache to avoid shutdown crashes

nix
Owen Green 5 years ago
parent 714c206296
commit ac163c4a11

@ -49,16 +49,20 @@ class NonRealTime : public SCUnit
public: public:
using Cache = std::unordered_map<index, CacheEntryPointer>; using Cache = std::unordered_map<index, CacheEntryPointer>;
using RTCacheAllocator = using RTCacheAllocator =
SCWorldAllocator<std::pair<const index, WeakCacheEntryPointer>>; SCWorldAllocator<std::pair<const index, WeakCacheEntryPointer>,Wrapper>;
using RTCacheMirror = struct RTCacheMirror: public std::unordered_map<index, WeakCacheEntryPointer, std::hash<index>,
std::unordered_map<index, WeakCacheEntryPointer, std::hash<index>, std::equal_to<index>, RTCacheAllocator>
std::equal_to<index>, RTCacheAllocator>; {
using RTCachePointer =
std::unique_ptr<RTCacheMirror, std::function<void(RTCacheMirror*)>>;
static Cache mCache; ~RTCacheMirror()
static RTCachePointer mRTCache; {
if(mWorld) mWorld = nullptr; //if we get as far as destroying this, then the world is gone and we should accept that and move on
}
};
static Cache mCache;
static RTCacheMirror mRTCache;
private: private:
static bool isNull(WeakCacheEntryPointer const& weak) static bool isNull(WeakCacheEntryPointer const& weak)
{ {
@ -66,20 +70,10 @@ private:
!WeakCacheEntryPointer{}.owner_before(weak); !WeakCacheEntryPointer{}.owner_before(weak);
} }
// shouldn't be called without at least *thinking* about getting spin lock
// first
static WeakCacheEntryPointer unsafeGet(index id)
{
auto lookup = mCache.find(id);
return lookup == mCache.end() ? WeakCacheEntryPointer() : lookup->second;
}
static WeakCacheEntryPointer rtget(index id) static WeakCacheEntryPointer rtget(index id)
{ {
if (!mRTCache) return {}; auto lookup = mRTCache.find(id);
auto lookup = mRTCache->find(id); return lookup == mRTCache.end() ? WeakCacheEntryPointer() : lookup->second;
return lookup == mRTCache->end() ? WeakCacheEntryPointer() : lookup->second;
} }
using RawCacheEntry = typename Cache::value_type; using RawCacheEntry = typename Cache::value_type;
@ -90,18 +84,17 @@ private:
{ {
FifoMsg msg; FifoMsg msg;
auto add = [](FifoMsg* m) { auto add = [](FifoMsg* m) {
if (!mRTCache)
if(!mWorld) mWorld = m->mWorld;
else if (mWorld != m->mWorld) //internal server has restarted
{ {
RTCacheMirror* tmp = rtalloc<RTCacheMirror>( mWorld = nullptr;
m->mWorld, RTCacheAllocator{m->mWorld, getInterfaceTable()}); mRTCache.clear();
World* w = m->mWorld; mWorld = m->mWorld;
mRTCache = RTCachePointer(tmp, [w](RTCacheMirror* x) {
if (w->mRunning) getInterfaceTable()->fRTFree(w, x);
});
} }
RawCacheEntry* r = static_cast<RawCacheEntry*>(m->mData); RawCacheEntry* r = static_cast<RawCacheEntry*>(m->mData);
auto res = mRTCache->emplace(r->first, r->second); mRTCache.emplace(r->first, r->second);
}; };
msg.Set(w, add, nullptr, &r); msg.Set(w, add, nullptr, &r);
auto ft = Wrapper::getInterfaceTable(); auto ft = Wrapper::getInterfaceTable();
@ -122,20 +115,38 @@ private:
FifoMsg msg; FifoMsg msg;
auto remove = [](FifoMsg* m) { auto remove = [](FifoMsg* m) {
if (!mRTCache) return;
if(!mWorld)
{
mRTCache.clear();
mWorld = m->mWorld; //
}
else if (mWorld != m->mWorld) //internal server has restarted
{
mWorld = nullptr;
mRTCache.clear();
mWorld = m->mWorld;
}
int* id = static_cast<int*>(m->mData); int* id = static_cast<int*>(m->mData);
mRTCache->erase(*id); mRTCache.erase(*id);
}; };
auto cleanup = [](FifoMsg* m) { delete static_cast<index*>(m->mData); }; auto cleanup = [](FifoMsg* m) { delete static_cast<index*>(m->mData); };
msg.Set(world, remove, cleanup, data); msg.Set(world, remove, cleanup, data);
auto ft = Wrapper::getInterfaceTable();
ft->fSendMsgToRT(world,msg);
} }
}; };
public: public:
static WeakCacheEntryPointer get(index id) { return unsafeGet(id); } static WeakCacheEntryPointer get(index id)
{
auto lookup = mCache.find(id);
return lookup == mCache.end() ? WeakCacheEntryPointer() : lookup->second;
}
static WeakCacheEntryPointer add(World* world, index id, const Params& params) static WeakCacheEntryPointer add(World* world, index id, const Params& params)
{ {
@ -325,13 +336,6 @@ private:
} }
}; };
// struct UnitInfo
// {
// int mSynthIndex;
// int mNodeID{0};
// };
struct CommandProcess : public NRTCommand struct CommandProcess : public NRTCommand
{ {
CommandProcess(World* world, sc_msg_iter* args, void* replyAddr) CommandProcess(World* world, sc_msg_iter* args, void* replyAddr)
@ -429,7 +433,7 @@ private:
} }
// Only for blocking execution // Only for blocking execution
bool stage4(World* w) // nrt bool stage4(World*) // nrt
{ {
if (auto ptr = get(NRTCommand::mID).lock()) if (auto ptr = get(NRTCommand::mID).lock())
{ {
@ -519,7 +523,7 @@ private:
return true; return true;
} }
bool stage4(World* w) // nrt bool stage4(World*) // nrt
{ {
if (auto ptr = get(NRTCommand::mID).lock()) if (auto ptr = get(NRTCommand::mID).lock())
{ {
@ -537,39 +541,6 @@ private:
return false; return false;
} }
// void notifyUnit(World* w)
// {
// if(mUnitInfo.mNodeID > 0)
// {
// auto ft = Wrapper::getInterfaceTable();
//
// NRTDoneCount++;
// FifoMsg msg;
//
// auto updateUnitDone = [](FifoMsg* m)
// {
// UnitInfo* info = static_cast<UnitInfo*>(m->mData);
//
// auto ft = Wrapper::getInterfaceTable();
// Graph* g = ft->fGetGraph(m->mWorld,info->mNodeID);
// if(g)
// {
// Unit* u = g->mUnits[info->mSynthIndex];
// if(u)
// {
// RTDoneCount++;
// u->mDone = true;
// }
// }
// };
//
// msg.Set(w, updateUnitDone, nullptr, &mUnitInfo);
// ft->fSendMsgToRT(w,msg);
// }
// }
bool mSuccess; bool mSuccess;
WeakCacheEntryPointer mRecord; WeakCacheEntryPointer mRecord;
}; };
@ -854,7 +825,6 @@ private:
void next(int) void next(int)
{ {
if (!mRTCache) return;
if (isNull(mRecord)) { mRecord = rtget(mID); }; if (isNull(mRecord)) { mRecord = rtget(mID); };
if (0 == mCounter++) if (0 == mCounter++)
@ -1026,7 +996,6 @@ private:
void init() void init()
{ {
mInit = false; mInit = false;
if (!mRTCache) return;
mInst = rtget(mID); mInst = rtget(mID);
if (auto ptr = mInst.lock()) if (auto ptr = mInst.lock())
{ {
@ -1133,7 +1102,16 @@ public:
void init(){}; void init(){};
static World* getWorld()
{
return mWorld;
}
private: private:
static World* mWorld;
static Result validateParameters(ParamSetType& p) static Result validateParameters(ParamSetType& p)
{ {
auto results = p.constrainParameterValues(); auto results = p.constrainParameterValues();
@ -1173,12 +1151,15 @@ private:
Result mResult; Result mResult;
}; };
template <typename Client, typename Wrapper>
World* NonRealTime<Client,Wrapper>::mWorld{nullptr};
template <typename Client, typename Wrapper> template <typename Client, typename Wrapper>
typename NonRealTime<Client, Wrapper>::Cache typename NonRealTime<Client, Wrapper>::Cache
NonRealTime<Client, Wrapper>::mCache{}; NonRealTime<Client, Wrapper>::mCache{};
template <typename Client, typename Wrapper> template <typename Client, typename Wrapper>
typename NonRealTime<Client, Wrapper>::RTCachePointer typename NonRealTime<Client, Wrapper>::RTCacheMirror
NonRealTime<Client, Wrapper>::mRTCache{}; NonRealTime<Client, Wrapper>::mRTCache{};
} // namespace impl } // namespace impl

@ -16,24 +16,20 @@
namespace fluid { namespace fluid {
template <typename T> template <typename T, typename Wrapper>
class SCWorldAllocator class SCWorldAllocator
{ {
World* mWorld{nullptr};
InterfaceTable* mInterface{nullptr};
public: public:
using propagate_on_container_move_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type;
using value_type = T; using value_type = T;
template <typename U> template <typename U, typename W>
friend class SCWorldAllocator; friend class SCWorldAllocator;
SCWorldAllocator(World* w, InterfaceTable* ft) : mWorld{w}, mInterface{ft} {} SCWorldAllocator() = default;
template <typename U> template <typename U,typename W>
SCWorldAllocator(const SCWorldAllocator<U>& other) noexcept SCWorldAllocator(const SCWorldAllocator<U,W>&) noexcept
: mWorld{other.mWorld}, mInterface{other.mInterface}
{} {}
T* allocate(std::size_t n) T* allocate(std::size_t n)
@ -41,17 +37,21 @@ public:
if (n > std::numeric_limits<std::size_t>::max() / sizeof(T)) if (n > std::numeric_limits<std::size_t>::max() / sizeof(T))
throw std::bad_array_new_length(); throw std::bad_array_new_length();
if (mWorld && mInterface) World* world = Wrapper::getWorld();
if (auto p = static_cast<T*>(mInterface->fRTAlloc(mWorld, n * sizeof(T)))) InterfaceTable* interface = Wrapper::getInterfaceTable();
if (world && interface)
if (auto p = static_cast<T*>(interface->fRTAlloc(world, n * sizeof(T))))
return p; return p;
throw std::bad_alloc(); throw std::bad_alloc();
} }
void deallocate(T* p, std::size_t n) noexcept void deallocate(T* p, std::size_t /*n*/) noexcept
{ {
assert(mWorld && mInterface); World* world = Wrapper::getWorld();
mInterface->fRTFree(mWorld, p); InterfaceTable* interface = Wrapper::getInterfaceTable();
if(world && interface) interface->fRTFree(world, p);
} }
}; };
} // namespace fluid } // namespace fluid

Loading…
Cancel
Save