diff --git a/Makefile.am b/Makefile.am index 2664e03..4af024e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -48,6 +48,7 @@ bin_PROGRAMS = plugin_LTLIBRARIES = noinst_HEADERS = pkglib_LTLIBRARIES = +pkginclude_HEADERS = EXTRA_DIST = MAINTAINERCLEANFILES = MOSTLYCLEANFILES = @@ -127,6 +128,7 @@ pkglib_LTLIBRARIES += src/backend/libbackend.la src_backend_libbackend_la_CPPFLAGS = \ -I@top_srcdir@ \ + -I@top_srcdir@/src/templates \ -DPOLDIR="\"$(policiesdir)\"" \ -DPLUGDIR="\"$(plugindir)\"" \ -DLOCALEDIR="\"$(localedir)\"" \ @@ -163,7 +165,7 @@ src_backend_libbackend_la_SOURCES = \ src/backend/thread.cc \ src/backend/user_interrupt_exception.cc -pkginclude_HEADERS = \ +pkginclude_HEADERS += \ config.h \ src/backend/dynamic_process.hh \ src/backend/dynamic_schedulable.hh \ @@ -198,6 +200,7 @@ bin_PROGRAMS += sgpemv2 sgpemv2_CPPFLAGS = \ -I@top_srcdir@ \ + -I@top_srcdir@/src/templates \ -DLOCALEDIR="\"$(localedir)\"" \ $(CAIRO_CFLAGS) \ $(GTKMM_CFLAGS) \ @@ -242,10 +245,12 @@ noinst_HEADERS += \ # # ############################################################ -noinst_HEADERS += \ +pkginclude_HEADERS += \ src/templates/parameter.tcc \ - src/templates/smartp.tcc \ - src/templates/smartp.hh + src/templates/singleton.hh \ + src/templates/singleton.tcc \ + src/templates/smartp.hh \ + src/templates/smartp.tcc # ############################################################ # @@ -266,6 +271,7 @@ noinst_PROGRAMS = \ src_testsuite_test_history_CPPFLAGS = \ -I@top_srcdir@/src \ + -I@top_srcdir@/src/templates \ $(GLIBMM_CFLAGS) src_testsuite_test_history_LDFLAGS = \ src/backend/libbackend.la \ @@ -277,6 +283,7 @@ src_testsuite_test_history_SOURCES = \ #src_testsuite_test_parse_command_CPPFLAGS = \ # -I@top_srcdir@/src \ +# -I@top_srcdir@/src/templates \ # $(GLIBMM_CFLAGS) #src_testsuite_test_parse_command_LDFLAGS = \ # src/backend/libbackend.la \ @@ -288,6 +295,7 @@ src_testsuite_test_history_SOURCES = \ # advice: get dummy_policy from the somewhere in the repository, and compile it in. #src_testsuite_test_stepforward_CPPFLAGS = \ # -I@top_srcdir@/src \ +# -I@top_srcdir@/src/templates \ # $(GLIBMM_CFLAGS) #src_testsuite_test_stepforward_LDFLAGS = \ # src/backend/libbackend.la \ diff --git a/config/sgpemv2-uninstalled.pc.in b/config/sgpemv2-uninstalled.pc.in index 214adf8..f7541a3 100644 --- a/config/sgpemv2-uninstalled.pc.in +++ b/config/sgpemv2-uninstalled.pc.in @@ -14,4 +14,4 @@ URL: http://www.math.unipd.it/ Requires: glibmm-2.4 >= 2.8 gthread-2.0 >= 2.8 Libs: -L${libdir}/src/backend -lbackend Libs.private: -lglibmm-2.4 -lgthread-2.0 -Cflags: -I${includedir}/backend +Cflags: -I${includedir}/backend -I${includedir}/templates diff --git a/plugins/pyloader/src/python_policy_manager.cc b/plugins/pyloader/src/python_policy_manager.cc index 424c477..2130357 100644 --- a/plugins/pyloader/src/python_policy_manager.cc +++ b/plugins/pyloader/src/python_policy_manager.cc @@ -107,10 +107,11 @@ PythonPolicyManager::init() // environment variables. // FIXME: find better way to achieve this. + GlobalPreferences& prefs = GlobalPreferences::get_instance(); Glib::ustring importdirs = "import sys\n" "sys.path[:0] = [ "; - for_each(GlobalPreferences::instance().policies_dir_begin(), - GlobalPreferences::instance().policies_dir_end(), + for_each(prefs.policies_dir_begin(), + prefs.policies_dir_end(), pol_dirs_concat(importdirs)); importdirs += " '" SHAREDIR "' ]\n"; @@ -131,8 +132,9 @@ PythonPolicyManager::get_avail_policies() void PythonPolicyManager::collect_policies() { - GlobalPreferences::dir_iterator dir_it = GlobalPreferences::instance().policies_dir_begin(); - GlobalPreferences::dir_iterator dir_end = GlobalPreferences::instance().policies_dir_end(); + GlobalPreferences& prefs = GlobalPreferences::get_instance(); + GlobalPreferences::dir_iterator dir_it = prefs.policies_dir_begin(); + GlobalPreferences::dir_iterator dir_end = prefs.policies_dir_end(); for(; dir_it != dir_end; ++dir_it) { diff --git a/plugins/pyloader/src/testsuite/test-python_loader.cc b/plugins/pyloader/src/testsuite/test-python_loader.cc index 9c8ba66..e0754ec 100644 --- a/plugins/pyloader/src/testsuite/test-python_loader.cc +++ b/plugins/pyloader/src/testsuite/test-python_loader.cc @@ -67,7 +67,7 @@ main(int argc, char** argv) { } else // Add argv[1] as the directory to search for uninstalled policies - sgpem::GlobalPreferences::instance().add_policies_dir(argv[1]); + sgpem::GlobalPreferences::get_instance().add_policies_dir(argv[1]); // Self-register itself to Scheduler, however we don't care about it TestPythonPolicyManager polman; diff --git a/src/backend/global_preferences.cc b/src/backend/global_preferences.cc index 7fe0d39..a5f3b23 100644 --- a/src/backend/global_preferences.cc +++ b/src/backend/global_preferences.cc @@ -23,17 +23,6 @@ using namespace sgpem; -GlobalPreferences* GlobalPreferences::_instance = 0; - -GlobalPreferences& -GlobalPreferences::instance() -{ - if(!_instance) - _instance = new GlobalPreferences(); - return *_instance; -} - - GlobalPreferences::GlobalPreferences() : _mod_dirs(1, PLUGDIR), _pol_dirs(1, POLDIR) {} diff --git a/src/backend/global_preferences.hh b/src/backend/global_preferences.hh index d073e40..d48ba93 100644 --- a/src/backend/global_preferences.hh +++ b/src/backend/global_preferences.hh @@ -26,6 +26,8 @@ #include #include +#include "singleton.hh" + namespace sgpem { class GlobalPreferences; } @@ -33,12 +35,13 @@ namespace sgpem { #include "config.h" namespace sgpem { - class SG_DLLEXPORT GlobalPreferences { - public: + class SG_DLLEXPORT GlobalPreferences : public Singleton + { + friend class Singleton; + + public: typedef std::vector::const_iterator dir_iterator; - static GlobalPreferences& instance(); - dir_iterator modules_dir_begin() const; dir_iterator modules_dir_end() const; @@ -53,7 +56,6 @@ namespace sgpem { GlobalPreferences(const GlobalPreferences&); GlobalPreferences& operator=(const GlobalPreferences&); - static GlobalPreferences* _instance; std::vector _mod_dirs; std::vector _pol_dirs; }; diff --git a/src/backend/history.cc b/src/backend/history.cc index 90d59b1..29f2c8d 100644 --- a/src/backend/history.cc +++ b/src/backend/history.cc @@ -23,25 +23,13 @@ using namespace std; using namespace sgpem; using namespace memory; -//History::instance; //static object -History* History::_instance = 0; - /** The constructor sets _total_time_elapsed to -1: this permits to insert the INITIAL STATUS of the simulation which must begin at instant -1 and live for 1 instant. */ -History::History() //private constructor. The parameter is discarded +History::History() //private constructor. :_total_time_elapsed(-1) {} - - -History& -History::get_instance() -{ - if(!_instance) - _instance = new History(); - return *_instance; -} /** diff --git a/src/backend/history.hh b/src/backend/history.hh index a3041fb..8c6a6b9 100644 --- a/src/backend/history.hh +++ b/src/backend/history.hh @@ -32,6 +32,8 @@ #include "dynamic_schedulable.hh" #include "../templates/smartp.hh" +#include "singleton.hh" + namespace sgpem { @@ -47,8 +49,10 @@ namespace sgpem */ class History; - class SG_DLLEXPORT History : public ObservedSubject + class SG_DLLEXPORT History : public Singleton, public ObservedSubject { + friend class Singleton; + public: /** Gets the \ref Schedulable object running at the specified time. @@ -82,16 +86,9 @@ namespace sgpem */ virtual void truncate_at(int instant); - - /** - Gets the only instance of History. - \return The Singleton instance of this object. - */ - static History& get_instance(); - + protected: - History(); //private constructor. The parameter is discarded - static History* _instance; + History(); //private constructor. private: int _total_time_elapsed; diff --git a/src/backend/policies_gatekeeper.cc b/src/backend/policies_gatekeeper.cc index 1083633..f6d8c02 100644 --- a/src/backend/policies_gatekeeper.cc +++ b/src/backend/policies_gatekeeper.cc @@ -34,16 +34,6 @@ using namespace sgpem; typedef vector::iterator ManagerIterator; typedef map::iterator ActiveIterator; -PoliciesGatekeeper* PoliciesGatekeeper::_instance = NULL; - -PoliciesGatekeeper& -PoliciesGatekeeper::get_instance() -{ - if(!_instance) - _instance = new PoliciesGatekeeper(); - return *_instance; -} - vector PoliciesGatekeeper::get_registered() const { diff --git a/src/backend/policies_gatekeeper.hh b/src/backend/policies_gatekeeper.hh index 939aeb6..cd6d99d 100644 --- a/src/backend/policies_gatekeeper.hh +++ b/src/backend/policies_gatekeeper.hh @@ -34,6 +34,8 @@ namespace sgpem #include #include +#include "singleton.hh" + namespace sgpem { class PoliciesGatekeeper; @@ -43,15 +45,11 @@ namespace sgpem */ - class SG_DLLEXPORT PoliciesGatekeeper + class SG_DLLEXPORT PoliciesGatekeeper : public Singleton { - public: - /** \brief Returns the unique instance of this class, conforming to the Singleton pattern. - * - * \return the unique instance of this class, conforming to the Singleton pattern. - */ - static PoliciesGatekeeper& get_instance(); + friend class Singleton; + public: std::vector get_registered() const; void register_manager(PolicyManager* manager); @@ -68,7 +66,6 @@ namespace sgpem // Deactivates active policies managed by the specified manager. void deactivate_policies(PolicyManager* manager); - static PoliciesGatekeeper* _instance; std::vector _registered; std::map _active_policies; }; diff --git a/src/backend/scheduler.cc b/src/backend/scheduler.cc index b60ed4e..236ad78 100644 --- a/src/backend/scheduler.cc +++ b/src/backend/scheduler.cc @@ -29,9 +29,6 @@ using namespace std; using namespace sgpem; using namespace memory; -Scheduler* -Scheduler::_instance = 0; - //private constructor. The parameter is discarded Scheduler::Scheduler() : _policy_manager(PolicyManager::get_registered_manager()) @@ -39,14 +36,6 @@ Scheduler::Scheduler() _policy_manager.init(); } -Scheduler& -Scheduler::get_instance() -{ - if(!_instance) - _instance = new Scheduler(); - return *_instance; -} - SchedulableQueue* Scheduler::get_ready_queue() { diff --git a/src/backend/scheduler.hh b/src/backend/scheduler.hh index 8210d91..0497e0f 100644 --- a/src/backend/scheduler.hh +++ b/src/backend/scheduler.hh @@ -37,11 +37,13 @@ namespace sgpem #include "schedulable_queue.hh" #include "user_interrupt_exception.hh" +#include "singleton.hh" + namespace sgpem { - class Scheduler; + class Scheduler; - /** \brief Manages the DynamicSchedulable objects, implementing a given policy. + /** \brief Manages the DynamicSchedulable objects, implementing a given policy. Class Scheduler manages the schedulable entities which are ready to run, ordering them in a queue; it also checks that the current scheduling policy @@ -50,61 +52,49 @@ namespace sgpem the DynamicSchedulable objects (for further details about this, check class DynamicSchedulable). - */ + */ - class SG_DLLEXPORT Scheduler - { - public: - /** \brief Returns the unique instance of this class, conforming to the Singleton pattern. - * - * If Scheduler isn't initialized, creates it. Should be called at least once before - * starting the Simulation. - * \return the unique instance of this class, conforming to the Singleton pattern. - */ - static Scheduler& get_instance(); - /** - Returns a pointer to the queue containing all the ready - schedulable objects (for the policy to sort it). - \return a pointer to the queue containing all the ready - schedulable objects (for the policy to sort it). - */ - SchedulableQueue* get_ready_queue(); - /** - Resets the simulation to the initial state. - */ - void reset_status(); - /** - Generates a new SchedulableQueue representing the status of the processes - at the simulation instant next to the current one, and extends the History by - one instant with it. - */ - void step_forward() throw(UserInterruptException); - /** - Sets the policy that will be used to generate the simulation at the next instant. - \param policy the policy that will be used to generate the simulation at the next instant. - */ - /* DISABLED until we don't have PolicyManager::set_policy() - void set_policy(Policy* policy); - */ - /** - Returns the policy that will be used to generate the simulation at the next instant. - \return the policy that will be used to generate the simulation at the next instant. - */ - Policy& get_policy(); + class SG_DLLEXPORT Scheduler : public Singleton + { + friend class Singleton; + public: + /** + Returns a pointer to the queue containing all the ready + schedulable objects (for the policy to sort it). + \return a pointer to the queue containing all the ready + schedulable objects (for the policy to sort it). + */ + SchedulableQueue* get_ready_queue(); + /** + Resets the simulation to the initial state. + */ + void reset_status(); + /** + Generates a new SchedulableQueue representing the status of the processes + at the simulation instant next to the current one, and extends the History by + one instant with it. + */ + void step_forward() throw(UserInterruptException); + /** + Sets the policy that will be used to generate the simulation at the next instant. + \param policy the policy that will be used to generate the simulation at the next instant. + */ + /* DISABLED until we don't have PolicyManager::set_policy() + void set_policy(Policy* policy); + */ + /** + Returns the policy that will be used to generate the simulation at the next instant. + \return the policy that will be used to generate the simulation at the next instant. + */ + Policy& get_policy(); - private: - Scheduler(); //private constructor. - static Scheduler* _instance; - SchedulableQueue _ready_queue; - PolicyManager& _policy_manager; - }; + private: + Scheduler(); //private constructor. + SchedulableQueue _ready_queue; + PolicyManager& _policy_manager; + }; }//~ namespace sgpem #endif //SCHEDULER_HH - - - - - diff --git a/src/main.cc b/src/main.cc index ea19530..65a709a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -63,8 +63,9 @@ static void load_pyloader_plugin() { // Leaks willingly: Module* pyloader = 0; - GlobalPreferences::dir_iterator it = GlobalPreferences::instance().modules_dir_begin(); - while(it != GlobalPreferences::instance().modules_dir_end()) { + GlobalPreferences& prefs = GlobalPreferences::get_instance(); + GlobalPreferences::dir_iterator it = prefs.modules_dir_begin(); + while(it != prefs.modules_dir_end()) { std::string pyloader_path = Module::build_path(*it, "pyloader"); pyloader = new Module(pyloader_path); if(*pyloader) break; diff --git a/src/parse_opts.cc b/src/parse_opts.cc index c26422b..c558ca6 100644 --- a/src/parse_opts.cc +++ b/src/parse_opts.cc @@ -80,10 +80,10 @@ parse_options(int& argc, char**& argv) // FIXME : to be written! break; case 'P': - GlobalPreferences::instance().add_policies_dir(optarg); + GlobalPreferences::get_instance().add_policies_dir(optarg); break; case 'M': - GlobalPreferences::instance().add_modules_dir(optarg); + GlobalPreferences::get_instance().add_modules_dir(optarg); break; case ':': printf(_("[EE] Wrong number of parameters. Please see \n" diff --git a/src/templates/parameter.tcc b/src/templates/parameter.tcc index ce60062..579dd43 100644 --- a/src/templates/parameter.tcc +++ b/src/templates/parameter.tcc @@ -1,4 +1,4 @@ -// Src/templates/parameter.tcc - Copyright 2005, 2006, University +// src/templates/parameter.tcc - Copyright 2005, 2006, University // of Padova, dept. of Pure and Applied // Mathematics // diff --git a/src/templates/singleton.hh b/src/templates/singleton.hh new file mode 100644 index 0000000..cd139e6 --- /dev/null +++ b/src/templates/singleton.hh @@ -0,0 +1,59 @@ +// singleton.hh - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef SINGLETON_HH +#define SINGLETON_HH 1 + +#include +#include "config.h" + +namespace sgpem +{ + + /** \brief An abstract implementation of the Singleton design pattern. + * + * Singleton implementers constuctor will have to declare friendliness + * to Singleton::get_instance(). This also attempts to achieve + * thread-safeness. + */ + template + class SG_DLLEXPORT Singleton + { + public: + + /** \brief Ensures thread safety is respected, and returns the instantiated object + * + * This is done by locking _instance via a mutex, before intantiating the + * Instantiated_class attribute (if not done before). + * + * \return The instantiated object + */ + static Instantiated_class& get_instance(); + + private: + static Instantiated_class* _instance; + static Glib::StaticMutex _mutex; + }; //~ class Singleton + +} //~ namespace sgpem + + +#include "singleton.tcc" + +#endif //~ SINGLETON_HH + diff --git a/src/templates/singleton.tcc b/src/templates/singleton.tcc new file mode 100644 index 0000000..bcecc88 --- /dev/null +++ b/src/templates/singleton.tcc @@ -0,0 +1,45 @@ +// singleton.tcc - Copyright 2005, 2006, University +// of Padova, dept. of Pure and Applied +// Mathematics +// +// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +#ifndef SINGLETON_TCC +#define SINGLETON_TCC 1 + +#include "singleton.hh" + +template +Instantiated_class* +sgpem::Singleton::_instance = NULL; + +template +Glib::StaticMutex +sgpem::Singleton::_mutex = GLIBMM_STATIC_MUTEX_INIT; + + +template +Instantiated_class& +sgpem::Singleton::get_instance() +{ + Glib::Mutex::Lock lock(_mutex); + if(_instance == NULL) + _instance = new Instantiated_class(); + return *_instance; +} + + +#endif //~ SINGLETON_TCC +