Let assets control their own lifecycle

This commit is contained in:
Emil Axelsson
2017-12-12 14:55:30 +01:00
parent e0504980ad
commit 1417db5ed7
12 changed files with 714 additions and 415 deletions
+31 -21
View File
@@ -26,6 +26,7 @@
#define __OPENSPACE_CORE___ASSET___H__
#include <openspace/util/resourcesynchronization.h>
#include <openspace/util/synchronizationwatcher.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/filesystem/file.h>
@@ -59,12 +60,14 @@ public:
/**
* Root asset constructor
*/
Asset(AssetLoader* loader);
Asset(AssetLoader* loader, SynchronizationWatcher* watcher);
/**
* Regular asset constructor
*/
Asset(AssetLoader* loader, ghoul::filesystem::File assetPath);
Asset(AssetLoader* loader,
SynchronizationWatcher* watcher,
ghoul::filesystem::File assetPath);
~Asset();
@@ -76,24 +79,31 @@ public:
AssetLoader* loader() const;
State state() const;
void setState(State state);
void addSynchronization(std::shared_ptr<ResourceSynchronization> synchronization);
std::vector<std::shared_ptr<ResourceSynchronization>> ownSynchronizations() const;
void syncStateChanged(std::shared_ptr<ResourceSynchronization> sync,
ResourceSynchronization::State s);
void load();
bool isLoaded() const;
void unload();
void unloadIfUnwanted();
// Sync
bool isSynchronized();
bool isSynchronized() const;
bool startSynchronizations();
bool cancelSynchronizations();
bool restartSynchronizations();
bool cancelAllSynchronizations();
bool cancelUnwantedSynchronizations();
bool restartAllSynchronizations();
float synchronizationProgress();
// Init
bool isInitReady() const;
bool hasInitializedRequester() const;
bool isInitialized() const;
void initialize();
void deinitialize();
void deinitializeIfUnwanted();
// Dependency graph
bool requires(const Asset* asset) const;
@@ -103,33 +113,34 @@ public:
void request(std::shared_ptr<Asset> child);
void unrequest(std::shared_ptr<Asset> child);
std::vector<std::shared_ptr<Asset>> requestedAssets();
std::vector<std::shared_ptr<Asset>> requestingAssets();
std::vector<std::shared_ptr<Asset>> requiredAssets();
std::vector<std::shared_ptr<Asset>> requiringAssets();
std::vector<std::shared_ptr<Asset>> requestedAssets() const;
std::vector<std::shared_ptr<Asset>> requestingAssets() const;
std::vector<std::shared_ptr<Asset>> requiredAssets() const;
std::vector<std::shared_ptr<Asset>> requiringAssets() const;
std::vector<std::shared_ptr<Asset>> requiredSubTreeAssets();
std::vector<std::shared_ptr<Asset>> subTreeAssets();
std::vector<std::shared_ptr<Asset>> childAssets();
std::vector<std::shared_ptr<Asset>> childAssets() const;
std::vector<std::shared_ptr<Asset>> parentAssets() const;
bool isRequired() const;
bool isRequested() const;
bool shouldBeInitialized() const;
std::string resolveLocalResource(std::string resourceName);
private:
void requiredAssetChangedState(std::shared_ptr<Asset> a);
void setState(State state);
void addRequestingAsset(std::shared_ptr<Asset> a);
void removeRequestingAsset(std::shared_ptr<Asset> a);
void addRequiringAsset(std::shared_ptr<Asset> a);
void removeRequiringAsset(std::shared_ptr<Asset> a);
void requiredAssetChangedState(std::shared_ptr<Asset> a);
void requestedAssetChangedState(std::shared_ptr<Asset> a);
bool isSyncResolveReady();
std::atomic<State> _state;
AssetLoader* _loader;
SynchronizationWatcher* _synchronizationWatcher;
std::vector<std::shared_ptr<ResourceSynchronization>> _synchronizations;
mutable std::mutex _synchronizationsMutex;
bool _hasAssetPath;
// The name of the asset
@@ -150,9 +161,8 @@ private:
// Assets that refers to this asset as a requested asset
std::vector<std::weak_ptr<Asset>> _requestingAssets;
// Synchronization callback handles
std::unordered_map<ResourceSynchronization*, ResourceSynchronization::CallbackHandle>
_syncCallbackHandles;
// Synchronization watches
std::vector<SynchronizationWatcher::WatchHandle> _syncWatches;
};
} // namespace openspace
+50 -22
View File
@@ -56,20 +56,23 @@ int noOperation(lua_State* state);
int exportAsset(lua_State* state);
} // namespace assetloader
class AssetStateChangeListener {
class AssetListener {
public:
virtual void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state) = 0;
virtual void assetRequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) = 0;
virtual void assetUnrequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) = 0;
};
class SynchronizationWatcher;
class AssetLoader {
public:
/**
* Constructor
*/
AssetLoader(
ghoul::lua::LuaState& luaState,
std::string assetRoot
);
AssetLoader(ghoul::lua::LuaState& luaState,
SynchronizationWatcher* syncWatcher,
std::string assetRoot);
/**
* Destructor
@@ -88,18 +91,15 @@ public:
*/
void remove(const std::string& identifier);
void trackAsset(std::shared_ptr<Asset> asset);
void untrackAsset(Asset* asset);
/**
* Returns the asset identified by the identifier,
* if the asset is loaded. Otherwise return nullptr.
*/
std::shared_ptr<Asset> has(const std::string& identifier) const;
/**
* Return all assets loaded using the loadAsset method.
* Non-recursive (does not include imports of the loaded assets)
*/
//std::vector<std::shared_ptr<Asset>> loadedAssets();
/**
* Return the lua state
*/
@@ -115,6 +115,8 @@ public:
*/
const std::string& assetRootDirectory() const;
bool loadAsset(std::shared_ptr<Asset> asset);
void callOnInitialize(Asset* asset);
void callOnDeinitialize(Asset* asset);
@@ -127,22 +129,46 @@ public:
const std::string& path) const;
void addAssetStateChangeListener(AssetStateChangeListener* listener);
void removeAssetStateChangeListener(AssetStateChangeListener* listener);
/**
* Add listener to asset state changes
*/
void addAssetListener(AssetListener* listener);
/**
* Remove listener to asset state changes
*/
void removeAssetListener(AssetListener* listener);
/**
* Notify listeners about asset state change
*/
void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state);
/**
* Notify listeners about new requests
*/
void assetRequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child);
/**
* Notify listeners about removed requests
*/
void assetUnrequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child);
private:
std::shared_ptr<Asset> require(const std::string& identifier);
std::shared_ptr<Asset> request(const std::string& path);
void unrequest(const std::string& path);
std::shared_ptr<Asset> loadAsset(std::string path);
/**
* Add the global assets table to the lua stack.
*/
void setUpAssetLuaTable(Asset* asset);
void tearDownAssetLuaTable(Asset* asset);
std::shared_ptr<Asset> getAsset(std::string path);
ghoul::filesystem::Directory currentDirectory() const;
void pushAsset(std::shared_ptr<Asset> asset);
void popAsset();
void updateLuaGlobals();
void setCurrentAsset(std::shared_ptr<Asset> asset);
void addLuaDependencyTable(Asset* dependant, Asset* dependency);
// Lua functions
@@ -168,12 +194,17 @@ private:
friend int assetloader::exportAsset(lua_State* state);
std::shared_ptr<Asset> _rootAsset;
std::unordered_map<std::string, std::shared_ptr<Asset>> _loadedAssets;
std::vector<std::shared_ptr<Asset>> _assetStack;
std::shared_ptr<Asset> _currentAsset;
std::unordered_map<std::string, std::weak_ptr<Asset>> _loadedAssets;
SynchronizationWatcher* _synchronizationWatcher;
std::string _assetRootDirectory;
ghoul::lua::LuaState* _luaState;
// State change listeners
std::vector<AssetListener*> _assetListeners;
// References to lua values
std::unordered_map<Asset*, std::vector<int>> _onInitializationFunctionRefs;
std::unordered_map<Asset*, std::vector<int>> _onDeinitializationFunctionRefs;
@@ -181,9 +212,6 @@ private:
_onDependencyInitializationFunctionRefs;
std::unordered_map<Asset*, std::map<Asset*, std::vector<int>>>
_onDependencyDeinitializationFunctionRefs;
std::vector<AssetStateChangeListener*> _assetStateChangeListeners;
int _assetsTableRef;
};
+9 -5
View File
@@ -28,7 +28,7 @@
#include <openspace/scene/asset.h>
#include <openspace/scene/assetloader.h>
#include <openspace/util/resourcesynchronizer.h>
#include <openspace/util/synchronizationwatcher.h>
#include <openspace/scripting/lualibrary.h>
@@ -51,11 +51,12 @@ class Asset;
* from the system if it is not a dependency of a loaded asset.
*/
class AssetManager : AssetStateChangeListener {
class AssetManager : AssetListener {
public:
AssetManager(
std::unique_ptr<AssetLoader> loader
);
AssetManager(std::unique_ptr<AssetLoader> loader,
std::unique_ptr<SynchronizationWatcher> syncWatcher);
virtual ~AssetManager() = default;
void initialize();
void deinitialize();
@@ -65,6 +66,8 @@ public:
std::shared_ptr<Asset> rootAsset();
void assetStateChanged(std::shared_ptr<Asset> asset, Asset::State state) override;
void assetRequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) override;
void assetUnrequested(std::shared_ptr<Asset> parent, std::shared_ptr<Asset> child) override;
bool update();
scripting::LuaLibrary luaLibrary();
@@ -77,6 +80,7 @@ private:
std::vector<std::shared_ptr<Asset>> _pendingInitializations;
std::unique_ptr<AssetLoader> _assetLoader;
std::unique_ptr<SynchronizationWatcher> _synchronizationWatcher;
};
} // namespace openspace
@@ -22,11 +22,63 @@
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
#define __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
#ifndef __OPENSPACE_CORE___SYNCHRONIZATIONWATCHER___H__
#define __OPENSPACE_CORE___SYNCHRONIZATIONWATCHER___H__
#include <openspace/util/resourcesynchronization.h>
#include <mutex>
#include <vector>
#include <memory>
#include <unordered_map>
namespace openspace {
/**
* Delays callbacks of synchronization state changes to
* when notify is called.
*/
class SynchronizationWatcher {
public:
using WatchHandle = size_t;
struct WatchData {
std::weak_ptr<ResourceSynchronization> synchronization;
ResourceSynchronization::CallbackHandle callbackHandle;
};
struct NotificationData {
std::weak_ptr<ResourceSynchronization> synchronization;
ResourceSynchronization::State state;
WatchHandle handle;
ResourceSynchronization::StateChangeCallback callback;
};
/*using SyncStateChangeCallback =
std::function<void(
std::shared_ptr<ResourceSynchronization>,
ResourceSynchronization::State
)>;*/
WatchHandle watchSynchronization(
std::shared_ptr<ResourceSynchronization> synchronization,
ResourceSynchronization::StateChangeCallback callback
);
void unwatchSynchronization(WatchHandle watch);
void notify();
private:
WatchHandle generateWatchHandle();
std::mutex _mutex;
std::unordered_map<WatchHandle, WatchData> _watchedSyncs;
std::vector<NotificationData> _pendingNotifications;
WatchHandle nextWatchHandle = 0;
};
} // namespace openspace
#endif // __OPENSPACE_CORE___RESOURCESYNCHRONIZER___H__
#endif // __OPENSPACE_CORE___SYNCHRONIZATIONWATCHER___H__