diff --git a/developer/doc/wiki/Schedules-in-the-Model-API-and-the-ScheduleTypeRegistry.md b/developer/doc/wiki/Schedules-in-the-Model-API-and-the-ScheduleTypeRegistry.md index 3a46a727fe7..d8ea62b2a63 100644 --- a/developer/doc/wiki/Schedules-in-the-Model-API-and-the-ScheduleTypeRegistry.md +++ b/developer/doc/wiki/Schedules-in-the-Model-API-and-the-ScheduleTypeRegistry.md @@ -107,10 +107,10 @@ This should be somewhat self-explanatory since the functions are well-named, but 2. If not, try to either find a compatible `ScheduleTypeLimits` or create a new one to set it to the `Schedule` * **That part can be quite confusing the first time you realize it happens behind the scenes when you call a setter and your `Schedule` now has a `ScheduleTypeLimits`. This is also why you can't have a setter take in a `const Schedule&`**: `bool setOpeningAreaFractionSchedule(Schedule&);` works, but `bool setOpeningAreaFractionSchedule(const Schedule&);` doesn't, since the `Schedule` passed can be modified. -Both of these flow branches will call into `getScheduleType`, which uses the entries you have manually set in the ScheduleTypeRegistrySingleton around [here](https://github.com/NREL/OpenStudio/blob/develop/src/model/ScheduleTypeRegistry.cpp#L118-L125): +Both of these flow branches will call into `getScheduleType`, which uses the entries you have manually set in the ScheduleTypeRegistry around [here](https://github.com/NREL/OpenStudio/blob/develop/src/model/ScheduleTypeRegistry.cpp#L118-L125): ```c++ -ScheduleTypeRegistrySingleton::ScheduleTypeRegistrySingleton() +ScheduleTypeRegistry::ScheduleTypeRegistry() { // className, scheduleDisplayName, scheduleRelationshipName, isContinuous, unitType, lowerLimitValue, upperLimitValue; @@ -133,6 +133,6 @@ For 1) above , the definition of [isCompatible](https://github.com/NREL/OpenStud ### When you don't already have a `ScheduleTypeLimits` assigned -For 2) when you are using a `Schedule` that doesn't already have a `ScheduleTypeLimits`, it'll loop on all `ScheduleTypeLimits` in the model, and call `isCompatible` on them and return the first one that matches the requirements. +For 2) when you are using a `Schedule` that doesn't already have a `ScheduleTypeLimits`, it'll loop on all `ScheduleTypeLimits` in the model, and call `isCompatible` on them and return the first one that matches the requirements. -**If not it'll create a new one with the requirements**. cf [ScheduleTypeRegistrySingleton::getOrCreateScheduleTypeLimits](https://github.com/NREL/OpenStudio/blob/8ae4d883ed1a6ba704aa8b60003646de69a00f39/src/model/ScheduleTypeRegistry.cpp#L77-L116) +**If not it'll create a new one with the requirements**. cf [ScheduleTypeRegistry::getOrCreateScheduleTypeLimits](https://github.com/NREL/OpenStudio/blob/8ae4d883ed1a6ba704aa8b60003646de69a00f39/src/model/ScheduleTypeRegistry.cpp#L77-L116) diff --git a/developer/ruby/SubProjectClassGenerators/ModelClassGenerator.rb b/developer/ruby/SubProjectClassGenerators/ModelClassGenerator.rb index 016f785e0a1..3b37f467bd5 100644 --- a/developer/ruby/SubProjectClassGenerators/ModelClassGenerator.rb +++ b/developer/ruby/SubProjectClassGenerators/ModelClassGenerator.rb @@ -1685,7 +1685,7 @@ def gtestGetterSetters def aux() result = String.new if @hasScheduleFields - result << "// TODO: Copy-paste this starter text into ScheduleTypeRegistry.cpp, in the ScheduleTypeRegistrySingleton\n" + result << "// TODO: Copy-paste this starter text into ScheduleTypeRegistry.cpp\n" result << "// constructor. Read the EnergyPlus Input-Output reference and fill out the ScheduleTypeLimits information\n" result << "// accordingly.\n" @nonextensibleFields.each { |field| diff --git a/src/energyplus/EnergyPlus.i b/src/energyplus/EnergyPlus.i index fd7b3c7c80d..ebe68cc007b 100644 --- a/src/energyplus/EnergyPlus.i +++ b/src/energyplus/EnergyPlus.i @@ -42,7 +42,6 @@ // Ignore Static Initializers %ignore openstudio::energyplus::detail; -%ignore StaticInitializer; %ignore ForwardTranslatorInitializer; %ignore openstudio::energyplus::detail::ForwardTranslatorInitializer; diff --git a/src/generateiddfactory/GenerateIddFactory.cpp b/src/generateiddfactory/GenerateIddFactory.cpp index bcd793b19dc..2a758f9aa90 100644 --- a/src/generateiddfactory/GenerateIddFactory.cpp +++ b/src/generateiddfactory/GenerateIddFactory.cpp @@ -57,158 +57,149 @@ void initializeOutFiles(GenerateIddFactoryOutFiles& outFiles, const std::vector< << '\n'; // write IddFactory.hxx - outFiles.iddFactoryHxx.tempFile << "#ifndef UTILITIES_IDD_IDDFACTORY_HXX" << '\n' - << "#define UTILITIES_IDD_IDDFACTORY_HXX" << '\n' - << '\n' - << "#include " << '\n' - << '\n' - << "#include " << '\n' - << "#include " << '\n' - << "#include " << '\n' - << "#include " << '\n' - << '\n' - << "#include " << '\n' - << "#include " << '\n' - << "#include " << '\n' - << '\n' - << "#include " << '\n' - << '\n' - << "namespace openstudio{" << '\n' - << '\n' - << "/** IddFactorySingleton can return \\link IddObject IddObjects\\endlink and \\link IddFile" << '\n' - << " * IddFiles\\endlink for the current version of EnergyPlus and OpenStudio. It can return \\link IddFile " - << '\n' - << " * IddFiles\\endlink only (no link with other methods in this class, for instance, no " << '\n' - << " * by-IddObjectType access to individual \\link IddObject IddObjects\\endlink) for " << '\n' - << " * previous versions of OpenStudio, back to version 0.7.0. It also supports the default IddObject " << '\n' - << " * type, Catchall, which is provided to enable the display of IdfObjects with misspelled type " << '\n' - << " * names, and a CommentOnly object. Its primary function is to establish a single set of IDD schema " << '\n' - << " * across all of OpenStudio, thereby ensuring consistency and reducing file I-O. " << '\n' - << " * " << '\n' - << " * IddFactorySingleton should be used through the IddFactory typedef as in" << '\n' - << " * \\code" << '\n' - << " * IddFile osIddFile = IddFactory::instance().iddFile(IddFileType::OpenStudio);" << '\n' - << " * \\endcode */" << '\n' - << "class UTILITIES_API IddFactorySingleton {" << '\n' - << '\n' - << " friend class Singleton;" << '\n' - << '\n' - << " public:" << '\n' - << " /** @name Getters */" << '\n' - << " //@{ " << '\n' - << '\n' - << " /** Get the file version. Throws if fileType == IddFileType::UserCustom or " << '\n' - << " * IddFileType::WholeFactory. */" << '\n' - << " std::string getVersion(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Get the file header. Throws if fileType == IddFileType::UserCustom or " << '\n' - << " * IddFileType::WholeFactory. */" << '\n' - << " std::string getHeader(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return all \\link IddObject IddObjects\\endlink registered in factory. */" << '\n' - << " std::vector objects() const;" << '\n' - << '\n' - << " /** Return all \\link IddObject IddObjects\\endlink in IddFileType type. */" << '\n' - << " std::vector getObjects(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return all groups in the factory (e.g. \"\" and \"Simulation Parameters\"). */" << '\n' - << " std::vector groups() const;" << '\n' - << '\n' - << " /** Return all groups in fileType. */" << '\n' - << " std::vector getGroups(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return all \\link IddObject IddObjects\\endlink in group (e.g. \"Simulation Parameters\"). */" << '\n' - << " std::vector getObjectsInGroup(const std::string& group) const;" << '\n' - << '\n' - << " /** Return all \\link IddObject IddObjects\\endlink in group and fileType. */" << '\n' - << " std::vector getObjectsInGroup(const std::string& group, IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return all \\link IddObject IddObjects\\endlink that match objectRegex. */" << '\n' - << " std::vector getObjects(const boost::regex& objectRegex) const;" << '\n' - << '\n' - << " /** Return all \\link IddObject IddObjects\\endlink that match objectRegex and are in fileType. */" << '\n' - << " std::vector getObjects(const boost::regex& objectRegex, IddFileType fileType) const;" << '\n' - << '\n' - << " /** Returns the version IddObject for fileType. Throws if fileType == IddFileType::UserCustom " << '\n' - << " * or IddFileType::WholeFactory. */" << '\n' - << " IddObject getVersionObject(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return the IddObject with .name() objectName, if it exists in the factory. */" << '\n' - << " boost::optional getObject(const std::string& objectName) const;" << '\n' - << '\n' - << " /** Return the IddObject corresponding to objectType. Returns false if type == " << '\n' - << " * IddObjectType::UserCustom. */" << '\n' - << " boost::optional getObject(IddObjectType objectType) const;" << '\n' - << '\n' - << " /** Return all objects in the factory that are required. */" << '\n' - << " std::vector requiredObjects() const;" << '\n' - << '\n' - << " /** Return all objects in IddFile fileType that are required. */" << '\n' - << " std::vector getRequiredObjects(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return all objects in the factory that are unique. */" << '\n' - << " std::vector uniqueObjects() const;" << '\n' - << '\n' - << " /** Return all objects in IddFile fileType that are unique. */" << '\n' - << " std::vector getUniqueObjects(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return the (current) IddFile corresponding to type. */" << '\n' - << " IddFile getIddFile(IddFileType fileType) const;" << '\n' - << '\n' - << " /** Return the IddFile corresponding to type and version. Unless version is equal to " << '\n' - << " * VersionString(getVersion(fileType)), files are loaded from disk and returned as " << '\n' - << " * IddFileType::UserCustom, to distinguish them from the IDD information wrapped by " << '\n' - << " * the IddFactory. At this time, only IddFileType::OpenStudio files are supported, " << '\n' - << " * and only for valid version identifiers >= VersionString(\"0.7.0\"). Returns false " << '\n' - << " * in all other cases. */" << '\n' - << " boost::optional getIddFile(IddFileType fileType, const VersionString& version) const;" << '\n' - << '\n' - << " //@}" << '\n' - << " /** @name Queries */" << '\n' - << " //@{" << '\n' - << '\n' - << " /** Returns true if IddObject of objectType belongs to IddFile of fileType. " << '\n' - << " * IddObjectType::Catchall is in no \\link IddFile IddFiles\\endlink; " << '\n' - << " * IddObjectType::CommentOnly is in all \\link IddFile IddFiles\\endlink. */" << '\n' - << " bool isInFile(IddObjectType objectType, IddFileType fileType) const;" << '\n' - << '\n' - << " //@}" << '\n' - << " private:" << '\n' - << '\n' - << " IddFactorySingleton();" << '\n'; + outFiles.iddFactoryHxx.tempFile << R"hpp(#ifndef UTILITIES_IDD_IDDFACTORY_HXX +#define UTILITIES_IDD_IDDFACTORY_HXX + +#include + +#include +#include +#include +#include + +#include +#include + +#include + +namespace openstudio{ + +/** IddFactory is a Singleton can return \link IddObject IddObjects\endlink and \link IddFile + * IddFiles\endlink for the current version of EnergyPlus and OpenStudio. It can return \link IddFile + * IddFiles\endlink only (no link with other methods in this class, for instance, no + * by-IddObjectType access to individual \link IddObject IddObjects\endlink) for + * previous versions of OpenStudio, back to version 0.7.0. It also supports the default IddObject + * type, Catchall, which is provided to enable the display of IdfObjects with misspelled type + * names, and a CommentOnly object. Its primary function is to establish a single set of IDD schema + * across all of OpenStudio, thereby ensuring consistency and reducing file I-O. + **/ +class UTILITIES_API IddFactory { + + public: + + static IddFactory& instance(); + + IddFactory(const IddFactory& other) = delete; + IddFactory(IddFactory&& other) = delete; + IddFactory& operator=(const IddFactory&) = delete; + IddFactory& operator=(IddFactory&&) = delete; + + /** @name Getters */ + //@{ + + /** Get the file version. Throws if fileType == IddFileType::UserCustom or + * IddFileType::WholeFactory. */ + std::string getVersion(IddFileType fileType) const; + + /** Get the file header. Throws if fileType == IddFileType::UserCustom or + * IddFileType::WholeFactory. */ + std::string getHeader(IddFileType fileType) const; + + /** Return all \link IddObject IddObjects\endlink registered in factory. */ + std::vector objects() const; + + /** Return all \link IddObject IddObjects\endlink in IddFileType type. */ + std::vector getObjects(IddFileType fileType) const; + + /** Return all groups in the factory (e.g. "" and "Simulation Parameters"). */ + std::vector groups() const; + + /** Return all groups in fileType. */ + std::vector getGroups(IddFileType fileType) const; + + /** Return all \link IddObject IddObjects\endlink in group (e.g. "Simulation Parameters"). */ + std::vector getObjectsInGroup(const std::string& group) const; + + /** Return all \link IddObject IddObjects\endlink in group and fileType. */ + std::vector getObjectsInGroup(const std::string& group, IddFileType fileType) const; + + /** Return all \link IddObject IddObjects\endlink that match objectRegex. */ + std::vector getObjects(const boost::regex& objectRegex) const; + + /** Return all \link IddObject IddObjects\endlink that match objectRegex and are in fileType. */ + std::vector getObjects(const boost::regex& objectRegex, IddFileType fileType) const; + + /** Returns the version IddObject for fileType. Throws if fileType == IddFileType::UserCustom + * or IddFileType::WholeFactory. */ + IddObject getVersionObject(IddFileType fileType) const; + + /** Return the IddObject with .name() objectName, if it exists in the factory. */ + boost::optional getObject(const std::string& objectName) const; + + /** Return the IddObject corresponding to objectType. Returns false if type == + * IddObjectType::UserCustom. */ + boost::optional getObject(IddObjectType objectType) const; + + /** Return all objects in the factory that are required. */ + std::vector requiredObjects() const; + + /** Return all objects in IddFile fileType that are required. */ + std::vector getRequiredObjects(IddFileType fileType) const; + + /** Return all objects in the factory that are unique. */ + std::vector uniqueObjects() const; + + /** Return all objects in IddFile fileType that are unique. */ + std::vector getUniqueObjects(IddFileType fileType) const; + + /** Return the (current) IddFile corresponding to type. */ + IddFile getIddFile(IddFileType fileType) const; + + /** Return the IddFile corresponding to type and version. Unless version is equal to + * VersionString(getVersion(fileType)), files are loaded from disk and returned as + * IddFileType::UserCustom, to distinguish them from the IDD information wrapped by + * the IddFactory. At this time, only IddFileType::OpenStudio files are supported, + * and only for valid version identifiers >= VersionString("0.7.0"). Returns false + * in all other cases. */ + boost::optional getIddFile(IddFileType fileType, const VersionString& version) const; + + //@} + /** @name Queries */ + //@{ + + /** Returns true if IddObject of objectType belongs to IddFile of fileType. + * IddObjectType::Catchall is in no \link IddFile IddFiles\endlink; + * IddObjectType::CommentOnly is in all \link IddFile IddFiles\endlink. */ + bool isInFile(IddObjectType objectType, IddFileType fileType) const; + + //@} + private: + + IddFactory(); + ~IddFactory() = default; +)hpp"; + for (const IddFileFactoryData& iddFile : iddFiles) { outFiles.iddFactoryHxx.tempFile << " void register" << iddFile.fileName() << "ObjectsInCallbackMap();" << '\n'; } - outFiles.iddFactoryHxx.tempFile << '\n' - << " REGISTER_LOGGER(\"utilities.idd.IddFactory\");" << '\n' - << '\n' - << " typedef std::function CreateIddObjectCallback;" << '\n' - << " typedef std::map IddObjectCallbackMap;" << '\n' - << " IddObjectCallbackMap m_callbackMap;" << '\n' - << '\n' - << " typedef std::multimap IddObjectSourceFileMap;" << '\n' - << " IddObjectSourceFileMap m_sourceFileMap;" << '\n' - << '\n' - << " mutable std::map m_osIddFiles;" << '\n' - << "};" << '\n' - << '\n' - << "#if _WIN32 || _MSC_VER" << '\n' - << " // Explicitly instantiate and export IddFactorySingleton Singleton template instance" << '\n' - << " // so that the same instance is shared between DLLs that link to Utilities.dll." << '\n' - << " UTILITIES_TEMPLATE_EXT template class UTILITIES_API openstudio::Singleton;" << '\n' - << "#endif" << '\n' - << '\n' - << "/** Convenience typedef for accessing IddFactorySingleton. Usage:" << '\n' - << " * \\code" << '\n' - << " * unsigned n = IddFactory::instance().objects().size();" << '\n' - << " * \\endcode" << '\n' - << " * " << '\n' - << " * \\relates IddFactorySingleton */" << '\n' - << "typedef openstudio::Singleton IddFactory;" << '\n' - << '\n' - << "} // openstudio" << '\n' - << '\n' - << "#endif //UTILITIES_IDD_IDDFACTORY_HXX" << '\n'; + + outFiles.iddFactoryHxx.tempFile << R"hpp( + REGISTER_LOGGER("utilities.idd.IddFactory"); + + using CreateIddObjectCallback = std::function; + using IddObjectCallbackMap = std::map; + IddObjectCallbackMap m_callbackMap; + + using IddObjectSourceFileMap = std::multimap; + IddObjectSourceFileMap m_sourceFileMap; + + mutable std::map m_osIddFiles; +}; + +} // openstudio + +#endif //UTILITIES_IDD_IDDFACTORY_HXX +)hpp"; // start IddFactory.cxx outFiles.iddFactoryCxx.tempFile << "#include " << '\n' @@ -309,14 +300,19 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " }(); // immediately invoked lambda" << '\n' << '\n' << " return object;" << '\n' - << "}" << '\n'; + << "}" << '\n' + << '\n'; + + // static instance as a Singleton + outFiles.iddFactoryCxx.tempFile << R"cpp(IddFactory& IddFactory::instance() { + static IddFactory instance; + return instance; +} + +)cpp"; // constructor - outFiles.iddFactoryCxx.tempFile << '\n' - << "IddFactorySingleton::IddFactorySingleton() {" << '\n' - << '\n' - << " // initialize callback map" << '\n' - << '\n'; + outFiles.iddFactoryCxx.tempFile << "IddFactory::IddFactory() {" << '\n' << '\n' << " // initialize callback map" << '\n' << '\n'; // register create functions in the callback map // Catchall outFiles.iddFactoryCxx.tempFile << " m_callbackMap.insert(IddObjectCallbackMap::value_type(IddObjectType::Catchall," @@ -395,7 +391,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto // version and header getters outFiles.iddFactoryCxx.tempFile << '\n' - << "std::string IddFactorySingleton::getVersion(IddFileType fileType) const {" << '\n' + << "std::string IddFactory::getVersion(IddFileType fileType) const {" << '\n' << " std::string result;" << '\n' << '\n' << " switch (fileType.value()) {" << '\n'; @@ -411,7 +407,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::string IddFactorySingleton::getHeader(IddFileType fileType) const {" << '\n' + << "std::string IddFactory::getHeader(IddFileType fileType) const {" << '\n' << " std::stringstream result;" << '\n' << " switch (fileType.value()) {" << '\n'; for (const IddFileFactoryData& idd : iddFiles) { @@ -448,7 +444,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto // object getters outFiles.iddFactoryCxx.tempFile << '\n' - << "std::vector IddFactorySingleton::objects() const {" << '\n' + << "std::vector IddFactory::objects() const {" << '\n' << " IddObjectVector result;" << '\n' << '\n' << " for (IddObjectCallbackMap::const_iterator it = m_callbackMap.begin()," << '\n' @@ -459,7 +455,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getObjects(IddFileType fileType) const {" << '\n' + << "std::vector IddFactory::getObjects(IddFileType fileType) const {" << '\n' << " IddObjectVector result;" << '\n' << '\n' << " for(IddObjectCallbackMap::const_iterator it = m_callbackMap.begin()," << '\n' @@ -472,7 +468,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::groups() const {" << '\n' + << "std::vector IddFactory::groups() const {" << '\n' << " StringSet result;" << '\n' << " for (const IddObject& object : objects()) {" << '\n' << " result.insert(object.group());" << '\n' @@ -480,7 +476,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return StringVector(result.begin(),result.end());" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getGroups(IddFileType fileType) const {" << '\n' + << "std::vector IddFactory::getGroups(IddFileType fileType) const {" << '\n' << " StringSet result;" << '\n' << " for (const IddObject& object : getObjects(fileType)) {" << '\n' << " result.insert(object.group());" << '\n' @@ -488,7 +484,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return StringVector(result.begin(),result.end());" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getObjectsInGroup(const std::string& group) const {" << '\n' + << "std::vector IddFactory::getObjectsInGroup(const std::string& group) const {" << '\n' << " IddObjectVector result;" << '\n' << " for (const IddObject& object : objects()) {" << '\n' << " if (istringEqual(object.group(),group)) {" << '\n' @@ -498,7 +494,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getObjectsInGroup(const std::string& group, IddFileType fileType) const {" << '\n' + << "std::vector IddFactory::getObjectsInGroup(const std::string& group, IddFileType fileType) const {" << '\n' << " IddObjectVector result;" << '\n' << " for (const IddObject& object : getObjects(fileType)) {" << '\n' << " if (istringEqual(object.group(),group)) {" << '\n' @@ -508,7 +504,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getObjects(const boost::regex& objectRegex) const {" << '\n' + << "std::vector IddFactory::getObjects(const boost::regex& objectRegex) const {" << '\n' << " IddObjectVector result;" << '\n' << '\n' << " for (int value : IddObjectType::getValues()) {" << '\n' @@ -525,7 +521,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getObjects(const boost::regex& objectRegex," << '\n' + << "std::vector IddFactory::getObjects(const boost::regex& objectRegex," << '\n' << " IddFileType fileType) const " << '\n' << "{" << '\n' << " IddObjectVector result;" << '\n' @@ -545,7 +541,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "IddObject IddFactorySingleton::getVersionObject(IddFileType fileType) const {" << '\n' + << "IddObject IddFactory::getVersionObject(IddFileType fileType) const {" << '\n' << " if (fileType == IddFileType::EnergyPlus) {" << '\n' << " return getObject(IddObjectType(IddObjectType::Version)).get();" << '\n' << " }" << '\n' @@ -558,7 +554,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return IddObject();" << '\n' << "}" << '\n' << '\n' - << "boost::optional IddFactorySingleton::getObject(const std::string& objectName) const" << '\n' + << "boost::optional IddFactory::getObject(const std::string& objectName) const" << '\n' << "{" << '\n' << " OptionalIddObject result;" << '\n' << '\n' @@ -572,7 +568,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "boost::optional IddFactorySingleton::getObject(IddObjectType objectType) const" << '\n' + << "boost::optional IddFactory::getObject(IddObjectType objectType) const" << '\n' << "{" << '\n' << " OptionalIddObject result;" << '\n' << '\n' @@ -591,7 +587,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto // required, unique, and required or unique objects outFiles.iddFactoryCxx.tempFile << '\n' - << "std::vector IddFactorySingleton::requiredObjects() const {" << '\n' + << "std::vector IddFactory::requiredObjects() const {" << '\n' << '\n' << " IddObjectVector result;" << '\n' << '\n' @@ -606,7 +602,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getRequiredObjects(IddFileType fileType) const {" << '\n' + << "std::vector IddFactory::getRequiredObjects(IddFileType fileType) const {" << '\n' << '\n' << " IddObjectVector result; " << '\n' << '\n' @@ -623,7 +619,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::uniqueObjects() const {" << '\n' + << "std::vector IddFactory::uniqueObjects() const {" << '\n' << '\n' << " IddObjectVector result;" << '\n' << '\n' @@ -638,7 +634,7 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << " return result;" << '\n' << "}" << '\n' << '\n' - << "std::vector IddFactorySingleton::getUniqueObjects(IddFileType fileType) const {" << '\n' + << "std::vector IddFactory::getUniqueObjects(IddFileType fileType) const {" << '\n' << '\n' << " IddObjectVector result; " << '\n' << '\n' @@ -657,79 +653,79 @@ void completeOutFiles(const IddFileFactoryDataVector& iddFiles, GenerateIddFacto << "}" << '\n'; // iddFile getters - outFiles.iddFactoryCxx.tempFile - << '\n' - << "IddFile IddFactorySingleton::getIddFile(IddFileType fileType) const {" << '\n' - << " IddFile result;" << '\n' - << '\n' - << " if (fileType == IddFileType::UserCustom) {" << '\n' - << " return result; " << '\n' - << " }" << '\n' - << '\n' - << " // Add the IddObjects." << '\n' - << " for(IddObjectCallbackMap::const_iterator it = m_callbackMap.begin()," << '\n' - << " itend = m_callbackMap.end(); it != itend; ++it) {" << '\n' - << " if (isInFile(it->first,fileType)) {" << '\n' - << " result.addObject(it->second());" << '\n' - << " }" << '\n' - << " }" << '\n' - << '\n' - << " // Set the file version and header." << '\n' - << " try {" << '\n' - << " result.setVersion(getVersion(fileType));" << '\n' - << " result.setHeader(getHeader(fileType));" << '\n' - << " }" << '\n' - << " catch (...) {}" << '\n' - << '\n' - << " return result;" << '\n' - << "}" << '\n' - << '\n' - << "boost::optional IddFactorySingleton::getIddFile(IddFileType fileType, const VersionString& version) const {" << '\n' - << " OptionalIddFile result;" << '\n' - << '\n' - << " if (fileType == IddFileType::UserCustom) {" << '\n' - << " return result; " << '\n' - << " }" << '\n' - << '\n' - << " if (fileType == IddFileType::WholeFactory) {" << '\n' - << " LOG(Warn,\"Cannot return the WholeFactory IddFile by version.\");" << '\n' - << " return result;" << '\n' - << " }" << '\n' - << '\n' - << " if (fileType == IddFileType::EnergyPlus) {" << '\n' - << " LOG(Warn,\"At this time, OpenStudio cannot return EnergyPlus IDD files by version.\");" << '\n' - << " return result;" << '\n' - << " }" << '\n' - << '\n' - << " VersionString currentVersion(openStudioVersion());" << '\n' - << " OS_ASSERT(fileType == IddFileType::OpenStudio);" << '\n' - << " if (version == currentVersion) {" << '\n' - << " return getIddFile(fileType);" << '\n' - << " }" << '\n' - << " else {" << '\n' - << " std::map::const_iterator it = m_osIddFiles.find(version);" << '\n' - << " if (it != m_osIddFiles.end()) {" << '\n' - << " return it->second;" << '\n' - << " }" << '\n' - << " std::string iddPath = \":/idd/versions\";" << '\n' - << " std::stringstream folderString;" << '\n' - << " folderString << version.major() << \"_\" << version.minor() << \"_\" << version.patch().get();" << '\n' - << " iddPath += \"/\" + folderString.str() + \"/OpenStudio.idd\";" << '\n' - << " if (::openstudio::embedded_files::hasFile(iddPath) && (version < currentVersion)) {" << '\n' - << " std::stringstream ss;" << '\n' - << " ss << ::openstudio::embedded_files::getFileAsString(iddPath);" << '\n' - << " result = IddFile::load(ss);" << '\n' - << " }" << '\n' - << " if (result) {" << '\n' - << " m_osIddFiles[version] = *result;" << '\n' - << " }" << '\n' - << " }" << '\n' - << " return result;" << '\n' - << "}" << '\n'; + outFiles.iddFactoryCxx.tempFile << '\n' + << "IddFile IddFactory::getIddFile(IddFileType fileType) const {" << '\n' + << " IddFile result;" << '\n' + << '\n' + << " if (fileType == IddFileType::UserCustom) {" << '\n' + << " return result; " << '\n' + << " }" << '\n' + << '\n' + << " // Add the IddObjects." << '\n' + << " for(IddObjectCallbackMap::const_iterator it = m_callbackMap.begin()," << '\n' + << " itend = m_callbackMap.end(); it != itend; ++it) {" << '\n' + << " if (isInFile(it->first,fileType)) {" << '\n' + << " result.addObject(it->second());" << '\n' + << " }" << '\n' + << " }" << '\n' + << '\n' + << " // Set the file version and header." << '\n' + << " try {" << '\n' + << " result.setVersion(getVersion(fileType));" << '\n' + << " result.setHeader(getHeader(fileType));" << '\n' + << " }" << '\n' + << " catch (...) {}" << '\n' + << '\n' + << " return result;" << '\n' + << "}" << '\n' + << '\n' + << "boost::optional IddFactory::getIddFile(IddFileType fileType, const VersionString& version) const {" + << '\n' + << " OptionalIddFile result;" << '\n' + << '\n' + << " if (fileType == IddFileType::UserCustom) {" << '\n' + << " return result; " << '\n' + << " }" << '\n' + << '\n' + << " if (fileType == IddFileType::WholeFactory) {" << '\n' + << " LOG(Warn,\"Cannot return the WholeFactory IddFile by version.\");" << '\n' + << " return result;" << '\n' + << " }" << '\n' + << '\n' + << " if (fileType == IddFileType::EnergyPlus) {" << '\n' + << " LOG(Warn,\"At this time, OpenStudio cannot return EnergyPlus IDD files by version.\");" << '\n' + << " return result;" << '\n' + << " }" << '\n' + << '\n' + << " VersionString currentVersion(openStudioVersion());" << '\n' + << " OS_ASSERT(fileType == IddFileType::OpenStudio);" << '\n' + << " if (version == currentVersion) {" << '\n' + << " return getIddFile(fileType);" << '\n' + << " }" << '\n' + << " else {" << '\n' + << " std::map::const_iterator it = m_osIddFiles.find(version);" << '\n' + << " if (it != m_osIddFiles.end()) {" << '\n' + << " return it->second;" << '\n' + << " }" << '\n' + << " std::string iddPath = \":/idd/versions\";" << '\n' + << " std::stringstream folderString;" << '\n' + << " folderString << version.major() << \"_\" << version.minor() << \"_\" << version.patch().get();" << '\n' + << " iddPath += \"/\" + folderString.str() + \"/OpenStudio.idd\";" << '\n' + << " if (::openstudio::embedded_files::hasFile(iddPath) && (version < currentVersion)) {" << '\n' + << " std::stringstream ss;" << '\n' + << " ss << ::openstudio::embedded_files::getFileAsString(iddPath);" << '\n' + << " result = IddFile::load(ss);" << '\n' + << " }" << '\n' + << " if (result) {" << '\n' + << " m_osIddFiles[version] = *result;" << '\n' + << " }" << '\n' + << " }" << '\n' + << " return result;" << '\n' + << "}" << '\n'; // query whether object is in file outFiles.iddFactoryCxx.tempFile << '\n' - << "bool IddFactorySingleton::isInFile(IddObjectType objectType, IddFileType fileType) const {" << '\n' + << "bool IddFactory::isInFile(IddObjectType objectType, IddFileType fileType) const {" << '\n' << " typedef IddObjectSourceFileMap::const_iterator const_iterator;" << '\n' << " std::pair range;" << '\n' << " range = m_sourceFileMap.equal_range(objectType);" << '\n' diff --git a/src/generateiddfactory/IddFileFactoryData.cpp b/src/generateiddfactory/IddFileFactoryData.cpp index 5c0332c2f29..70a39e8166f 100644 --- a/src/generateiddfactory/IddFileFactoryData.cpp +++ b/src/generateiddfactory/IddFileFactoryData.cpp @@ -346,7 +346,7 @@ void IddFileFactoryData::parseFile(const path& outPath, const std::string& outFi } // register objects with CallbackMap - cxxFile->tempFile << "void IddFactorySingleton::register" << fileName() << "ObjectsInCallbackMap() {" << '\n'; + cxxFile->tempFile << "void IddFactory::register" << fileName() << "ObjectsInCallbackMap() {" << '\n'; for (const StringPair& objectName : objectNames()) { cxxFile->tempFile << " m_callbackMap.insert(IddObjectCallbackMap::value_type(IddObjectType::" << objectName.first << ",create" << objectName.first << "IddObject));" << '\n'; diff --git a/src/model/OutputMeter_Impl.hpp b/src/model/OutputMeter_Impl.hpp index 7098e64c0df..1c9e744a1b3 100644 --- a/src/model/OutputMeter_Impl.hpp +++ b/src/model/OutputMeter_Impl.hpp @@ -10,8 +10,6 @@ #include "ModelObject_Impl.hpp" #include "OutputMeter.hpp" -#include "../utilities/core/StaticInitializer.hpp" - namespace openstudio { class EndUseType; diff --git a/src/model/Schedule.hpp b/src/model/Schedule.hpp index 2b3b0aae739..9ed2cf5b8e3 100644 --- a/src/model/Schedule.hpp +++ b/src/model/Schedule.hpp @@ -26,7 +26,7 @@ namespace model { * \li OS:Schedule:VariableInterval * * For detailed information on ScheduleTypeLimits, please see ScheduleBase and - * \link ScheduleTypeRegistrySingleton ScheduleTypeRegistry \endlink. In general, ModelObject + * \link ScheduleTypeRegistry ScheduleTypeRegistry \endlink. In general, ModelObject * setters that take a Schedule will fail if the ScheduleTypeLimits are set and are incompatible * with the proposed use. This ensures that the Schedule is written using units and bounds * expected by the user object (e.g. fractional for lighting schedules, W for people activity diff --git a/src/model/ScheduleBase.hpp b/src/model/ScheduleBase.hpp index 8e273ad0476..3be8834de7a 100644 --- a/src/model/ScheduleBase.hpp +++ b/src/model/ScheduleBase.hpp @@ -23,7 +23,7 @@ namespace model { /** ScheduleBase is a ResourceObject that serves as a base class for Schedule and ScheduleDay, * that is, objects with ScheduleTypeLimits. This class provides getters and setters for * ScheduleTypeLimits. Note that while users can explicitly set their own ScheduleTypeLimits, - * we recommend using the \link ScheduleTypeRegistrySingleton ScheduleTypeRegistry\endlink and + * we recommend using the \link ScheduleTypeRegistry ScheduleTypeRegistry\endlink and * related non-member functions, or letting user \link ModelObject ModelObjects\endlink set * this field, instead. */ class MODEL_API ScheduleBase : public ResourceObject diff --git a/src/model/ScheduleTypeRegistry.cpp b/src/model/ScheduleTypeRegistry.cpp index 6ede93052ba..c3fad35a17c 100644 --- a/src/model/ScheduleTypeRegistry.cpp +++ b/src/model/ScheduleTypeRegistry.cpp @@ -17,7 +17,7 @@ namespace openstudio { namespace model { - std::vector ScheduleTypeRegistrySingleton::classNames() const { + std::vector ScheduleTypeRegistry::classNames() const { StringVector result; for (const ClassNameToScheduleTypesMap::value_type& p : m_classNameToScheduleTypesMap) { result.push_back(p.first); @@ -25,7 +25,7 @@ namespace model { return result; } - std::vector ScheduleTypeRegistrySingleton::getScheduleTypesByClassName(const std::string& className) const { + std::vector ScheduleTypeRegistry::getScheduleTypesByClassName(const std::string& className) const { ScheduleTypeVector result; auto it = m_classNameToScheduleTypesMap.find(className); if (it != m_classNameToScheduleTypesMap.end()) { @@ -34,7 +34,7 @@ namespace model { return result; } - ScheduleType ScheduleTypeRegistrySingleton::getScheduleType(const std::string& className, const std::string& scheduleDisplayName) const { + ScheduleType ScheduleTypeRegistry::getScheduleType(const std::string& className, const std::string& scheduleDisplayName) const { ScheduleTypeVector scheduleTypes = getScheduleTypesByClassName(className); for (const ScheduleType& scheduleType : scheduleTypes) { if (scheduleType.scheduleDisplayName == scheduleDisplayName) { @@ -45,7 +45,7 @@ namespace model { return {}; } - ScheduleTypeLimits ScheduleTypeRegistrySingleton::getOrCreateScheduleTypeLimits(const ScheduleType& scheduleType, Model& model) const { + ScheduleTypeLimits ScheduleTypeRegistry::getOrCreateScheduleTypeLimits(const ScheduleType& scheduleType, Model& model) const { std::string defaultName = getDefaultName(scheduleType); // DLM: I do not understand why both upper and lower limit have to be set to reuse this? @@ -83,7 +83,12 @@ namespace model { return scheduleTypeLimits; } - ScheduleTypeRegistrySingleton::ScheduleTypeRegistrySingleton() { + ScheduleTypeRegistry& ScheduleTypeRegistry::instance() { + static ScheduleTypeRegistry instance; + return instance; + } + + ScheduleTypeRegistry::ScheduleTypeRegistry() { // className, scheduleDisplayName, scheduleRelationshipName, isContinuous, unitType, lowerLimitValue, upperLimitValue; const ScheduleType scheduleTypes[] = { @@ -604,7 +609,7 @@ namespace model { } } - std::string ScheduleTypeRegistrySingleton::getDefaultName(const ScheduleType& scheduleType) const { + std::string ScheduleTypeRegistry::getDefaultName(const ScheduleType& scheduleType) const { std::string result = scheduleType.unitType; if (result.empty()) { if (scheduleType.isContinuous) { diff --git a/src/model/ScheduleTypeRegistry.hpp b/src/model/ScheduleTypeRegistry.hpp index d542ac8a049..a4fcecd29c2 100644 --- a/src/model/ScheduleTypeRegistry.hpp +++ b/src/model/ScheduleTypeRegistry.hpp @@ -8,7 +8,6 @@ #include "ModelAPI.hpp" -#include "../utilities/core/Singleton.hpp" #include "../utilities/core/Logger.hpp" #include @@ -30,7 +29,7 @@ namespace model { { /** The name of a class that can point to a schedule. */ std::string className; - /** The display name of that schedule (which is used as a key in ScheduleTypeRegistrySingleton, + /** The display name of that schedule (which is used as a key in ScheduleTypeRegistry, * and is also intented for use in UI displays). */ std::string scheduleDisplayName; /** The name of the Relationship that points from the user (of type className) to the Schedule. */ @@ -54,17 +53,17 @@ namespace model { * \relates ScheduleType */ MODEL_API bool isCompatible(const ScheduleType& scheduleType, const ScheduleTypeLimits& candidate, bool isStringent = false); - /** Singleton class that contains a registry of all types of schedules that can exist in a Model. - * Do not use directly, but rather, use the ScheduleTypeRegistry typedef (e.g. - * \code - * ScheduleType st = ScheduleTypeRegistry::instance().getScheduleType("Lights","Lighting") - * \endcode - * ). */ - class MODEL_API ScheduleTypeRegistrySingleton + /** Singleton class that contains a registry of all types of schedules that can exist in a Model. */ + class MODEL_API ScheduleTypeRegistry { - friend class Singleton; - public: + static ScheduleTypeRegistry& instance(); + + ScheduleTypeRegistry(const ScheduleTypeRegistry& other) = delete; + ScheduleTypeRegistry(ScheduleTypeRegistry&& other) = delete; + ScheduleTypeRegistry& operator=(const ScheduleTypeRegistry&) = delete; + ScheduleTypeRegistry& operator=(ScheduleTypeRegistry&&) = delete; + /** Returns the names of classes that have \link ScheduleType ScheduleTypes \endlink registered * with the ScheduleTypeRegistry. */ std::vector classNames() const; @@ -85,34 +84,33 @@ namespace model { std::string getDefaultName(const ScheduleType& scheduleType) const; private: + ScheduleTypeRegistry(); + ~ScheduleTypeRegistry() = default; + REGISTER_LOGGER("openstudio.model.ScheduleTypeRegistry"); - ScheduleTypeRegistrySingleton(); using ClassNameToScheduleTypesMap = std::map>; ClassNameToScheduleTypesMap m_classNameToScheduleTypesMap; }; - /** \relates ScheduleTypeRegistrySingleton */ - using ScheduleTypeRegistry = openstudio::Singleton; - /** Returns true if candidate is consistent with the ScheduleType that corresponds to className * and scheduleRelationshipName. Throws if there is no such ScheduleType. - * \relates ScheduleTypeRegistrySingleton */ + * \relates ScheduleTypeRegistry */ MODEL_API bool isCompatible(const std::string& className, const std::string& scheduleDisplayName, const ScheduleTypeLimits& candidate); /** If schedule.scheduleTypeLimtis(), returns true if that ScheduleTypeLimits isCompatible and * otherwise returns false. Otherwise, uses - * ScheduleTypeRegistrySingleton::getOrCreateScheduleTypeLimits to find an appropriate + * ScheduleTypeRegistry::getOrCreateScheduleTypeLimits to find an appropriate * ScheduleTypeLimits and then calls Schedule::setScheduleTypeLimtis, which should succeed in * this case. This method is used by all of the ModelObject methods that set schedules. - * \relates ScheduleTypeRegistrySingleton */ + * \relates ScheduleTypeRegistry */ MODEL_API bool checkOrAssignScheduleTypeLimits(const std::string& className, const std::string& scheduleDisplayName, Schedule& schedule); /** Returns all of the ScheduleTypeLimtis already in model that are \link isCompatible * compatible\endlink with className and scheduleDisplayName. May be used instead of - * ScheduleTypeRegistrySingleton::getOrCreateScheduleTypeLimits to reduce the number of + * ScheduleTypeRegistry::getOrCreateScheduleTypeLimits to reduce the number of * ScheduleTypeLimits that are ultimately created and present in a model. - * \relates ScheduleTypeRegistrySingleton */ + * \relates ScheduleTypeRegistry */ MODEL_API std::vector getCompatibleScheduleTypeLimits(const Model& model, const std::string& className, const std::string& scheduleDisplayName); diff --git a/src/utilities/CMakeLists.txt b/src/utilities/CMakeLists.txt index d3e55af79e4..fa5dd19c8fe 100644 --- a/src/utilities/CMakeLists.txt +++ b/src/utilities/CMakeLists.txt @@ -60,8 +60,6 @@ set(core_src core/Queue.hpp core/RubyInterpreter.hpp core/RubyException.hpp - core/Singleton.hpp - core/StaticInitializer.hpp core/String.hpp core/String.cpp core/StringHelpers.hpp @@ -398,7 +396,6 @@ set(${target_name}_swig_src core/Exception.i core/Logger.i core/Path.i - core/Singleton.i core/System.i core/UUID.i core/UnzipFile.i diff --git a/src/utilities/core/Core.i b/src/utilities/core/Core.i index be32cc94972..f50a7bf44a0 100644 --- a/src/utilities/core/Core.i +++ b/src/utilities/core/Core.i @@ -54,7 +54,6 @@ %include %include %include -%include %include %include %include diff --git a/src/utilities/core/Enum.hpp b/src/utilities/core/Enum.hpp index a19ced97973..7810e19fddc 100644 --- a/src/utilities/core/Enum.hpp +++ b/src/utilities/core/Enum.hpp @@ -9,7 +9,6 @@ #include #include #include -#include "StaticInitializer.hpp" #include #include #include diff --git a/src/utilities/core/EnumBase.hpp b/src/utilities/core/EnumBase.hpp index 55d7750a099..7cd50cc5494 100644 --- a/src/utilities/core/EnumBase.hpp +++ b/src/utilities/core/EnumBase.hpp @@ -6,8 +6,6 @@ #ifndef UTILITIES_CORE_ENUMBASE_HPP #define UTILITIES_CORE_ENUMBASE_HPP -#include "StaticInitializer.hpp" - #include #include #include @@ -20,7 +18,7 @@ /** Base class for OPENSTUDIO_ENUMs. Comparison operators use the underlying (integer) value. */ template -class EnumBase : public ::StaticInitializer +class EnumBase { public: /** Default constructor. EnumBase default constructor never actually called; OPENSTUDIO_ENUM- diff --git a/src/utilities/core/Singleton.hpp b/src/utilities/core/Singleton.hpp deleted file mode 100644 index e156eb3d756..00000000000 --- a/src/utilities/core/Singleton.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/*********************************************************************************************************************** -* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. -* See also https://openstudio.net/license -***********************************************************************************************************************/ - -#ifndef UTILITIES_CORE_SINGLETON_HPP -# define UTILITIES_CORE_SINGLETON_HPP - -// Warning: If T's constructor throws, instance() will return a null reference. - -namespace openstudio { - -// Ripped from boost http://www.boost.org/doc/libs/1_42_0/libs/pool/doc/implementation/singleton.html -// T must be: no-throw default constructible and no-throw destructible -template -class Singleton -{ - public: - Singleton() = delete; - using object_type = T; - - // If, at any point (in user code), Singleton::instance() - // is called, then the following function is instantiated. - static object_type& instance() { - static object_type obj; - return obj; - } -}; -} // namespace openstudio - -#endif // UTILITIES_CORE_SINGLETON_HPP - -/* EXAMPLE USAGE - -How to use this class? - -myclass.hpp - -#ifndef MYCLASS_HPP -#define MYCLASS_HPP - -#include "singleton.hpp" - -class MyClassSingleton -{ - -friend class Singleton; - -public: - - void doSomething() { std::cout << "Something"; } - -private: - - MyClass(); - -}; - -typedef Singleton MyClass; - -#endif - -main.cpp - -#include -#include -#include - -#include "myclass.hpp" - -void test() -{ - MyClass::instance().doSomething(); -} - -int main(int argc, char* []argv) -{ - boost::thread thread1(&test); - boost::thread thread2(&test); - thread1.join(); - thread2.join(); - return 0; -} - -*/ diff --git a/src/utilities/core/Singleton.i b/src/utilities/core/Singleton.i deleted file mode 100644 index 5a62e797ddb..00000000000 --- a/src/utilities/core/Singleton.i +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef UTILITIES_CORE_SINGLETON_I -#define UTILITIES_CORE_SINGLETON_I - -%{ - #include -%} - -namespace openstudio{ - - template - class Singleton { - public: - static T& instance(); - //static void init(); // never throws - ~Singleton(); - - private: - Singleton(); - }; - -} // openstudio - -#endif //UTILITIES_CORE_SINGLETON_I diff --git a/src/utilities/core/StaticInitializer.hpp b/src/utilities/core/StaticInitializer.hpp deleted file mode 100644 index e3f8c94eef1..00000000000 --- a/src/utilities/core/StaticInitializer.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/*********************************************************************************************************************** -* OpenStudio(R), Copyright (c) Alliance for Sustainable Energy, LLC. -* See also https://openstudio.net/license -***********************************************************************************************************************/ - -#ifndef UTILITIES_CORE_STATICINITIALIZER_HPP -#define UTILITIES_CORE_STATICINITIALIZER_HPP - -/// This template should be used as a base class for a class that has static -/// data to initialize. There is no thread safe way in windows to initialize static -/// data except to do it before main runs, or under some other controlled condition. -/// This template ensures that the static member function initialize() of the derived -/// class is called before main begins. -/// This code is not necessary with GCC because GCC puts static initializers in critical sections -template -struct StaticInitializer -{ -#ifndef __GNUC__ - private: - struct object_creator - { - // This constructor does nothing more than ensure that instance() - // is called before main() begins, thus creating the static - // T object before multithreading race issues can come up. - object_creator() { - StaticInitializer::do_initialize(); - } - - inline void do_nothing() const {} - }; - static object_creator create_object; - - public: - StaticInitializer() { - do_initialize(); - } - - // If, at any point (in user code), Singleton::instance() - // is called, then the following function is instantiated. - static void do_initialize() { - // call the static function - T::initialize(); - - // The following line does nothing else than force the instantiation - // of Singleton::create_object, whose constructor is - // called before main() begins. - create_object.do_nothing(); - } -#endif -}; - -#ifndef __GNUC__ -template -typename StaticInitializer::object_creator StaticInitializer::create_object; -#endif - -#endif // UTILITIES_CORE_STATICINITIALIZER_HPP diff --git a/src/utilities/core/UUID.cpp b/src/utilities/core/UUID.cpp index b6d32ad738f..3ab4a57345a 100644 --- a/src/utilities/core/UUID.cpp +++ b/src/utilities/core/UUID.cpp @@ -5,7 +5,6 @@ #include "UUID.hpp" #include "String.hpp" -#include "StaticInitializer.hpp" #include @@ -15,45 +14,18 @@ namespace openstudio { -namespace detail { - struct BoostGeneratorsInitializer : StaticInitializer - { - static void initialize() { - createUUID(); - toUUID(std::string("00000000-0000-0000-0000-000000000000")); - } - }; - struct MakeSureBoostGeneratorsInitializerIsInitialized - { - MakeSureBoostGeneratorsInitializerIsInitialized() = default; - - BoostGeneratorsInitializer m_i; - }; - -} // namespace detail - UUID::UUID() : boost::uuids::uuid(boost::uuids::nil_uuid()) {} UUID::UUID(const boost::uuids::uuid& t_other) : boost::uuids::uuid(t_other) {} UUID UUID::random_generate() { - static boost::thread_specific_ptr gen; - - if (gen.get() == nullptr) { - gen.reset(new boost::uuids::random_generator); - } - - return UUID((*gen)()); + static thread_local boost::uuids::random_generator gen; + return UUID(gen()); } UUID UUID::string_generate(const std::string& t_str) { - static boost::thread_specific_ptr gen; - - if (gen.get() == nullptr) { - gen.reset(new boost::uuids::string_generator); - } - - return UUID((*gen)(t_str)); + static thread_local boost::uuids::string_generator gen; + return UUID(gen(t_str)); } UUID createUUID() { diff --git a/src/utilities/idd/CommentRegex.hpp b/src/utilities/idd/CommentRegex.hpp index d4249504d34..1978eda4cad 100644 --- a/src/utilities/idd/CommentRegex.hpp +++ b/src/utilities/idd/CommentRegex.hpp @@ -7,7 +7,6 @@ #define UTILITIES_IDD_COMMENTREGEX_HPP #include "../UtilitiesAPI.hpp" -#include "../core/StaticInitializer.hpp" #include diff --git a/src/utilities/idd/Idd.i b/src/utilities/idd/Idd.i index a19e52e80a8..a6680982ac9 100644 --- a/src/utilities/idd/Idd.i +++ b/src/utilities/idd/Idd.i @@ -76,6 +76,7 @@ %include %include %include +%include %extend openstudio::IddKey{ std::string __str__() const{ diff --git a/src/utilities/idd/IddEnums.hpp b/src/utilities/idd/IddEnums.hpp index d1b0d79d7e8..72689846841 100644 --- a/src/utilities/idd/IddEnums.hpp +++ b/src/utilities/idd/IddEnums.hpp @@ -22,7 +22,7 @@ namespace openstudio { * * UserCustom \link openstudio::IddFile IddFiles\endlink are loaded directly from disk, and * typically correspond to old or under-development versions of EnergyPlus or OpenStudio. The - * rest of the enumeration values designate subsets of the \link openstudio::IddFactorySingleton + * rest of the enumeration values designate subsets of the \link openstudio::IddFactory * IddFactory\endlink (the current versions of the EnergyPlus and OpenStudio IDDs, and all * objects in the factory). */ #ifdef SWIG @@ -71,15 +71,15 @@ using OptionalIddFileTypeSet = boost::optional>; /** \class IddObjectType * \brief Enumeration of the \link openstudio::IddObject IddObject\endlink types available - * through the \link openstudio::IddFactorySingleton IddFactory\endlink. + * through the \link openstudio::IddFactory IddFactory\endlink. * \details Catchall is the default constructed \link openstudio::IddObject IddObject\endlink * type. UserCustom is the default type for \link openstudio::IddObject IddObjects\endlink * constructed by \link openstudio::IddObject::load IddObject::load\endlink. UserCustom objects * must be referenced by name through an \link openstudio::IddFile IddFile\endlink or \link * openstudio::IddFileAndFactoryWrapper IddFileAndFactoryWrapper\endlink. They cannot be - * accessed through the \link openstudio::IddFactorySingleton IddFactory\endlink (by name or + * accessed through the \link openstudio::IddFactory IddFactory\endlink (by name or * type). CommentOnly is a convenience object for capturing standalone comments in IDFs. All other - * types are derived from the IDD files used to create \link openstudio::IddFactorySingleton + * types are derived from the IDD files used to create \link openstudio::IddFactory * IddFactory\endlink. See the OPENSTUDIO_ENUM documentation in utilities/core/Enum.hpp. * */ #ifdef SWIG diff --git a/src/utilities/idd/IddFile.hpp b/src/utilities/idd/IddFile.hpp index 919d9a9385c..9f3d5484d68 100644 --- a/src/utilities/idd/IddFile.hpp +++ b/src/utilities/idd/IddFile.hpp @@ -20,7 +20,7 @@ namespace openstudio { // forward declarations -class IddFactorySingleton; +class IddFactory; namespace detail { class IddFile_Impl; } // namespace detail @@ -118,7 +118,7 @@ class UTILITIES_API IddFile //@} protected: - friend class IddFactorySingleton; + friend class IddFactory; /// set version void setVersion(const std::string& version); diff --git a/src/utilities/idd/IddFileAndFactoryWrapper.hpp b/src/utilities/idd/IddFileAndFactoryWrapper.hpp index 3c8c9f11a09..956ea14adfc 100644 --- a/src/utilities/idd/IddFileAndFactoryWrapper.hpp +++ b/src/utilities/idd/IddFileAndFactoryWrapper.hpp @@ -12,7 +12,7 @@ namespace openstudio { -/** Wraps the functionality of IddFile and \link IddFactorySingleton IddFactory \endlink +/** Wraps the functionality of IddFile and \link IddFactory IddFactory \endlink * into one class for use by IdfFile and Workspace. */ class UTILITIES_API IddFileAndFactoryWrapper { @@ -27,7 +27,7 @@ class UTILITIES_API IddFileAndFactoryWrapper IddFileAndFactoryWrapper(const IddFile& iddFile); /** Construct wrapper that provides access to the iddFileType IddFile through the \link - * IddFactorySingleton IddFactory \endlink. Logs a warning if iddFileType == + * IddFactory IddFactory \endlink. Logs a warning if iddFileType == * IddFileType::UserCustom, since this results in an empty IddFile. */ IddFileAndFactoryWrapper(IddFileType iddFileType); @@ -75,7 +75,7 @@ class UTILITIES_API IddFileAndFactoryWrapper std::vector uniqueObjects() const; /** Get the IddFile, which may have been explicitly specified by the user, or may be implicitly - * specified by reference to the \link IddFactorySingleton IddFactory\endlink. */ + * specified by reference to the \link IddFactory IddFactory\endlink. */ IddFile iddFile() const; /** Get the IddFileType. If iddFileType() == IddFileType::UserCustom, then the file has been @@ -87,11 +87,11 @@ class UTILITIES_API IddFileAndFactoryWrapper /** @name Setters */ //@{ - /** Set the IddFile explicitly. This option does not use the \link IddFactorySingleton + /** Set the IddFile explicitly. This option does not use the \link IddFactory * IddFactory\endlink. */ void setIddFile(const IddFile& iddFile); - /** Set the IddFile by specifying iddFileType. This option uses the \link IddFactorySingleton + /** Set the IddFile by specifying iddFileType. This option uses the \link IddFactory * IddFactory\endlink, unless iddFileType == IddFileType::UserCustom, in which case a warning * is logged. */ void setIddFile(IddFileType iddFileType); diff --git a/src/utilities/idd/IddObject.hpp b/src/utilities/idd/IddObject.hpp index f3b45fee85b..c5228b4bcf9 100644 --- a/src/utilities/idd/IddObject.hpp +++ b/src/utilities/idd/IddObject.hpp @@ -49,7 +49,7 @@ class UTILITIES_API IddObject std::string name() const; /** Get object type, as specified by the OPENSTUDIO_ENUM IddObjectType. Similar information to - * name() for \link IddObject IddObjects \endlink stored by the \link IddFactorySingleton + * name() for \link IddObject IddObjects \endlink stored by the \link IddFactory * IddFactory \endlink, that is type() == IddObjectType(name()) and * type().valueDescription() == name(). */ IddObjectType type() const; diff --git a/src/utilities/idd/IddRegex.hpp b/src/utilities/idd/IddRegex.hpp index dfaa1231a62..ce3fbbeaefb 100644 --- a/src/utilities/idd/IddRegex.hpp +++ b/src/utilities/idd/IddRegex.hpp @@ -7,7 +7,6 @@ #define UTILITIES_IDD_IDDREGEX_HPP #include "../UtilitiesAPI.hpp" -#include "../core/StaticInitializer.hpp" #include namespace openstudio { diff --git a/src/utilities/idd/mainpage.hpp b/src/utilities/idd/mainpage.hpp index 4e586c7b504..d8425e00353 100644 --- a/src/utilities/idd/mainpage.hpp +++ b/src/utilities/idd/mainpage.hpp @@ -9,7 +9,7 @@ namespace openstudio { * * \details OpenStudio provides parsing of and programmatic access to Input Data Dictionary (IDD) files, * objects, and fields through the OpenStudio utilities library (in the openstudio namespace). IDD files - * of central importance to OpenStudio are wrapped into the \link IddFactorySingleton IddFactory \endlink, + * of central importance to OpenStudio are wrapped into the \link IddFactory IddFactory \endlink, * and used to generate IddFileType, IddObjectType, and field-level enumeration classes (see IddEnums.hpp * and IddFieldEnums.hxx). * @@ -26,9 +26,9 @@ namespace openstudio { * \li IddKey * \li IddKeyProperties * - * \link IddFactorySingleton IddFactory\endlink classes and enums + * \link IddFactory IddFactory\endlink classes and enums * - * \li \link IddFactorySingleton IddFactory\endlink + * \li \link IddFactory IddFactory\endlink * \li IddFileType * \li IddObjectType * \li IddFieldEnums.hxx @@ -63,9 +63,9 @@ namespace openstudio { * OpenStudio for parsing and accessing \link IddFile IddFiles\endlink, and \link IddObject * IddObjects\endlink, including the two \link IddFile IddFiles\endlink of central importance to * OpenStudio: the current versions of Energy+.idd and OpenStudio.idd, which are best accessed - * through the \link IddFactorySingleton IddFactory \endlink. (Legacy versions of the + * through the \link IddFactory IddFactory \endlink. (Legacy versions of the * OpenStudio.idd should also be loaded from disk using the - * \link IddFactorySingleton IddFactory\endlink, to avoid duplicate parsing effort.) + * \link IddFactory IddFactory\endlink, to avoid duplicate parsing effort.) * * \section parsing_idd File and Object Parsing * @@ -103,7 +103,7 @@ namespace openstudio { * a version string is specified, prefixed by '!IDD_Version '. This version string should be the * default value for the Version Identifier field in the file's version object ('Version' in the * EnergyPlus IDD, 'OS:Version' in the OpenStudio IDD). Version information is generally available - * through the IddFile, \link IddFactorySingleton IddFactory \endlink, IddFileAndFactoryWrapper, + * through the IddFile, \link IddFactory IddFactory \endlink, IddFileAndFactoryWrapper, * IdfFile, and Workspace classes. * * \section usage_idd Programmatic Access @@ -163,7 +163,7 @@ namespace openstudio { * * Two particular IddFiles, the current Energy+.idd and OpenStudio.idd, are central to OpenStudio, * and so the utilities/idd sub-project provides convenience functionality to support their - * consistent use throughout the rest of the project via the \link IddFactorySingleton IddFactory + * consistent use throughout the rest of the project via the \link IddFactory IddFactory * \endlink. * * The IddFactory is generated from ProposedEnergy+.idd (contains the same information as @@ -183,7 +183,7 @@ namespace openstudio { * IddFieldEnums.hxx should never be included directly; please use it as a table of contents to find * the specific files that should be \#included in your source. * - * The \link IddFactorySingleton IddFactory\endlink API and IddFile API are purposefully similar, as + * The \link IddFactory IddFactory\endlink API and IddFile API are purposefully similar, as * openstudio::IdfFile and openstudio::Workspace can be used with either an explicit IddFile, or with * an implicit IDD that is specified by filtering the IddFactory with an IddFileType (typically * IddFileType::EnergyPlus or IddFileType::OpenStudio). Instead of each of those classes handling the @@ -191,8 +191,8 @@ namespace openstudio { * embodied in the IddFileAndFactoryWrapper, which explicitly provides a common API to these two * in-memory instantiations of IDD. * - * The \link IddFactorySingleton IddFactory\endlink also provides access to older versions of the - * OpenStudio.idd. In addition to the convenience of the \link IddFactorySingleton::getIddFile + * The \link IddFactory IddFactory\endlink also provides access to older versions of the + * OpenStudio.idd. In addition to the convenience of the \link IddFactory::getIddFile * IddFactory::instance().getIddFile \endlink syntax, accessing the legacy files in this way ensures * that each file is only parsed once, which is necessary for some applications (for * instance, the openstudio::osversion::VersionTranslator) to have acceptable performance. diff --git a/src/utilities/idf/IdfRegex.hpp b/src/utilities/idf/IdfRegex.hpp index b347f0a661a..a1de4270a5e 100644 --- a/src/utilities/idf/IdfRegex.hpp +++ b/src/utilities/idf/IdfRegex.hpp @@ -7,7 +7,6 @@ #define UTILITIES_IDF_IDFREGEX_HPP #include "../UtilitiesAPI.hpp" -#include "../core/StaticInitializer.hpp" #include #include diff --git a/src/utilities/mainpage.hpp b/src/utilities/mainpage.hpp index 6f5a547f9b1..982ac15610a 100644 --- a/src/utilities/mainpage.hpp +++ b/src/utilities/mainpage.hpp @@ -49,7 +49,7 @@ namespace openstudio { * Logger.hpp, LogMessage.hpp, Optional.hpp, Path.hpp, PathHelpers.hpp, String.hpp, UUID.hpp * \li Used more sparingly: Application.hpp, ApplicationPathHelpers.hpp, Checksum.hpp, * CommandLine.hpp, EnumHelpers.hpp, Exception.hpp, FileReference.hpp, Finder.hpp, - * PathWatcher.hpp, Queue.hpp, Singleton.hpp, StaticInitializer.hpp, + * PathWatcher.hpp, Queue.hpp, * StringHelpers.hpp, StringStreamLogSink.hpp, System.hpp, UnzipFile.hpp * URLHelpers.hpp, ZipFile.hpp * @@ -110,11 +110,11 @@ namespace openstudio { * * \li Unit * \li Quantity - * \li \link UnitFactorySingleton UnitFactory \endlink - Singleton and related non-member + * \li \link UnitFactory UnitFactory \endlink - Singleton and related non-member * functions for creating \link Unit Units\endlink from strings. - * \li \link QuantityFactorySingleton QuantityFactory \endlink - Singleton and related + * \li \link QuantityFactory QuantityFactory \endlink - Singleton and related * non-member functions for creating \link Quantity Quantities\endlink from strings. - * \li \link QuantityConverterSingleton QuantityConverter \endlink - Singleton and related + * \li \link QuantityConverter QuantityConverter \endlink - Singleton and related * non-member functions for converting \link Quantity Quantities\endlink and * \link OSQuantityVector OSQuantityVectors \endlink to different units. * \li OSOptionalQuantity - Class for always returning a Unit and optionally diff --git a/src/utilities/units/QuantityConverter.cpp b/src/utilities/units/QuantityConverter.cpp index b8da1b5a3f3..e08a4a9a786 100644 --- a/src/utilities/units/QuantityConverter.cpp +++ b/src/utilities/units/QuantityConverter.cpp @@ -23,7 +23,7 @@ namespace openstudio { -boost::optional QuantityConverterSingleton::convert(const Quantity& q, UnitSystem sys) const { +boost::optional QuantityConverter::convert(const Quantity& q, UnitSystem sys) const { if ((q.system() != UnitSystem::Mixed) && (q.system() == sys)) { return q; } @@ -64,7 +64,7 @@ boost::optional QuantityConverterSingleton::convert(const Quantity& q, return converted; } -boost::optional QuantityConverterSingleton::convert(const Quantity& original, const Unit& targetUnits) const { +boost::optional QuantityConverter::convert(const Quantity& original, const Unit& targetUnits) const { Quantity working(original); OptionalQuantity candidate; @@ -93,7 +93,12 @@ boost::optional QuantityConverterSingleton::convert(const Quantity& or return result; } -QuantityConverterSingleton::QuantityConverterSingleton() { +QuantityConverter& QuantityConverter::instance() { + static QuantityConverter instance; + return instance; +} + +QuantityConverter::QuantityConverter() { // initialize the quantity converter maps here const baseUnitConversionFactor toSI[] = {{UnitSystem::SI, "kg", "kg", 1.0, 0}, @@ -247,7 +252,7 @@ QuantityConverterSingleton::QuantityConverterSingleton() { } } -boost::optional QuantityConverterSingleton::m_convertToSI(const Quantity& original) const { +boost::optional QuantityConverter::m_convertToSI(const Quantity& original) const { // create a working copy of the original Quantity working(original); // Make sure to work unscaled: 10^0 @@ -312,7 +317,7 @@ boost::optional QuantityConverterSingleton::m_convertToSI(const Quanti return result; } -Quantity QuantityConverterSingleton::m_convertFromSI(const Quantity& original, const UnitSystem& targetSys) const { +Quantity QuantityConverter::m_convertFromSI(const Quantity& original, const UnitSystem& targetSys) const { Quantity working(original); // Make sure to work unscaled: 10^0 @@ -368,7 +373,7 @@ Quantity QuantityConverterSingleton::m_convertFromSI(const Quantity& original, c return converted; } -boost::optional QuantityConverterSingleton::m_convertToTargetFromSI(const Quantity& original, const Unit& targetUnits) const { +boost::optional QuantityConverter::m_convertToTargetFromSI(const Quantity& original, const Unit& targetUnits) const { Quantity working(original); // Make sure to work unscaled: 10^0 diff --git a/src/utilities/units/QuantityConverter.hpp b/src/utilities/units/QuantityConverter.hpp index be4157e4f92..e30f85445ca 100644 --- a/src/utilities/units/QuantityConverter.hpp +++ b/src/utilities/units/QuantityConverter.hpp @@ -7,7 +7,6 @@ #define UTILITIES_UNITS_QUANTITYCONVERTER_HPP #include "../UtilitiesAPI.hpp" -#include "../core/Singleton.hpp" #include "../core/Logger.hpp" #include "Unit.hpp" @@ -66,19 +65,24 @@ struct baseUnitConversionFactor /** Singleton for converting quantities to different \link UnitSystem unit systems \endlink or * to targeted \link Unit units \endlink */ -class UTILITIES_API QuantityConverterSingleton +class UTILITIES_API QuantityConverter { + public: + static QuantityConverter& instance(); - friend class Singleton; + QuantityConverter(const QuantityConverter& other) = delete; + QuantityConverter(QuantityConverter&& other) = delete; + QuantityConverter& operator=(const QuantityConverter&) = delete; + QuantityConverter& operator=(QuantityConverter&&) = delete; - public: boost::optional convert(const Quantity& q, UnitSystem sys) const; boost::optional convert(const Quantity& original, const Unit& targetUnits) const; private: REGISTER_LOGGER("openstudio.units.QuantityConverter"); - QuantityConverterSingleton(); + QuantityConverter(); + ~QuantityConverter() = default; using BaseUnitConversionMap = std::map; using UnitSystemConversionMultiMap = std::multimap; @@ -93,24 +97,21 @@ class UTILITIES_API QuantityConverterSingleton boost::optional m_convertToTargetFromSI(const Quantity& original, const Unit& targetUnits) const; }; -/** \relates QuantityConverterSingleton */ -using QuantityConverter = openstudio::Singleton; - -/** Non-member function to simplify interface for users. \relates QuantityConverterSingleton */ +/** Non-member function to simplify interface for users. \relates QuantityConverter */ UTILITIES_API boost::optional convert(double original, const std::string& originalUnits, const std::string& finalUnits); -/** Non-member function to simplify interface for users. \relates QuantityConverterSingleton */ +/** Non-member function to simplify interface for users. \relates QuantityConverter */ UTILITIES_API boost::optional convert(const Quantity& original, UnitSystem sys); /** Non-member function that uses just two calls to QuantityConverter to convert an entire - * OSQuantityVector. \relates QuantityConverterSingleton \relates OSQuantityVector */ + * OSQuantityVector. \relates QuantityConverter \relates OSQuantityVector */ UTILITIES_API OSQuantityVector convert(const OSQuantityVector& original, UnitSystem sys); -/** Non-member function to simplify interface for users. \relates QuantityConverterSingleton */ +/** Non-member function to simplify interface for users. \relates QuantityConverter */ UTILITIES_API boost::optional convert(const Quantity& original, const Unit& targetUnits); /** Non-member function that uses just two calls to QuantityConverter to convert an entire - * OSQuantityVector. \relates QuantityConverterSingleton \relates OSQuantityVector */ + * OSQuantityVector. \relates QuantityConverter \relates OSQuantityVector */ UTILITIES_API OSQuantityVector convert(const OSQuantityVector& original, const Unit& targetUnits); } // namespace openstudio diff --git a/src/utilities/units/QuantityConverter.i b/src/utilities/units/QuantityConverter.i index 9cf10358754..5d5ac262bc6 100644 --- a/src/utilities/units/QuantityConverter.i +++ b/src/utilities/units/QuantityConverter.i @@ -6,7 +6,6 @@ %} // hide shared_ptrs, expose helper functions -%ignore QuantityConverterSingleton; %ignore QuantityConverter; %include diff --git a/src/utilities/units/QuantityFactory.cpp b/src/utilities/units/QuantityFactory.cpp index d129cf252db..d02d3456062 100644 --- a/src/utilities/units/QuantityFactory.cpp +++ b/src/utilities/units/QuantityFactory.cpp @@ -17,7 +17,12 @@ using std::dynamic_pointer_cast; namespace openstudio { -boost::optional QuantityFactorySingleton::createQuantity(const std::string& quantityString) const { +QuantityFactory& QuantityFactory::instance() { + static QuantityFactory instance; + return instance; +} + +boost::optional QuantityFactory::createQuantity(const std::string& quantityString) const { OptionalQuantity result; StringPair strings = decomposeQuantityString(quantityString); try { @@ -29,7 +34,7 @@ boost::optional QuantityFactorySingleton::createQuantity(const std::st return result; } -boost::optional QuantityFactorySingleton::createQuantity(const std::string& quantityString, UnitSystem system) const { +boost::optional QuantityFactory::createQuantity(const std::string& quantityString, UnitSystem system) const { OptionalQuantity result; StringPair strings = decomposeQuantityString(quantityString); try { @@ -41,7 +46,7 @@ boost::optional QuantityFactorySingleton::createQuantity(const std::st return result; } -boost::optional QuantityFactorySingleton::createQuantity(double value, const std::string& unitString) const { +boost::optional QuantityFactory::createQuantity(double value, const std::string& unitString) const { // create return variable, and try to create unit OptionalQuantity result; UnitSystem system = getSystem(unitString); @@ -52,7 +57,7 @@ boost::optional QuantityFactorySingleton::createQuantity(double value, return result; } -boost::optional QuantityFactorySingleton::createQuantity(double value, const std::string& unitString, UnitSystem system) const { +boost::optional QuantityFactory::createQuantity(double value, const std::string& unitString, UnitSystem system) const { // create return variable, and try to create unit OptionalQuantity result; OptionalUnit unit = UnitFactory::instance().createUnit(unitString, system); diff --git a/src/utilities/units/QuantityFactory.hpp b/src/utilities/units/QuantityFactory.hpp index 45e8167130b..ee88e634f5a 100644 --- a/src/utilities/units/QuantityFactory.hpp +++ b/src/utilities/units/QuantityFactory.hpp @@ -8,7 +8,6 @@ #include "../UtilitiesAPI.hpp" -#include "../core/Singleton.hpp" #include "Quantity.hpp" #include "UnitFactory.hpp" @@ -19,12 +18,16 @@ namespace openstudio { -class UTILITIES_API QuantityFactorySingleton +class UTILITIES_API QuantityFactory { + public: + static QuantityFactory& instance(); - friend class Singleton; + QuantityFactory(const QuantityFactory& other) = delete; + QuantityFactory(QuantityFactory&& other) = delete; + QuantityFactory& operator=(const QuantityFactory&) = delete; + QuantityFactory& operator=(QuantityFactory&&) = delete; - public: // FACTORY USE /** Parses quantity string to separate the value from the unit. Then creates the quantity @@ -47,11 +50,12 @@ class UTILITIES_API QuantityFactorySingleton boost::optional createQuantity(double value, const std::string& unitString, UnitSystem system) const; private: + QuantityFactory() = default; + ~QuantityFactory() = default; + REGISTER_LOGGER("openstudio.units.QuantityFactory"); }; -using QuantityFactory = openstudio::Singleton; - /** Creates a Quantity object from quantityString (a string that matches * openstudio::regexQuantity()). */ UTILITIES_API boost::optional createQuantity(const std::string& quantityString); diff --git a/src/utilities/units/QuantityFactory.i b/src/utilities/units/QuantityFactory.i index f1796ed15bb..f70d1f710a1 100644 --- a/src/utilities/units/QuantityFactory.i +++ b/src/utilities/units/QuantityFactory.i @@ -6,7 +6,6 @@ %} // hide shared_ptrs, expose helper functions -%ignore QuantityFactorySingleton; %ignore QuantityFactory; %include diff --git a/src/utilities/units/ScaleFactory.cpp b/src/utilities/units/ScaleFactory.cpp index 059ef69e8df..973c6e3a505 100644 --- a/src/utilities/units/ScaleFactory.cpp +++ b/src/utilities/units/ScaleFactory.cpp @@ -15,7 +15,7 @@ namespace openstudio { -bool ScaleFactorySingleton::registerScale(ScaleConstant scale) { +bool ScaleFactory::registerScale(ScaleConstant scale) { bool result = m_exponentMap.insert(ExponentLookupMap::value_type(scale().exponent, scale)).second; if (!result) { @@ -31,7 +31,7 @@ bool ScaleFactorySingleton::registerScale(ScaleConstant scale) { return result; } -std::vector ScaleFactorySingleton::registeredScales() { +std::vector ScaleFactory::registeredScales() { // make vector of the correct length std::vector result(m_exponentMap.size()); @@ -47,7 +47,7 @@ std::vector ScaleFactorySingleton::registeredScales() { return result; } -ScaleConstant ScaleFactorySingleton::createScale(int exponent) const { +ScaleConstant ScaleFactory::createScale(int exponent) const { ExponentLookupMap::const_iterator lookupPair; lookupPair = m_exponentMap.find(exponent); @@ -60,7 +60,7 @@ ScaleConstant ScaleFactorySingleton::createScale(int exponent) const { return lookupPair->second; // return function pointer that encloses const Scale& } -ScaleConstant ScaleFactorySingleton::createScale(const std::string& abbr) const { +ScaleConstant ScaleFactory::createScale(const std::string& abbr) const { AbbreviationLookupMap::const_iterator lookupPair; lookupPair = m_abbreviationMap.find(abbr); @@ -73,7 +73,12 @@ ScaleConstant ScaleFactorySingleton::createScale(const std::string& abbr) const return lookupPair->second; // return function pointer that encloses const Scale& } -ScaleFactorySingleton::ScaleFactorySingleton() { +ScaleFactory& ScaleFactory::instance() { + static ScaleFactory instance; + return instance; +} + +ScaleFactory::ScaleFactory() { // default ScaleFactory initialization /** \todo Provide functionality for swapping out entire ScaleFactory library or for * complete user customization. */ @@ -104,7 +109,7 @@ ScaleFactorySingleton::ScaleFactorySingleton() { registerScale(yocto); } -ScaleConstant ScaleFactorySingleton::m_recoverFromFailedCreate() const { +ScaleConstant ScaleFactory::m_recoverFromFailedCreate() const { // fatal error if no scales are registered since will never get valid scale. if (m_exponentMap.empty()) { @@ -115,7 +120,7 @@ ScaleConstant ScaleFactorySingleton::m_recoverFromFailedCreate() const { return notDefined; } -std::ostream& operator<<(std::ostream& os, const ScaleFactorySingleton& factory) { +std::ostream& operator<<(std::ostream& os, const ScaleFactory& factory) { for (const auto& map : factory.m_exponentMap) { os << map.second() << '\n'; // output scale and go to next line } diff --git a/src/utilities/units/ScaleFactory.hpp b/src/utilities/units/ScaleFactory.hpp index afd620fa872..568fb3759e7 100644 --- a/src/utilities/units/ScaleFactory.hpp +++ b/src/utilities/units/ScaleFactory.hpp @@ -7,7 +7,6 @@ #define UTILITIES_UNITS_SCALEFACTORY_HPP #include "../UtilitiesAPI.hpp" -#include "../core/Singleton.hpp" #include "../core/Logger.hpp" #include "Scale.hpp" @@ -20,14 +19,15 @@ namespace openstudio { /** Singleton that creates scales based on std::string or exponent. * Access using ScaleFactory::instance(). */ -class UTILITIES_API ScaleFactorySingleton +class UTILITIES_API ScaleFactory { - - friend class Singleton; - public: - /// Destructor. - ~ScaleFactorySingleton() = default; + static ScaleFactory& instance(); + + ScaleFactory(const ScaleFactory& other) = delete; + ScaleFactory(ScaleFactory&& other) = delete; + ScaleFactory& operator=(const ScaleFactory&) = delete; + ScaleFactory& operator=(ScaleFactory&&) = delete; /** Store a scale callback function for future lookup using the scale exponent or * abbreviation. By default, SI scales are registered during factory construction. */ @@ -37,7 +37,7 @@ class UTILITIES_API ScaleFactorySingleton std::vector registeredScales(); /** Outputs the scales registered in the factory. */ - friend UTILITIES_API std::ostream& operator<<(std::ostream& os, const ScaleFactorySingleton& factory); + friend UTILITIES_API std::ostream& operator<<(std::ostream& os, const ScaleFactory& factory); /** Creates a scale from an exponent. Throws if the factory does not have any scales registered. * Returns ScaleConstant with ().value == 0.0 if exponent not in factory. */ @@ -50,7 +50,8 @@ class UTILITIES_API ScaleFactorySingleton private: REGISTER_LOGGER("openstudio.units.ScaleFactory"); /// Private constructor initializes ScaleFactory with standard SI scales. - ScaleFactorySingleton(); + ScaleFactory(); + ~ScaleFactory() = default; using ExponentLookupMap = std::map; using AbbreviationLookupMap = std::map; @@ -60,11 +61,9 @@ class UTILITIES_API ScaleFactorySingleton ScaleConstant m_recoverFromFailedCreate() const; }; -using ScaleFactory = openstudio::Singleton; - /** Prints scales that are registered in the factory (and thus available for use in * Units and Quantities). */ -UTILITIES_API std::ostream& operator<<(std::ostream& os, const ScaleFactorySingleton& factory); +UTILITIES_API std::ostream& operator<<(std::ostream& os, const ScaleFactory& factory); /** Wrapper around << for SWIG bindings. Prints each scale registered in ScaleFactory, * and thus available for use in Units, Quantities, and bare Scale operations. */ diff --git a/src/utilities/units/UnitFactory.cpp b/src/utilities/units/UnitFactory.cpp index 6683c5054d3..3b113020d00 100644 --- a/src/utilities/units/UnitFactory.cpp +++ b/src/utilities/units/UnitFactory.cpp @@ -41,7 +41,7 @@ namespace openstudio { -bool UnitFactorySingleton::registerUnit(CreateUnitCallback createFn, UnitSystem system) { +bool UnitFactory::registerUnit(CreateUnitCallback createFn, UnitSystem system) { Unit thisUnit = createFn(); std::string standardString = thisUnit.standardString(false); @@ -112,7 +112,7 @@ bool UnitFactorySingleton::registerUnit(CreateUnitCallback createFn, UnitSystem return result; } -bool UnitFactorySingleton::registerEquivalentString(const std::string& equivalentString, const std::string& standardString) { +bool UnitFactory::registerEquivalentString(const std::string& equivalentString, const std::string& standardString) { // register the pair bool result = m_standardStringLookupMap.insert(StandardStringLookupMap::value_type(equivalentString, StringVector(1u, standardString))).second; @@ -124,9 +124,9 @@ bool UnitFactorySingleton::registerEquivalentString(const std::string& equivalen return result; } -boost::optional UnitFactorySingleton::createUnit(const std::string& unitString, UnitSystem system) const { +boost::optional UnitFactory::createUnit(const std::string& unitString, UnitSystem system) const { if (m_callbackMaps.empty()) { - LOG(Warn, "UnitFactorySingleton::createUnit called, but the maps appear to be empty."); + LOG(Warn, "UnitFactory::createUnit called, but the maps appear to be empty."); } std::string resultCacheKey = unitString + " in unit system " + system.valueName(); @@ -242,7 +242,7 @@ boost::optional UnitFactorySingleton::createUnit(const std::string& unitSt return result; } -boost::optional UnitFactorySingleton::createUnitSimple(const std::string& unitString, UnitSystem system) const { +boost::optional UnitFactory::createUnitSimple(const std::string& unitString, UnitSystem system) const { if (unitString.empty()) { Unit result = createDimensionlessUnit(system); if (OptionalTemperatureUnit T = result.optionalCast()) { @@ -321,7 +321,7 @@ boost::optional UnitFactorySingleton::createUnitSimple(const std::string& return candidate; } -std::string UnitFactorySingleton::lookupPrettyString(const std::string& standardString) const { +std::string UnitFactory::lookupPrettyString(const std::string& standardString) const { PrettyStringLookupMap::const_iterator lookupPair; lookupPair = m_prettyStringLookupMap.find(standardString); @@ -332,7 +332,12 @@ std::string UnitFactorySingleton::lookupPrettyString(const std::string& standard } } -UnitFactorySingleton::UnitFactorySingleton() { +UnitFactory& UnitFactory::instance() { + static UnitFactory instance; + return instance; +} + +UnitFactory::UnitFactory() { // Celsius Base Units ======================================================== registerUnit(createCelsiusTemperature); diff --git a/src/utilities/units/UnitFactory.hpp b/src/utilities/units/UnitFactory.hpp index f3dcd69cd68..05d52dd3494 100644 --- a/src/utilities/units/UnitFactory.hpp +++ b/src/utilities/units/UnitFactory.hpp @@ -8,7 +8,6 @@ #include "../UtilitiesAPI.hpp" -#include "../core/Singleton.hpp" #include "Unit.hpp" #include "../core/Logger.hpp" @@ -30,12 +29,16 @@ namespace openstudio { * * Also provides a function for looking up pretty units without having to * create a unit. */ -class UTILITIES_API UnitFactorySingleton +class UTILITIES_API UnitFactory { + public: + static UnitFactory& instance(); - friend class Singleton; + UnitFactory(const UnitFactory& other) = delete; + UnitFactory(UnitFactory&& other) = delete; + UnitFactory& operator=(const UnitFactory&) = delete; + UnitFactory& operator=(UnitFactory&&) = delete; - public: /** Units are created by functions that accept no arguments and return * something that can be converted into a Unit::Ptr. */ using CreateUnitCallback = boost::function; @@ -69,7 +72,8 @@ class UTILITIES_API UnitFactorySingleton private: REGISTER_LOGGER("openstudio.units.UnitFactory"); - UnitFactorySingleton(); + UnitFactory(); + ~UnitFactory() = default; using ResultCacheMap = std::map>; @@ -90,60 +94,56 @@ class UTILITIES_API UnitFactorySingleton boost::optional createUnitSimple(const std::string& unitString, UnitSystem system = UnitSystem::Mixed) const; }; -/** Typedef for accessing the UnitFactorySingleton as UnitFactory::instance(). - * \relates UnitFactorySingleton */ -using UnitFactory = openstudio::Singleton; - /** Returns the best match UnitSystem for unitString, in priority order SI, IP, ..., Mixed - * \relates UnitFactorySingleton */ + * \relates UnitFactory */ UTILITIES_API UnitSystem getSystem(const std::string& unitString); -/** Returns true if unitString can be created as a unit in system. \relates UnitFactorySingleton */ +/** Returns true if unitString can be created as a unit in system. \relates UnitFactory */ UTILITIES_API bool isInSystem(const std::string& unitString, UnitSystem system); /** Returns true if any of unitString's baseUnits are registered in the factory. - * \relates UnitFactorySingleton */ + * \relates UnitFactory */ UTILITIES_API bool containsRegisteredBaseUnit(const std::string& unitString); /** Extracts a unitString from text, if possible. Only returns strings that contain at least one - * registered base unit. \relates UnitFactorySingleton */ + * registered base unit. \relates UnitFactory */ UTILITIES_API std::string extractUnitString(const std::string& text); /** Converts unitString to standard form. Right now, does conversion like people/100 m^2 --> - * c(people/m^2). \relates UnitFactorySingleton */ + * c(people/m^2). \relates UnitFactory */ UTILITIES_API std::string convertToStandardForm(const std::string& unitString); /** Replaces unitString in text, using same finder algorithm as extractUnitString. - * \relates UnitFactorySingleton */ + * \relates UnitFactory */ UTILITIES_API std::string replaceUnitString(const std::string& text, const std::string& newUnitString); -/** Returns true if unitString can be turned into a Unit. \relates UnitFactorySingleton */ +/** Returns true if unitString can be turned into a Unit. \relates UnitFactory */ UTILITIES_API bool isUnitString(const std::string& unitString); -/** Returns a Unit of the type that corresponds to system. \relates UnitFactorySingleton */ +/** Returns a Unit of the type that corresponds to system. \relates UnitFactory */ UTILITIES_API Unit createDimensionlessUnit(UnitSystem system); /** Creates a Unit corresponding to unitString (using UnitFactory). User may specify preferred * UnitSystem, and can cast the result to the appropriate class, as desired. - * \relates UnitFactorySingleton */ + * \relates UnitFactory */ UTILITIES_API boost::optional createUnit(const std::string& unitString, UnitSystem system); /** Creates a Unit corresponding to unitString (using UnitFactory). Attempts to find the best - * UnitSystem for unitString, in priority order SI, IP, ..., Mixed. \relates UnitFactorySingleton */ + * UnitSystem for unitString, in priority order SI, IP, ..., Mixed. \relates UnitFactory */ UTILITIES_API boost::optional createUnit(const std::string& unitString); -/** Returns true if uStr1 and uStr2 evaluate to the same unit. \relates UnitFactorySingleton */ +/** Returns true if uStr1 and uStr2 evaluate to the same unit. \relates UnitFactory */ UTILITIES_API bool unitStringsEqual(const std::string& uStr1, const std::string& uStr2); /** In IP units, power density is often expressed as W/ft^2, which is actually a - * mixed unit. \relates UnitFactorySingleton */ + * mixed unit. \relates UnitFactory */ UTILITIES_API Unit createIPPowerDensity(); -/** Make sure crgal^3/min shows up as gal/min. \relates UnitFactorySingleton */ +/** Make sure crgal^3/min shows up as gal/min. \relates UnitFactory */ UTILITIES_API Unit createGPMVolumetricFlowrate(); /** In IP units, pressure is often expressed as lb_f/in^2, which is actually a mixed - * unit. \relates UnitFactorySingleton */ + * unit. \relates UnitFactory */ UTILITIES_API Unit createIPPressure(); } // namespace openstudio diff --git a/src/utilities/units/UnitFactory.i b/src/utilities/units/UnitFactory.i index 88e064abcff..a2595a4233c 100644 --- a/src/utilities/units/UnitFactory.i +++ b/src/utilities/units/UnitFactory.i @@ -6,7 +6,6 @@ %} // hide shared_ptrs from users, just export helper functions -%ignore UnitFactorySingleton; %ignore UnitFactory; %include