c++ - Locking for multi-threaded hot swapping -


in multi-threaded graphics application, have assets images, models, sound files , on. of them loaded files on disk. when files change, want automatically reload them , update corresponding assets may used on application. similar use case lod. when models far away camera, want replace them cheaper less detailed versions.

while assets replaced, other parts of application run in different threads , may read assets. need locking. how can provide proper locking replace assets while making easy possible other parts of application use them?

for example, provide abstract base class assets. contain shared mutex. then, there loader class, internally stores assets , returns references them.

class asset { public:     std::shared_mutex access_; };  class loader { public:     template <typename t>     t &load(std::string filename); private:     std::map<std::pair<std::string, std::type_index>, void*> assets_; };  template <typename t> class assetloadertraits; 

however, there potentially lot of assets, let's try fewer mutexes. example, loader keep list of locked assets. there 1 mutex access list. moreover, wouldn't need asset base class anymore.

class loader { public:     template <typename t>     t &load(std::string filename);     void lock(std::string filename);     bool try_lock(std::string filename, std::chronos::duration trying);     void unlock(std::string filename); private:     std::map<std::pair<std::string, std::type_index>, void*> assets_;     std::shared_mutex map_access_;     std::map<std::string> locked_assets_; };  template <typename t> class assetloadertraits; 

however, still feel isn't best solution. if there thousands of assets, processed in bulk. there loop on vector of assets , locking mechanism required in every iteration. locking, i'd need remember filenames of assets want use. (also, feels weird loader holds locks.)

std::vector<std::pair<std::string, image&>> images; image &image = loader.load<image>("/path/to/image.png"); images.push_back(std::make_pair("/path/to/image.png", image)); // ...  (auto &i : images) {     std::string &filename = i.first;     image &image = i.second;     loader.lock(filename);     // ...     loader.unlock(filename);         } 

is there better way this? feel i'm over-complicating , have overseen simpler solution. how situation commonly solved? goals have simple interface , performance iterations on large collections of assets.

using mutexes guaranteeing have stuttering in use of assets. consider start loading version of asset, display routine wants use it, locked , thread therefore blocked until unlocked.

you instead use share_ptr, consumer keep share_ptr on asset until no longer used.

  • remember keep around if give pointer data in object render function, else render function might reference null).
  • remember unreference pointers after render no longer uses it.

the loader loads new data , when finished loading atomic switch on assets next request consumer gets new asset.

  • if 2 consumers gets 2 different versions of same asset, huge problem? should resolve after 1 update, unless music or sounds or other duration.

ps. code review.

  • when using mutex try using lock_guard raii pattern.
  • often better avoid std::map (and std::list) , use std::unordered_map or std::vector instead due performance.
  • difficult read type declarations

    std::map< std::pair< std::string, std::type_index>, void*>

if using using write this

using assetid = std::pair<std::string, std::type_index>;  std::map<assertid, void*> 

if meant.


Comments

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -