From 1b0cb56dccd88789084c0e1995edd303ecf46d02 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Tue, 14 Jun 2011 05:41:02 +0200 Subject: [PATCH] implement PlayOut subsystem and draft OutputDirector --- src/backend/thread-wrapper.hpp | 2 +- src/common/guifacade.cpp | 2 +- src/common/subsys.hpp | 11 +- src/common/subsystem-runner.hpp | 2 +- src/lib/result.hpp | 9 +- src/proc/control/handling-pattern.hpp | 1 + src/proc/facade.cpp | 17 ++- .../mobject/session/lifecycle-advisor.hpp | 4 +- .../mobject/session/sess-manager-impl.cpp | 14 +- .../mobject/session/sess-manager-impl.hpp | 2 +- src/proc/play/output-director.cpp | 135 ++++++++++++++++++ src/proc/play/output-director.hpp | 100 +++++++++++++ src/proc/play/output-manager.cpp | 44 ------ 13 files changed, 270 insertions(+), 73 deletions(-) create mode 100644 src/proc/play/output-director.cpp create mode 100644 src/proc/play/output-director.hpp delete mode 100644 src/proc/play/output-manager.cpp diff --git a/src/backend/thread-wrapper.hpp b/src/backend/thread-wrapper.hpp index 60413b037..699bfd11d 100644 --- a/src/backend/thread-wrapper.hpp +++ b/src/backend/thread-wrapper.hpp @@ -200,7 +200,7 @@ namespace backend { /** Synchronisation barrier. In the function executing in this thread - * needs to be a corresponding Thread::sync() call. Blocking until + * needs to be a corresponding Thread::syncPoint() call. Blocking until * both the caller and the thread have reached the barrier. */ void diff --git a/src/common/guifacade.cpp b/src/common/guifacade.cpp index aff7febb8..5e1c4599d 100644 --- a/src/common/guifacade.cpp +++ b/src/common/guifacade.cpp @@ -156,7 +156,7 @@ namespace gui { if (facade) { WARN (guifacade, "GUI subsystem terminates, but GuiFacade isn't properly closed. " - "Closing it forcedly; this indicates broken startup logic and should be fixed."); + "Closing it forcedly; this indicates broken startup logic and should be fixed."); try { facade.reset (0); } catch(...) { WARN_IF (lumiera_error_peek(), guifacade, "Ignoring error: %s", lumiera_error()); } lumiera_error(); // clear any remaining error state... diff --git a/src/common/subsys.hpp b/src/common/subsys.hpp index 363b17e51..26b080861 100644 --- a/src/common/subsys.hpp +++ b/src/common/subsys.hpp @@ -104,9 +104,12 @@ namespace lumiera { /** initiate termination of this subsystem. - * may be called repeatedly any time... - * @warning must not block nor throw. */ - virtual void triggerShutdown () throw() =0; + * This trigger may be called repeatedly any time... + * When the subsystem actually has terminated, + * the SigTerm passed to #start must be invoked. + * @note called within a locked context (barrier) + * @warning must not block nor throw. */ + virtual void triggerShutdown () throw() =0; const std::vector @@ -114,7 +117,7 @@ namespace lumiera { private: - /** weather this subsystem is actually operational. + /** whether this subsystem is actually operational. * When returning \c false here, the application may * terminate at any point without further notice * Note further, that a subsystem must not be in diff --git a/src/common/subsystem-runner.hpp b/src/common/subsystem-runner.hpp index 89a90245d..6cbd3495a 100644 --- a/src/common/subsystem-runner.hpp +++ b/src/common/subsystem-runner.hpp @@ -173,7 +173,7 @@ namespace lumiera { if (!and_all (susy->getPrerequisites(), isRunning() )) { susy->triggerShutdown(); - throw error::Logic("Unable to start all prerequisites of Subsystem "+string(*susy)); + throw error::State("Unable to start all prerequisites of Subsystem "+string(*susy)); } } void diff --git a/src/lib/result.hpp b/src/lib/result.hpp index ae4f7b187..daf153a49 100644 --- a/src/lib/result.hpp +++ b/src/lib/result.hpp @@ -58,11 +58,10 @@ namespace lib { /** - * Result value and status of some operation. - * It can be created for passing a result produced - * by the operation, or the failure to do so. The value - * can be retrieved by implicit or explicit conversion. - * @throws on any attempt to access the value in case of failure + * Optional Result value or status of some operation. + * It can be created for passing a result produced by the operation, or the + * failure to do so. The value can be retrieved by implicit or explicit conversion. + * @throw error::State on any attempt to access the value in case of failure * @warning this class has a lot of implicit conversions; * care should be taken when defining functions * to take Result instances as parameter.... diff --git a/src/proc/control/handling-pattern.hpp b/src/proc/control/handling-pattern.hpp index f414e25a1..6cc947211 100644 --- a/src/proc/control/handling-pattern.hpp +++ b/src/proc/control/handling-pattern.hpp @@ -67,6 +67,7 @@ namespace control { * It is returned when invoking a HandlingPattern * and can be used to check for success and/or re-throw * any Exception encountered during the command execution. + * @todo couldn't that be replaced by a lib::Result instance?? */ class ExecResult : public lib::BoolCheckable diff --git a/src/proc/facade.cpp b/src/proc/facade.cpp index 6ca6a84b6..de6d562ee 100644 --- a/src/proc/facade.cpp +++ b/src/proc/facade.cpp @@ -23,6 +23,7 @@ #include "proc/facade.hpp" #include "lib/singleton.hpp" +#include "proc/play/output-director.hpp" #include @@ -77,7 +78,7 @@ namespace proc { bool shouldStart (lumiera::Option&) { - TODO ("determine, if an existing Session schould be loaded"); + TODO ("determine, if an existing Session should be loaded"); return false; } @@ -127,22 +128,24 @@ namespace proc { bool start (lumiera::Option&, Subsys::SigTerm termination) { - UNIMPLEMENTED ("bring up and configure the output connections and the player"); - return false; + this->completedSignal_ = termination; + return play::OutputDirector::instance().connectUp(); } + SigTerm completedSignal_; + + void triggerShutdown () throw() { - UNIMPLEMENTED ("initiate playback/render halt and disconnect output"); + play::OutputDirector::instance().triggerDisconnect (completedSignal_); } + bool checkRunningState () throw() { - //Lock guard (*this); - TODO ("implement detecting running state"); - return false; + return play::OutputDirector::instance().isOperational(); } }; diff --git a/src/proc/mobject/session/lifecycle-advisor.hpp b/src/proc/mobject/session/lifecycle-advisor.hpp index a3c286af8..0e8364fae 100644 --- a/src/proc/mobject/session/lifecycle-advisor.hpp +++ b/src/proc/mobject/session/lifecycle-advisor.hpp @@ -31,7 +31,7 @@ ** here; any implementation is delegated to the relevant session facilities. ** ** The idea of a LifecycleAdvisor is inspired by GUI frameworks, especially - ** Spring RichClient. Typically, such frameworks provides a means for flexible + ** Spring RichClient. Typically, such frameworks provide a means for flexible ** configuration of the application lifecycle. Configurability isn't the primary ** goal here, as there is only one Lumiera application and the session lifecycle ** can be considered fixed, with the exception of some extension points, which are @@ -64,7 +64,7 @@ namespace session { /** - * Skeleton operations conducting the session lifecycle sequences. + * Skeleton of operations conducting the session lifecycle sequences. * Any details of the operations are delegated to the current session * and associated services. * @warning this object is assumed to be used as a single instance diff --git a/src/proc/mobject/session/sess-manager-impl.cpp b/src/proc/mobject/session/sess-manager-impl.cpp index 972a711be..9ce3c61ec 100644 --- a/src/proc/mobject/session/sess-manager-impl.cpp +++ b/src/proc/mobject/session/sess-manager-impl.cpp @@ -67,7 +67,7 @@ namespace session { SessionImplAPI* SessManagerImpl::operator-> () throw() { - if (!pImpl_) + if (!pSess_) try { // create empty default configured session this->reset(); @@ -80,7 +80,7 @@ namespace session { } - return pImpl_.get(); + return pSess_.get(); } @@ -201,8 +201,8 @@ namespace session { * \link #operator-> access \endlink to the session object. */ SessManagerImpl::SessManagerImpl () throw() - : pImpl_ (0) - , lifecycle_(new SessionLifecycleDetails(pImpl_)) + : pSess_ (0) + , lifecycle_(new SessionLifecycleDetails(pSess_)) { Session::initFlag = true; //////////////////////////////////////// TICKET #518 instead of this hack, implement basic-init of the session manager for real } @@ -219,7 +219,7 @@ namespace session { bool SessManagerImpl::isUp () { - return bool(pImpl_); ///////////////////// TICKET #702 possible race, because this gets true way before the interface is up + return bool(pSess_); ///////////////////// TICKET #702 possible race, because this gets true way before the interface is up } /** @note no transactional behaviour. may succeed partially. @@ -229,7 +229,7 @@ namespace session { SessManagerImpl::clear () { Lock sync(this); - pImpl_->clear(); + pSess_->clear(); } @@ -242,7 +242,7 @@ namespace session { { Lock sync(this); lifecycle_->shutDown(); - pImpl_.reset(); + pSess_.reset(); } diff --git a/src/proc/mobject/session/sess-manager-impl.hpp b/src/proc/mobject/session/sess-manager-impl.hpp index 14af631c6..403f835c8 100644 --- a/src/proc/mobject/session/sess-manager-impl.hpp +++ b/src/proc/mobject/session/sess-manager-impl.hpp @@ -42,7 +42,7 @@ namespace session { : public SessManager , public lib::Sync<> { - scoped_ptr pImpl_; + scoped_ptr pSess_; scoped_ptr lifecycle_; SessManagerImpl() throw(); diff --git a/src/proc/play/output-director.cpp b/src/proc/play/output-director.cpp new file mode 100644 index 000000000..0bcbebc26 --- /dev/null +++ b/src/proc/play/output-director.cpp @@ -0,0 +1,135 @@ +/* + OutputDirector - handling all the real external output connections + + Copyright (C) Lumiera.org + 2011, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +* *****************************************************/ + + +#include "proc/play/play-service.hpp" +#include "proc/play/output-manager.hpp" +#include "proc/play/output-director.hpp" +#include "backend/thread-wrapper.hpp" + +using backend::Thread; + + +namespace proc { +namespace play { + + + + namespace { // hidden local details of the service implementation.... + + } // (End) hidden service impl details + + + + /** storage for the single application wide OutputDirector instance */ + lib::Singleton OutputDirector::instance; + + + /** bring up the framework for handling input/output connections. + * Creating this object happens on first access and shouldn't be + * confused with actually booting up / shutting down this subsystem. + * Rather, the purpose of the OutputDirector is actively to conduct + * the Lifecycle of booting, connecting, operating, disconnecting. + */ + OutputDirector::OutputDirector() + { } + + OutputDirector::~OutputDirector() { } + + + + /** connect and bring up the external input/output connections, + * handlers and interface services and the render/playback service. + * @return true if the output subsystem can be considered operational + * + * @todo WIP-WIP-WIP 6/2011 + */ + bool + OutputDirector::connectUp() + { + Lock sync(this); + + player_.reset (new PlayService); + return this->isOperational(); + } + + + bool + OutputDirector::isOperational() const + { + return bool(player_); ////////////TODO more to check here.... + } + + + + /** initiate shutdown of all ongoing render/playback processes + * and closing of all external input/output interfaces. + * Works as an asynchronous operation; the given callback signal + * will be invoked when the shutdown is complete. + * @note starting a new thread, which might fail. + * When this happens, the raised exception will cause + * immediate unconditional termination of the application. + */ + void + OutputDirector::triggerDisconnect (SigTerm completedSignal) throw() + { + Thread ("Output shutdown supervisor", bind (&OutputDirector::bringDown, this, completedSignal)); + } + + + /** @internal actually bring down any calculation processes + * and finally disconnect any external input/output interfaces. + * This shutdown and cleanup operation is executed in a separate + * "Output shutdown supervisor" thread and has the liability to + * bring down the relevant facilities within a certain timespan. + * When done, the last operation within this thread will be to + * invoke the callback signal given as parameter. + * @note locks the OutputDirector + */ + void + OutputDirector::bringDown (SigTerm completedSignal) + { + Lock sync(this); + string problemLog; + try + { + TODO ("actually bring down the output generation"); + player_.reset(0); + + completedSignal(0); + } + + catch (lumiera::Error& problem) + { + problemLog = problem.what(); + lumiera_error(); // reset error state + completedSignal (&problemLog); + } + catch (...) + { + problemLog = "Unknown error while disconnecting output. " + "Lumiera error flag is = "+string(lumiera_error()); + completedSignal (&problemLog); + } + } + +}} // namespace proc::play diff --git a/src/proc/play/output-director.hpp b/src/proc/play/output-director.hpp new file mode 100644 index 000000000..2783b097c --- /dev/null +++ b/src/proc/play/output-director.hpp @@ -0,0 +1,100 @@ +/* + OUTPUT-DIRECTOR.hpp - handling all the real external output connections + + Copyright (C) Lumiera.org + 2011, Hermann Vosseler + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/** @file output-director.hpp + ** A global service to coordinate and handle all external output activities. + ** The OutputDirector is an application internal singleton service for + ** coordinating and controlling all actual input/output- and rendering + ** capabilities, exposing distinct lifecycle functions to connect, bring + ** up and shut down what can be considered the "Player/Output" subsystem. + ** + ** @see output-manager-test.cpp ////TODO + */ + + +#ifndef PROC_PLAY_OUTPUT_DIRECTOR_H +#define PROC_PLAY_OUTPUT_DIRECTOR_H + + +#include "lib/error.hpp" +#include "lib/singleton.hpp" +#include "proc/play/output-manager.hpp" +#include "common/subsys.hpp" +#include "lib/sync.hpp" + +#include +//#include +//#include +//#include +#include + + +namespace proc { +namespace play { + +//using std::string; +//using std::vector; +//using std::tr1::shared_ptr; + using boost::scoped_ptr; + + + class PlayService; + + +//typedef lib::ScopedPtrVect DisplayerTab; + + + + /****************************************************** + * Management of external Output connections. + * + * @todo write Type comment + */ + class OutputDirector + : boost::noncopyable + , public lib::Sync<> + { + typedef lumiera::Subsys::SigTerm SigTerm; + + scoped_ptr player_; + + public: + static lib::Singleton instance; + + bool connectUp() ; + void triggerDisconnect(SigTerm) throw(); + + bool isOperational() const; + + private: + OutputDirector() ; + ~OutputDirector() ; + friend class lib::singleton::StaticCreate; + + + void bringDown (SigTerm completedSignal); + }; + + + +}} // namespace proc::play +#endif diff --git a/src/proc/play/output-manager.cpp b/src/proc/play/output-manager.cpp deleted file mode 100644 index 6ffca994f..000000000 --- a/src/proc/play/output-manager.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - OutputManager - handling all the real external output connections - - Copyright (C) Lumiera.org - 2011, Hermann Vosseler - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -* *****************************************************/ - - -#include "proc/play/output-manager.hpp" - - - -namespace proc { -namespace play { - - - - namespace { // hidden local details of the service implementation.... - - } // (End) hidden service impl details - - - - - OutputSlot::~OutputSlot() { } - - - -}} // namespace proc::play