diff --git a/Code/Mantid/Framework/Kernel/inc/MantidKernel/SingletonHolder.h b/Code/Mantid/Framework/Kernel/inc/MantidKernel/SingletonHolder.h index e189b49c31cd..faca5f0c1c22 100644 --- a/Code/Mantid/Framework/Kernel/inc/MantidKernel/SingletonHolder.h +++ b/Code/Mantid/Framework/Kernel/inc/MantidKernel/SingletonHolder.h @@ -44,6 +44,9 @@ namespace Mantid class SingletonHolder { public: + /// Allow users to access to the type returned by Instance() + typedef T HeldType; + static T& Instance(); private: diff --git a/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/TrackingInstanceMethod.h b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/TrackingInstanceMethod.h new file mode 100644 index 000000000000..1ed9b12a5487 --- /dev/null +++ b/Code/Mantid/Framework/PythonInterface/inc/MantidPythonInterface/kernel/TrackingInstanceMethod.h @@ -0,0 +1,93 @@ +#ifndef MANTID_PYTHONINTERFACE_TRACKINGINSTANCEMETHOD_H_ +#define MANTID_PYTHONINTERFACE_TRACKINGINSTANCEMETHOD_H_ + +/* + Copyright © 2014 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory + + This file is part of Mantid. + + Mantid 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 3 of the License, or + (at your option) any later version. + + Mantid 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, see . + + File change history is stored at: + Code Documentation is available at: + */ +#include + +namespace Mantid +{ + namespace PythonInterface + { + /** + * Add an Instance() & __del__ method to the already exported python type. + * The methods track how many times instance() & __del__ are called and clear the + * SingletonType object when the count reaches zero. + * @tparam SingletonType The main SingletonHolder type. It is expected to have a nested type + * HeldType that defines the implementation + * @tparam PythonType The boost.python C++ exported type + */ + template + class TrackingInstanceMethod + { + /// Type returned by instance() + typedef typename SingletonType::HeldType InstanceType; + + public: + /** + * Add the instance tracking methods + * @param classType The python type already exported using class_ + */ + static void define(PythonType & classType) + { + classType.def("__del__", &TrackingInstanceMethod::decref); + classType.def("Instance", &TrackingInstanceMethod::instance, + return_value_policy(), + "Return a reference to the singleton instance"); + classType.staticmethod("Instance"); + } + + /** + * Increment reference count & return the singleton instance + * @return A reference to the InstanceType + */ + static InstanceType &instance() + { + ++g_py_instance_count; + return SingletonType::Instance(); + } + + /** + * @param self The calling object + */ + static void decref(InstanceType & self) + { + --g_py_instance_count; + if (g_py_instance_count == 0) + { + self.clear(); + } + } + + private: + /// Track the number of calls to instance/decref + static size_t g_py_instance_count; + }; + + /// Initialize static counter + template + size_t TrackingInstanceMethod::g_py_instance_count = 0; + + } +} + +#endif /* MANTID_PYTHONINTERFACE_TRACKINGINSTANCEMETHOD */ diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp index c501b5edb2e4..c71750cf2350 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AlgorithmManager.cpp @@ -1,5 +1,6 @@ #include "MantidAPI/AlgorithmManager.h" #include "MantidPythonInterface/api/AlgorithmIDProxy.h" +#include "MantidPythonInterface/kernel/TrackingInstanceMethod.h" #include #include @@ -10,6 +11,7 @@ using namespace Mantid::API; using Mantid::PythonInterface::AlgorithmIDProxy; +using Mantid::PythonInterface::TrackingInstanceMethod; using namespace boost::python; namespace @@ -66,7 +68,9 @@ namespace void export_AlgorithmManager() { - class_("AlgorithmManagerImpl", no_init) + typedef class_ PythonType; + + auto pythonClass = class_("AlgorithmManagerImpl", no_init) .def("create", &AlgorithmManagerImpl::create, create_overloads((arg("name"), arg("version")), "Creates a managed algorithm.")) .def("createUnmanaged", &AlgorithmManagerImpl::createUnmanaged, createUnmanaged_overloads((arg("name"), arg("version")), "Creates an unmanaged algorithm.")) @@ -83,9 +87,9 @@ void export_AlgorithmManager() .def("clear", &AlgorithmManagerImpl::clear, "Clears the current list of managed algorithms") .def("cancelAll", &AlgorithmManagerImpl::cancelAll, "Requests that all currently running algorithms be cancelled") - - .def("Instance", &AlgorithmManager::Instance, return_value_policy(), - "Returns a reference to the AlgorithmManager singleton") - .staticmethod("Instance") ; + + // Instance method + TrackingInstanceMethod::define(pythonClass); + } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp index bdfebc28d73a..ffe453646bad 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/AnalysisDataService.cpp @@ -1,5 +1,6 @@ #include "MantidPythonInterface/kernel/DataServiceExporter.h" #include "MantidPythonInterface/kernel/Registry/DowncastRegistry.h" +#include "MantidPythonInterface/kernel/TrackingInstanceMethod.h" #include "MantidAPI/AnalysisDataService.h" #include "MantidAPI/Workspace.h" @@ -11,6 +12,7 @@ using namespace Mantid::API; using Mantid::PythonInterface::DataServiceExporter; +using Mantid::PythonInterface::TrackingInstanceMethod; using namespace Mantid::PythonInterface::Registry; using namespace boost::python; @@ -68,22 +70,18 @@ namespace void export_AnalysisDataService() { - - auto adsType = DataServiceExporter::define("AnalysisDataServiceImpl"); + typedef DataServiceExporter ADSExporter; + auto pythonClass = ADSExporter::define("AnalysisDataServiceImpl"); // -- special ADS behaviour -- // replace the add/addOrReplace,__setitem__ methods as we need to exact the exact stored type - adsType.def("add", &addItem, + pythonClass.def("add", &addItem, "Adds the given object to the service with the given name. If the name/object exists it will raise an error."); - adsType.def("addOrReplace", &addOrReplaceItem, + pythonClass.def("addOrReplace", &addOrReplaceItem, "Adds the given object to the service with the given name. The the name exists the object is replaced."); - adsType.def("__setitem__", &addOrReplaceItem); + pythonClass.def("__setitem__", &addOrReplaceItem); - // Add instance method for the ADS singleton - adsType.def("Instance", &AnalysisDataService::Instance, - return_value_policy(), - "Return a reference to the ADS singleton"); - adsType.staticmethod("Instance"); + // Instance method + TrackingInstanceMethod::define(pythonClass); } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/PropertyManagerDataService.cpp b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/PropertyManagerDataService.cpp index d2955e3d301c..65cab60bf180 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/PropertyManagerDataService.cpp +++ b/Code/Mantid/Framework/PythonInterface/mantid/api/src/Exports/PropertyManagerDataService.cpp @@ -1,4 +1,5 @@ #include "MantidPythonInterface/kernel/DataServiceExporter.h" +#include "MantidPythonInterface/kernel/TrackingInstanceMethod.h" #include "MantidAPI/PropertyManagerDataService.h" #include "MantidKernel/PropertyManager.h" @@ -7,6 +8,8 @@ using namespace Mantid::API; using namespace Mantid::Kernel; +using Mantid::PythonInterface::DataServiceExporter; +using Mantid::PythonInterface::TrackingInstanceMethod; using namespace boost::python; /// Weak pointer to DataItem typedef @@ -14,15 +17,14 @@ typedef boost::weak_ptr PropertyManager_wptr; void export_PropertyManagerDataService() { - using Mantid::PythonInterface::DataServiceExporter; register_ptr_to_python(); - auto pmdType = DataServiceExporter::define("PropertyManagerDataServiceImpl"); - pmdType.def("Instance", &PropertyManagerDataService::Instance, - return_value_policy(), - "Return a reference to the ADS singleton"); - pmdType.staticmethod("Instance"); + typedef DataServiceExporter PMDExporter; + auto pmdType = PMDExporter::define("PropertyManagerDataServiceImpl"); + + // Instance method + TrackingInstanceMethod::define(pmdType); + } diff --git a/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt b/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt index 9de90f326cc1..fa48f236c134 100644 --- a/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt +++ b/Code/Mantid/Framework/PythonInterface/mantid/kernel/CMakeLists.txt @@ -95,6 +95,7 @@ set ( INC_FILES ${HEADER_DIR}/kernel/PropertyWithValueExporter.h ${HEADER_DIR}/kernel/PythonObjectInstantiator.h ${HEADER_DIR}/kernel/StlExportDefinitions.h + ${HEADER_DIR}/kernel/TrackingInstanceMethod.h ${HEADER_DIR}/kernel/TypedValidatorExporter.h ) diff --git a/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt b/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt index 68f05f3c316c..4b639417edcf 100644 --- a/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt +++ b/Code/Mantid/MantidQt/CustomInterfaces/test/CMakeLists.txt @@ -6,11 +6,10 @@ if ( CXXTEST_FOUND ) set ( TESTHELPER_SRCS ../../../Framework/TestHelpers/src/ComponentCreationHelper.cpp ../../../Framework/TestHelpers/src/WorkspaceCreationHelper.cpp ../../../Framework/TestHelpers/src/ScopedFileHelper.cpp - ) + ../../../Framework/TestHelpers/src/TearDownWorld.cpp + ) if ( GMOCK_FOUND AND GTEST_FOUND ) - set ( TESTHELPER_SRCS ../../../Framework/TestHelpers/src/TearDownWorld.cpp ) - cxxtest_add_test ( CustomInterfacesTest ${TEST_FILES} ${GMOCK_TEST_FILES} ) target_link_libraries( CustomInterfacesTest CustomInterfaces DataObjects ${GMOCK_LIBRARIES} ${GTEST_LIBRARIES} ) add_dependencies( CustomInterfacesTest MDAlgorithms )