From ac163c4a118cafebf39a32ea0ad8d8750e86c059 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 28 Jun 2021 09:00:37 +0100 Subject: [PATCH] Fix RT cache to avoid shutdown crashes --- include/wrapper/NonRealtime.hpp | 137 ++++++++++++--------------- include/wrapper/SCWorldAllocator.hpp | 28 +++--- 2 files changed, 73 insertions(+), 92 deletions(-) diff --git a/include/wrapper/NonRealtime.hpp b/include/wrapper/NonRealtime.hpp index f43ace6..7f490fe 100644 --- a/include/wrapper/NonRealtime.hpp +++ b/include/wrapper/NonRealtime.hpp @@ -49,16 +49,20 @@ class NonRealTime : public SCUnit public: using Cache = std::unordered_map; using RTCacheAllocator = - SCWorldAllocator>; - using RTCacheMirror = - std::unordered_map, - std::equal_to, RTCacheAllocator>; - using RTCachePointer = - std::unique_ptr>; - + SCWorldAllocator,Wrapper>; + struct RTCacheMirror: public std::unordered_map, + std::equal_to, RTCacheAllocator> + { + + ~RTCacheMirror() + { + 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 RTCachePointer mRTCache; - + static RTCacheMirror mRTCache; private: static bool isNull(WeakCacheEntryPointer const& weak) { @@ -66,20 +70,10 @@ private: !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) { - if (!mRTCache) return {}; - auto lookup = mRTCache->find(id); - return lookup == mRTCache->end() ? WeakCacheEntryPointer() : lookup->second; + auto lookup = mRTCache.find(id); + return lookup == mRTCache.end() ? WeakCacheEntryPointer() : lookup->second; } using RawCacheEntry = typename Cache::value_type; @@ -90,18 +84,17 @@ private: { FifoMsg msg; auto add = [](FifoMsg* m) { - if (!mRTCache) + + if(!mWorld) mWorld = m->mWorld; + else if (mWorld != m->mWorld) //internal server has restarted { - RTCacheMirror* tmp = rtalloc( - m->mWorld, RTCacheAllocator{m->mWorld, getInterfaceTable()}); - World* w = m->mWorld; - mRTCache = RTCachePointer(tmp, [w](RTCacheMirror* x) { - if (w->mRunning) getInterfaceTable()->fRTFree(w, x); - }); + mWorld = nullptr; + mRTCache.clear(); + mWorld = m->mWorld; } - + RawCacheEntry* r = static_cast(m->mData); - auto res = mRTCache->emplace(r->first, r->second); + mRTCache.emplace(r->first, r->second); }; msg.Set(w, add, nullptr, &r); auto ft = Wrapper::getInterfaceTable(); @@ -122,20 +115,38 @@ private: FifoMsg msg; 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(m->mData); - mRTCache->erase(*id); + mRTCache.erase(*id); }; auto cleanup = [](FifoMsg* m) { delete static_cast(m->mData); }; msg.Set(world, remove, cleanup, data); + auto ft = Wrapper::getInterfaceTable(); + ft->fSendMsgToRT(world,msg); } }; 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) { @@ -325,13 +336,6 @@ private: } }; - -// struct UnitInfo -// { -// int mSynthIndex; -// int mNodeID{0}; -// }; - struct CommandProcess : public NRTCommand { CommandProcess(World* world, sc_msg_iter* args, void* replyAddr) @@ -429,7 +433,7 @@ private: } // Only for blocking execution - bool stage4(World* w) // nrt + bool stage4(World*) // nrt { if (auto ptr = get(NRTCommand::mID).lock()) { @@ -519,7 +523,7 @@ private: return true; } - bool stage4(World* w) // nrt + bool stage4(World*) // nrt { if (auto ptr = get(NRTCommand::mID).lock()) { @@ -537,39 +541,6 @@ private: 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(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; WeakCacheEntryPointer mRecord; }; @@ -854,7 +825,6 @@ private: void next(int) { - if (!mRTCache) return; if (isNull(mRecord)) { mRecord = rtget(mID); }; if (0 == mCounter++) @@ -1026,7 +996,6 @@ private: void init() { mInit = false; - if (!mRTCache) return; mInst = rtget(mID); if (auto ptr = mInst.lock()) { @@ -1132,8 +1101,17 @@ public: void init(){}; + + static World* getWorld() + { + return mWorld; + } private: + + + static World* mWorld; + static Result validateParameters(ParamSetType& p) { auto results = p.constrainParameterValues(); @@ -1173,12 +1151,15 @@ private: Result mResult; }; +template +World* NonRealTime::mWorld{nullptr}; + template typename NonRealTime::Cache NonRealTime::mCache{}; template -typename NonRealTime::RTCachePointer +typename NonRealTime::RTCacheMirror NonRealTime::mRTCache{}; } // namespace impl diff --git a/include/wrapper/SCWorldAllocator.hpp b/include/wrapper/SCWorldAllocator.hpp index a53d1fd..d7310cf 100644 --- a/include/wrapper/SCWorldAllocator.hpp +++ b/include/wrapper/SCWorldAllocator.hpp @@ -16,24 +16,20 @@ namespace fluid { -template +template class SCWorldAllocator { - World* mWorld{nullptr}; - InterfaceTable* mInterface{nullptr}; - public: using propagate_on_container_move_assignment = std::true_type; using value_type = T; - template + template friend class SCWorldAllocator; - SCWorldAllocator(World* w, InterfaceTable* ft) : mWorld{w}, mInterface{ft} {} + SCWorldAllocator() = default; - template - SCWorldAllocator(const SCWorldAllocator& other) noexcept - : mWorld{other.mWorld}, mInterface{other.mInterface} + template + SCWorldAllocator(const SCWorldAllocator&) noexcept {} T* allocate(std::size_t n) @@ -41,17 +37,21 @@ public: if (n > std::numeric_limits::max() / sizeof(T)) throw std::bad_array_new_length(); - if (mWorld && mInterface) - if (auto p = static_cast(mInterface->fRTAlloc(mWorld, n * sizeof(T)))) + World* world = Wrapper::getWorld(); + InterfaceTable* interface = Wrapper::getInterfaceTable(); + + if (world && interface) + if (auto p = static_cast(interface->fRTAlloc(world, n * sizeof(T)))) return p; 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); - mInterface->fRTFree(mWorld, p); + World* world = Wrapper::getWorld(); + InterfaceTable* interface = Wrapper::getInterfaceTable(); + if(world && interface) interface->fRTFree(world, p); } }; } // namespace fluid