EXPORT_C void RMemSpySession::GetThreadInfoItemsL( RArray<CMemSpyApiThreadInfoItem*> &aInfoItems, TThreadId aId, TMemSpyThreadInfoItemType aType ) { TPckgBuf<TThreadId> id( aId ); TPckgBuf<TMemSpyThreadInfoItemType> type( aType ); TPckgBuf<TInt> count; TInt error = SendReceive( EMemSpyClientServerOpGetThreadInfoItemsCount, TIpcArgs( &id, &type, &count ) ); TInt itemCount = count(); if( error == KErrNone ) { if( itemCount == 0 ) { aInfoItems.Reset(); } else { HBufC8* buffer = HBufC8::NewLC( itemCount * sizeof(TMemSpyThreadInfoItemData) ); TPtr8 bufferPtr(buffer->Des()); TPckgBuf<TInt> requestedCount( itemCount ); TIpcArgs args( &requestedCount, &id, &type, &bufferPtr ); TInt error = SendReceive( EMemSpyClientServerOpGetThreadInfoItems, args ); // TODO check error aInfoItems.Reset(); for(TInt i=0, offset = 0; i < itemCount; i++, offset+=sizeof(TMemSpyThreadInfoItemData)) { TPckgBuf<TMemSpyThreadInfoItemData> data; data.Copy(bufferPtr.Ptr()+offset, sizeof(TMemSpyThreadInfoItemData)); aInfoItems.AppendL(CMemSpyApiThreadInfoItem::NewLC(data())); } CleanupStack::Pop(aInfoItems.Count()); CleanupStack::PopAndDestroy(buffer); } } User::LeaveIfError(error); }
namespace Magnum { namespace Test { struct ResourceManagerTest: TestSuite::Tester { explicit ResourceManagerTest(); void state(); void stateFallback(); void stateDisallowed(); void basic(); void residentPolicy(); void referenceCountedPolicy(); void manualPolicy(); void defaults(); void clear(); void clearWhileReferenced(); void loader(); }; struct Data { static std::size_t count; explicit Data() { ++count; } ~Data() { --count; } }; typedef Magnum::ResourceManager<Int, Data> ResourceManager; size_t Data::count = 0; ResourceManagerTest::ResourceManagerTest() { addTests({&ResourceManagerTest::state, &ResourceManagerTest::stateFallback, &ResourceManagerTest::stateDisallowed, &ResourceManagerTest::basic, &ResourceManagerTest::residentPolicy, &ResourceManagerTest::referenceCountedPolicy, &ResourceManagerTest::manualPolicy, &ResourceManagerTest::defaults, &ResourceManagerTest::clear, &ResourceManagerTest::clearWhileReferenced, &ResourceManagerTest::loader}); } void ResourceManagerTest::state() { ResourceManager rm; Resource<Data> data = rm.get<Data>("data"); CORRADE_VERIFY(!data); CORRADE_COMPARE(data.state(), ResourceState::NotLoaded); CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoaded); rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident); CORRADE_VERIFY(!data); CORRADE_COMPARE(data.state(), ResourceState::Loading); CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::Loading); rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident); CORRADE_VERIFY(!data); CORRADE_COMPARE(data.state(), ResourceState::NotFound); CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFound); /* Nothing happened at all */ CORRADE_COMPARE(Data::count, 0); } void ResourceManagerTest::stateFallback() { { ResourceManager rm; rm.setFallback(new Data); Resource<Data> data = rm.get<Data>("data"); CORRADE_VERIFY(data); CORRADE_COMPARE(data.state(), ResourceState::NotLoadedFallback); CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotLoadedFallback); rm.set<Data>("data", nullptr, ResourceDataState::Loading, ResourcePolicy::Resident); CORRADE_VERIFY(data); CORRADE_COMPARE(data.state(), ResourceState::LoadingFallback); CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::LoadingFallback); rm.set<Data>("data", nullptr, ResourceDataState::NotFound, ResourcePolicy::Resident); CORRADE_VERIFY(data); CORRADE_COMPARE(data.state(), ResourceState::NotFoundFallback); CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::NotFoundFallback); /* Only fallback is here */ CORRADE_COMPARE(Data::count, 1); } /* Fallback gets destroyed */ CORRADE_COMPARE(Data::count, 0); } void ResourceManagerTest::stateDisallowed() { ResourceManager rm; std::ostringstream out; Error::setOutput(&out); rm.set("data", Data(), ResourceDataState::Loading, ResourcePolicy::Resident); CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n"); out.str({}); rm.set<Data>("data", nullptr, ResourceDataState::Final, ResourcePolicy::Resident); CORRADE_COMPARE(out.str(), "ResourceManager::set(): data should be null if and only if state is NotFound or Loading\n"); } void ResourceManagerTest::basic() { ResourceManager rm; /* One mutable, one final */ ResourceKey questionKey("the-question"); ResourceKey answerKey("the-answer"); rm.set(questionKey, 10, ResourceDataState::Mutable, ResourcePolicy::Resident); rm.set(answerKey, 42, ResourceDataState::Final, ResourcePolicy::Resident); Resource<Int> theQuestion = rm.get<Int>(questionKey); Resource<Int> theAnswer = rm.get<Int>(answerKey); /* Check basic functionality */ CORRADE_COMPARE(theQuestion.state(), ResourceState::Mutable); CORRADE_COMPARE(theAnswer.state(), ResourceState::Final); CORRADE_COMPARE(*theQuestion, 10); CORRADE_COMPARE(*theAnswer, 42); CORRADE_COMPARE(rm.count<Int>(), 2); /* Cannot change already final resource */ std::ostringstream out; Error::setOutput(&out); rm.set(answerKey, 43, ResourceDataState::Mutable, ResourcePolicy::Resident); CORRADE_COMPARE(*theAnswer, 42); CORRADE_COMPARE(out.str(), "ResourceManager::set(): cannot change already final resource " + answerKey.hexString() + '\n'); /* But non-final can be changed */ rm.set(questionKey, 20, ResourceDataState::Final, ResourcePolicy::Resident); CORRADE_COMPARE(theQuestion.state(), ResourceState::Final); CORRADE_COMPARE(*theQuestion, 20); } void ResourceManagerTest::residentPolicy() { ResourceManager* rm = new ResourceManager; rm->set("blah", new Data, ResourceDataState::Mutable, ResourcePolicy::Resident); CORRADE_COMPARE(Data::count, 1); rm->free(); CORRADE_COMPARE(Data::count, 1); delete rm; CORRADE_COMPARE(Data::count, 0); } void ResourceManagerTest::referenceCountedPolicy() { ResourceManager rm; ResourceKey dataRefCountKey("dataRefCount"); /* Resource is deleted after all references are removed */ rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted); CORRADE_COMPARE(rm.count<Data>(), 1); { Resource<Data> data = rm.get<Data>(dataRefCountKey); CORRADE_COMPARE(data.state(), ResourceState::Final); CORRADE_COMPARE(Data::count, 1); } CORRADE_COMPARE(rm.count<Data>(), 0); CORRADE_COMPARE(Data::count, 0); /* Reference counted resources which were not used once will stay loaded until free() is called */ rm.set(dataRefCountKey, new Data, ResourceDataState::Final, ResourcePolicy::ReferenceCounted); CORRADE_COMPARE(rm.count<Data>(), 1); CORRADE_COMPARE(rm.state<Data>(dataRefCountKey), ResourceState::Final); CORRADE_COMPARE(rm.referenceCount<Data>(dataRefCountKey), 0); rm.free<Data>(); CORRADE_COMPARE(rm.count<Data>(), 0); CORRADE_COMPARE(rm.state<Data>(dataRefCountKey), ResourceState::NotLoaded); CORRADE_COMPARE(rm.referenceCount<Data>(dataRefCountKey), 0); } void ResourceManagerTest::manualPolicy() { ResourceManager rm; ResourceKey dataKey("data"); /* Manual free */ { rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual); Resource<Data> data = rm.get<Data>(dataKey); rm.free(); } CORRADE_COMPARE(rm.count<Data>(), 1); CORRADE_COMPARE(Data::count, 1); rm.free(); CORRADE_COMPARE(rm.count<Data>(), 0); CORRADE_COMPARE(Data::count, 0); rm.set(dataKey, new Data, ResourceDataState::Mutable, ResourcePolicy::Manual); CORRADE_COMPARE(rm.count<Data>(), 1); CORRADE_COMPARE(Data::count, 1); } void ResourceManagerTest::defaults() { ResourceManager rm; rm.set("data", new Data); CORRADE_COMPARE(rm.state<Data>("data"), ResourceState::Final); } void ResourceManagerTest::clear() { ResourceManager rm; rm.set("blah", new Data); CORRADE_COMPARE(Data::count, 1); rm.free(); CORRADE_COMPARE(Data::count, 1); rm.clear(); CORRADE_COMPARE(Data::count, 0); } void ResourceManagerTest::clearWhileReferenced() { /* Should cover also the destruction case */ std::ostringstream out; Error::setOutput(&out); ResourceManager rm; rm.set("blah", Int()); /** @todo this will leak, is there any better solution without hitting assertion in decrementReferenceCount()? */ new Resource<Int>(rm.get<Int>("blah")); rm.clear(); CORRADE_COMPARE(out.str(), "ResourceManager: cleared/destroyed while data are still referenced\n"); } void ResourceManagerTest::loader() { class IntResourceLoader: public AbstractResourceLoader<Int> { public: IntResourceLoader(): resource(ResourceManager::instance().get<Data>("data")) {} void load() { set("hello", 773, ResourceDataState::Final, ResourcePolicy::Resident); setNotFound("world"); } private: void doLoad(ResourceKey) override {} std::string doName(ResourceKey key) const override { if(key == ResourceKey("hello")) return "hello"; return ""; } /* To verify that the loader is destroyed before unloading _all types of_ resources */ Resource<Data> resource; }; auto rm = new ResourceManager; auto loader = new IntResourceLoader; rm->setLoader(loader); { Resource<Data> data = rm->get<Data>("data"); Resource<Int> hello = rm->get<Int>("hello"); Resource<Int> world = rm->get<Int>("world"); CORRADE_COMPARE(data.state(), ResourceState::NotLoaded); CORRADE_COMPARE(hello.state(), ResourceState::Loading); CORRADE_COMPARE(world.state(), ResourceState::Loading); CORRADE_COMPARE(loader->requestedCount(), 2); CORRADE_COMPARE(loader->loadedCount(), 0); CORRADE_COMPARE(loader->notFoundCount(), 0); CORRADE_COMPARE(loader->name(ResourceKey("hello")), "hello"); loader->load(); CORRADE_COMPARE(hello.state(), ResourceState::Final); CORRADE_COMPARE(*hello, 773); CORRADE_COMPARE(world.state(), ResourceState::NotFound); CORRADE_COMPARE(loader->requestedCount(), 2); CORRADE_COMPARE(loader->loadedCount(), 1); CORRADE_COMPARE(loader->notFoundCount(), 1); /* Verify that the loader is deleted at proper time */ rm->set("data", new Data); CORRADE_COMPARE(Data::count, 1); } delete rm; CORRADE_COMPARE(Data::count, 0); } }}