diff --git a/Source/Ember/Interpolate.h b/Source/Ember/Interpolate.h index ee80d28..fdbd75e 100644 --- a/Source/Ember/Interpolate.h +++ b/Source/Ember/Interpolate.h @@ -440,15 +440,16 @@ public: Align(&embers[i1], &localEmbers[0], 2); smoothFlag = false; } - - if (i2 == size - 1) + else if (i2 == size - 1) { Align(&embers[i1], &localEmbers[0], 2); smoothFlag = false; } - - Align(&embers[i1 - 1], &localEmbers[0], 4);//Should really be doing some sort of checking here to ensure the ember vectors have 4 elements. - smoothFlag = true; + else + { + Align(&embers[i1 - 1], &localEmbers[0], 4);//Should really be doing some sort of checking here to ensure the ember vectors have 4 elements. + smoothFlag = true; + } } result.m_Time = time; diff --git a/Source/Ember/Utils.h b/Source/Ember/Utils.h index 25fcebf..e2cb048 100644 --- a/Source/Ember/Utils.h +++ b/Source/Ember/Utils.h @@ -193,16 +193,13 @@ private: /// member variables cannot be exported across module boundaries. /// Derived classes should inherit from this using the CRTP, and declare a friend to it. /// They also should make their constructors private and destructors public. -/// This has a severe flaw in that it cannot be used across module boundaries, else -/// every module will have its own copy. This makes it function as a per-module -/// singleton, which is unlikely to ever be desired. /// Attribution: This class is a combination of /// http://btorpey.github.io/blog/2014/02/12/shared-singletons/ /// and /// http://enki-tech.blogspot.com/2012/08/c11-generic-singleton.html /// template -class EMBER_API Singleton +class Singleton { public: /// @@ -213,7 +210,7 @@ public: template static shared_ptr Instance(Args... args) { - static weak_ptr staticInstance; + auto& staticInstance = GetStaticInstance(); auto temp = staticInstance.lock(); if (!temp) @@ -224,6 +221,18 @@ public: return temp; } + +protected: + /// + /// Clever hack to get a static to behave like a member variable that can be seen between classes and functions in the hierarchy. + /// Also has the added benefit that it makes this work across module boundaries. + /// + /// static weak_ptr reference + static std::weak_ptr& GetStaticInstance() + { + static std::weak_ptr staticInstance; + return staticInstance; + } }; //Use this if the body of the destructor will be implemented in a cpp file. @@ -231,8 +240,6 @@ public: friend class Singleton; \ public: \ ~x(); \ - \ - private: \ x(const x& other) = delete; \ const x& operator=(const x& other) = delete//Semicolon deliberately omitted to force it on the caller. @@ -241,33 +248,9 @@ public: friend class Singleton; \ public: \ ~x(){} \ - \ - private: \ x(const x& other) = delete; \ const x& operator=(const x& other) = delete -//Use this if not deriving from the Singleton class and are declaring Instance() in a header and implementing it in a cpp file. -#define SINGLETON_INSTANCE_DECL(x) \ - static std::shared_ptr Instance(); \ - x(const x& other) = delete; \ - const x& operator=(const x& other) = delete//Semicolon deliberately omitted to force it on the caller. - -//Use this if not deriving from the Singleton class and are implementing Instance() in a cpp file. -#define SINGLETON_INSTANCE_IMPL(x) \ - std::shared_ptr x::Instance() \ - { \ - static weak_ptr staticInstance; \ - auto temp = staticInstance.lock(); \ - \ - if (!temp) \ - { \ - temp.reset(new x()); \ - staticInstance = temp; \ - } \ - \ - return temp; \ - } - /// /// Open a file in binary mode and read its entire contents into a vector of bytes. Optionally null terminate. /// diff --git a/Source/Ember/VarFuncs.h b/Source/Ember/VarFuncs.h index cd76889..99d0884 100644 --- a/Source/Ember/VarFuncs.h +++ b/Source/Ember/VarFuncs.h @@ -13,7 +13,7 @@ namespace EmberNs /// This class is a singleton since all of its data is shared and read-only. /// template -class EMBER_API VarFuncs +class EMBER_API VarFuncs : public Singleton> { public: /// @@ -542,7 +542,7 @@ public: } } - SINGLETON_INSTANCE_DECL(VarFuncs);//Implemented in VariationList.cpp + SINGLETON_DERIVED_IMPL(VarFuncs); private: /// diff --git a/Source/Ember/VariationList.cpp b/Source/Ember/VariationList.cpp index b27781e..b20003f 100644 --- a/Source/Ember/VariationList.cpp +++ b/Source/Ember/VariationList.cpp @@ -16,14 +16,6 @@ namespace EmberNs m_Variations.push_back(new Pre##varName##Variation()); \ m_Variations.push_back(new Post##varName##Variation()); -/// -/// Singleton patterns, return a reference to the only instance of this object in existence. -/// -template -SINGLETON_INSTANCE_IMPL(VarFuncs) -template -SINGLETON_INSTANCE_IMPL(VariationList) - /// /// Constructor which initializes all of the variation objects and stores them in the list. /// diff --git a/Source/Ember/VariationList.h b/Source/Ember/VariationList.h index 83f7216..09fb25d 100644 --- a/Source/Ember/VariationList.h +++ b/Source/Ember/VariationList.h @@ -18,10 +18,10 @@ namespace EmberNs /// Template argument expected to be float or double. /// template -class EMBER_API VariationList +class EMBER_API VariationList: public Singleton> { public: - ~VariationList(); + //~VariationList(); const Variation* GetVariation(size_t index) const; const Variation* GetVariation(size_t index, eVariationType varType) const; Variation* GetVariationCopy(size_t index, T weight = 1) const; @@ -45,7 +45,7 @@ public: const vector*>& PreVars() const; const vector*>& PostVars() const; - SINGLETON_INSTANCE_DECL(VariationList);//Implemented in VariationList.cpp + SINGLETON_DERIVED_DECL(VariationList); private: VariationList(); diff --git a/Source/EmberCL/OpenCLInfo.cpp b/Source/EmberCL/OpenCLInfo.cpp index d16de2b..43cbf9d 100644 --- a/Source/EmberCL/OpenCLInfo.cpp +++ b/Source/EmberCL/OpenCLInfo.cpp @@ -68,8 +68,6 @@ OpenCLInfo::OpenCLInfo() } } -SINGLETON_INSTANCE_IMPL(OpenCLInfo) - /// /// Get a const reference to the vector of available platforms. /// diff --git a/Source/EmberCL/OpenCLInfo.h b/Source/EmberCL/OpenCLInfo.h index 3b6a808..cc466f2 100644 --- a/Source/EmberCL/OpenCLInfo.h +++ b/Source/EmberCL/OpenCLInfo.h @@ -17,7 +17,7 @@ namespace EmberCLns /// This class derives from EmberReport, so the caller is able /// to retrieve a text dump of error information if any errors occur. /// -class EMBERCL_API OpenCLInfo : public EmberReport +class EMBERCL_API OpenCLInfo : public EmberReport, public Singleton { public: const vector& Platforms() const; @@ -54,9 +54,10 @@ public: return val; } - SINGLETON_INSTANCE_DECL(OpenCLInfo); + SINGLETON_DERIVED_IMPL(OpenCLInfo); private: + OpenCLInfo(); bool m_Init; diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp index b613fd0..ce5b631 100644 --- a/Source/EmberGenome/EmberGenome.cpp +++ b/Source/EmberGenome/EmberGenome.cpp @@ -339,7 +339,7 @@ bool EmberGenome(EmberOptions& opt) { if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time) { - cerr << "Error: control points must be sorted by time, but " << embers[i].m_Time << " <= " << embers[i - 1].m_Time << ", index " << i << ".\n"; + cerr << "Error: control points must be sorted by time, but time " << embers[i].m_Time << " <= " << embers[i - 1].m_Time << ", index " << i << ".\n"; return false; } @@ -405,6 +405,15 @@ bool EmberGenome(EmberOptions& opt) return false; } + for (i = 0; i < embers.size(); i++) + { + if (i > 0 && embers[i].m_Time <= embers[i - 1].m_Time) + { + cerr << "Error: control points must be sorted by time, but time " << embers[i].m_Time << " <= " << embers[i - 1].m_Time << ", index " << i << ".\n"; + return false; + } + } + if (opt.Enclosed()) cout << "\n"; @@ -529,8 +538,8 @@ bool EmberGenome(EmberOptions& opt) oldY = embers[i].m_CenterY; embers[i].m_FinalRasH = size_t(T(embers[i].m_FinalRasH) / T(opt.Frames())); embers[i].m_CenterY = embers[i].m_CenterY - ((opt.Frames() - 1) * embers[i].m_FinalRasH) / - (2 * embers[i].m_PixelsPerUnit * pow(T(2.0), embers[i].m_Zoom)); - embers[i].m_CenterY += embers[i].m_FinalRasH * opt.Frame() / (embers[i].m_PixelsPerUnit * pow(T(2.0), embers[i].m_Zoom)); + (2 * embers[i].m_PixelsPerUnit * std::pow(T(2.0), embers[i].m_Zoom)); + embers[i].m_CenterY += embers[i].m_FinalRasH * opt.Frame() / (embers[i].m_PixelsPerUnit * std::pow(T(2.0), embers[i].m_Zoom)); tools.RotateOldCenterBy(embers[i].m_CenterX, embers[i].m_CenterY, oldX, oldY, embers[i].m_Rotate); if (pTemplate) diff --git a/Source/Fractorium/Main.cpp b/Source/Fractorium/Main.cpp index 4eb27cd..9295061 100644 --- a/Source/Fractorium/Main.cpp +++ b/Source/Fractorium/Main.cpp @@ -27,8 +27,12 @@ int main(int argc, char* argv[]) putenv(const_cast("GPU_MAX_ALLOC_PERCENT=100")); #endif int rv = -1; - auto vlf = VariationList::Instance();//Create two instances that will stay alive until this function exits. + auto vf = VarFuncs::Instance();//Create instances that will stay alive until the program exits. + auto vlf = VariationList::Instance(); +#ifdef DO_DOUBLE + auto vd = VarFuncs::Instance(); auto vld = VariationList::Instance();//No further creations should occur after this. +#endif try {