Unified use of std::future for loading sessions in Mixer and

SessionSource.
This commit is contained in:
brunoherbelin
2020-08-16 19:10:23 +02:00
parent c6d8c7189f
commit f6588de023
5 changed files with 114 additions and 115 deletions

View File

@@ -20,43 +20,15 @@ using namespace tinyxml2;
#include "SystemToolkit.h" #include "SystemToolkit.h"
//#include "GarbageVisitor.h" //#include "GarbageVisitor.h"
#include "SessionVisitor.h" #include "SessionVisitor.h"
#include "SessionCreator.h"
#include "SessionSource.h" #include "SessionSource.h"
#include "MediaSource.h" #include "MediaSource.h"
#include "Mixer.h" #include "Mixer.h"
#define THREADED_LOADING #define THREADED_LOADING
// static semaphore to prevent multiple threads for load / save
static std::atomic<bool> sessionThreadActive_ = false;
static std::vector< std::future<Session *> > sessionLoaders_; static std::vector< std::future<Session *> > sessionLoaders_;
static std::vector< std::future<Session *> > sessionImporters_; static std::vector< std::future<Session *> > sessionImporters_;
static std::chrono::milliseconds timeout_ = std::chrono::milliseconds(4); const std::chrono::milliseconds timeout_ = std::chrono::milliseconds(4);
// static multithreaded session loading
static Session *loadSession_(const std::string& filename)
{
Session *s = new Session;
if (s) {
// actual loading of xml file
SessionCreator creator( s );
if (creator.load(filename)) {
// loaded ok
s->setFilename(filename);
}
else {
// error loading
delete s;
s = nullptr;
}
}
return s;
}
// static multithreaded session saving // static multithreaded session saving
@@ -586,9 +558,6 @@ void Mixer::save()
void Mixer::saveas(const std::string& filename) void Mixer::saveas(const std::string& filename)
{ {
if (sessionThreadActive_)
return;
// optional copy of views config // optional copy of views config
session_->config(View::MIXING)->copyTransform( mixing_.scene.root() ); session_->config(View::MIXING)->copyTransform( mixing_.scene.root() );
session_->config(View::GEOMETRY)->copyTransform( geometry_.scene.root() ); session_->config(View::GEOMETRY)->copyTransform( geometry_.scene.root() );

View File

@@ -6,6 +6,7 @@
#include "Session.h" #include "Session.h"
#include "GarbageVisitor.h" #include "GarbageVisitor.h"
#include "Recorder.h" #include "Recorder.h"
#include "SessionCreator.h"
#include "Log.h" #include "Log.h"
@@ -303,3 +304,26 @@ void Session::unlock()
access_.unlock(); access_.unlock();
} }
Session *loadSession_(const std::string& filename)
{
Session *s = new Session;
if (s) {
// actual loading of xml file
SessionCreator creator( s );
if (creator.load(filename)) {
// loaded ok
s->setFilename(filename);
}
else {
// error loading
delete s;
s = nullptr;
}
}
return s;
}

View File

@@ -85,4 +85,7 @@ protected:
std::mutex access_; std::mutex access_;
}; };
Session *loadSession_(const std::string& filename);
#endif // SESSION_H #endif // SESSION_H

View File

@@ -18,26 +18,26 @@
#include "Mixer.h" #include "Mixer.h"
void SessionSource::loadSession(const std::string& filename, SessionSource *source) //void SessionSource::loadSession(const std::string& filename, SessionSource *source)
{ //{
source->loadFinished_ = false; // source->loadFinished_ = false;
// actual loading of xml file // // actual loading of xml file
SessionCreator creator( source->session_ ); // SessionCreator creator( source->session_ );
if (creator.load(filename)) { // if (creator.load(filename)) {
// all ok, validate session filename // // all ok, validate session filename
source->session_->setFilename(filename); // source->session_->setFilename(filename);
} // }
else { // else {
// error loading // // error loading
Log::Notify("Failed to load Session file %s.", filename.c_str()); // Log::Notify("Failed to load Session file %s.", filename.c_str());
source->loadFailed_ = true; // source->failed_ = true;
} // }
// end thread // // end thread
source->loadFinished_ = true; // source->loadFinished_ = true;
} //}
SessionSource::SessionSource() : Source(), path_("") SessionSource::SessionSource() : Source(), path_("")
{ {
@@ -69,11 +69,9 @@ SessionSource::SessionSource() : Source(), path_("")
overlays_[View::TRANSITION]->attach(center); overlays_[View::TRANSITION]->attach(center);
groups_[View::TRANSITION]->attach(overlays_[View::TRANSITION]); groups_[View::TRANSITION]->attach(overlays_[View::TRANSITION]);
loadFailed_ = false; failed_ = false;
loadFinished_ = true;
wait_for_sources_ = false; wait_for_sources_ = false;
session_ = nullptr;
session_ = new Session;
// create surface: // create surface:
// - textured with original texture from session // - textured with original texture from session
@@ -96,9 +94,8 @@ void SessionSource::load(const std::string &p)
{ {
path_ = p; path_ = p;
// launch a thread to load the session // launch a thread to load the session
loadFinished_ = false; sessionLoader_ = std::async(std::launch::async, loadSession_, path_);
std::thread ( SessionSource::loadSession, path_, this).detach();
Log::Notify("Opening %s", p.c_str()); Log::Notify("Opening %s", p.c_str());
} }
@@ -113,14 +110,14 @@ Session *SessionSource::detach()
// make disabled // make disabled
initialized_ = false; initialized_ = false;
loadFailed_ = true; failed_ = true;
return giveaway; return giveaway;
} }
bool SessionSource::failed() const bool SessionSource::failed() const
{ {
return loadFailed_; return failed_;
} }
uint SessionSource::texture() const uint SessionSource::texture() const
@@ -137,66 +134,71 @@ void SessionSource::replaceRenderingShader()
void SessionSource::init() void SessionSource::init()
{ {
if (session_ == nullptr) // init is first about getting the loaded session
return; if (session_ == nullptr) {
// did the loader finish ?
if (sessionLoader_.wait_for(std::chrono::milliseconds(4)) == std::future_status::ready) {
session_ = sessionLoader_.get();
if (session_ == nullptr)
failed_ = true;
}
}
else {
if (wait_for_sources_) { if (wait_for_sources_) {
// force update of of all sources // force update of of all sources
active_ = true; active_ = true;
touch(); touch();
// check that every source is ready.. // check that every source is ready..
bool ready = true; bool ready = true;
for (SourceList::iterator iter = session_->begin(); iter != session_->end(); iter++) for (SourceList::iterator iter = session_->begin(); iter != session_->end(); iter++)
{ {
// interrupt if any source is NOT ready // interrupt if any source is NOT ready
if ( !(*iter)->ready() ){ if ( !(*iter)->ready() ){
ready = false; ready = false;
break; break;
}
}
// if all sources are ready, done with initialization!
if (ready) {
// remove the loading icon
Node *loader = overlays_[View::TRANSITION]->back();
overlays_[View::TRANSITION]->detatch(loader);
delete loader;
// done init
wait_for_sources_ = false;
initialized_ = true;
Log::Info("Source Session %s loaded %d sources.", path_.c_str(), session_->numSource());
} }
} }
// if all sources are ready, done with initialization! else if ( !failed_ ) {
if (ready) {
// remove the loading icon // set resolution
Node *loader = overlays_[View::TRANSITION]->back(); session_->setResolution( session_->config(View::RENDERING)->scale_ );
overlays_[View::TRANSITION]->detatch(loader);
delete loader; // deep update once to draw framebuffer
// done init View::need_deep_update_ = true;
wait_for_sources_ = false; session_->update(dt_);
initialized_ = true;
Log::Info("Source Session %s loaded %d sources.", path_.c_str(), session_->numSource()); // get the texture index from framebuffer of session, apply it to the surface
sessionsurface_->setTextureIndex( session_->frame()->texture() );
// create Frame buffer matching size of session
FrameBuffer *renderbuffer = new FrameBuffer( session_->frame()->resolution());
// set the renderbuffer of the source and attach rendering nodes
attach(renderbuffer);
// icon in mixing view
overlays_[View::MIXING]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) );
overlays_[View::LAYER]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) );
// wait for all sources to init
wait_for_sources_ = true;
} }
} }
if ( loadFinished_ && !loadFailed_ && session_ != nullptr) {
loadFinished_ = false;
// set resolution
session_->setResolution( session_->config(View::RENDERING)->scale_ );
// deep update once to draw framebuffer
View::need_deep_update_ = true;
session_->update(dt_);
// get the texture index from framebuffer of session, apply it to the surface
sessionsurface_->setTextureIndex( session_->frame()->texture() );
// create Frame buffer matching size of session
FrameBuffer *renderbuffer = new FrameBuffer( session_->frame()->resolution());
// set the renderbuffer of the source and attach rendering nodes
attach(renderbuffer);
// icon in mixing view
overlays_[View::MIXING]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) );
overlays_[View::LAYER]->attach( new Symbol(Symbol::SESSION, glm::vec3(0.8f, 0.8f, 0.01f)) );
// wait for all sources to init
wait_for_sources_ = true;
}
} }
void SessionSource::setActive (bool on) void SessionSource::setActive (bool on)
@@ -212,7 +214,7 @@ void SessionSource::setActive (bool on)
void SessionSource::update(float dt) void SessionSource::update(float dt)
{ {
if (session_ == nullptr) if (session_ == nullptr)
loadFailed_ = true; return;
// update content // update content
if (active_) if (active_)
@@ -223,7 +225,7 @@ void SessionSource::update(float dt)
session_->deleteSource(session_->failedSource()); session_->deleteSource(session_->failedSource());
// fail session if all sources failed // fail session if all sources failed
if ( session_->numSource() < 1) if ( session_->numSource() < 1)
loadFailed_ = true; failed_ = true;
} }
Source::update(dt); Source::update(dt);

View File

@@ -2,6 +2,7 @@
#define SESSIONSOURCE_H #define SESSIONSOURCE_H
#include <atomic> #include <atomic>
#include <future>
#include "Source.h" #include "Source.h"
class SessionSource : public Source class SessionSource : public Source
@@ -35,9 +36,9 @@ protected:
std::string path_; std::string path_;
Session *session_; Session *session_;
std::atomic<bool> loadFailed_; std::atomic<bool> failed_;
std::atomic<bool> loadFinished_;
std::atomic<bool> wait_for_sources_; std::atomic<bool> wait_for_sources_;
std::future<Session *> sessionLoader_;
}; };