/* Copyright 2003-2007 ROBLOX Corporation, All Rights Reserved */ #pragma once #include "rbx/Debug.h" #include "Util/Name.h" #include #include #include "Security/ApiSecurity.h" #include "Security/FuzzyTokens.h" #include "V8DataModel/HackDefines.h" #include "rbx/boost.hpp" #include "boost/weak_ptr.hpp" #include "boost/shared_ptr.hpp" #include "boost/scoped_ptr.hpp" #include "boost/enable_shared_from_this.hpp" using boost::shared_ptr; using boost::scoped_ptr; using boost::weak_ptr; using boost::enable_shared_from_this; namespace RBX { namespace Reflection { class DescribedBase; } enum CreatorRole { ReplicationCreator, SerializationCreator, ScriptingCreator, EngineCreator }; template boost::shared_ptr shared_polymorphic_downcast(const boost::shared_ptr& r) { BOOST_ASSERT(dynamic_cast(r.get()) == r.get()); return boost::static_pointer_cast(r); } template boost::shared_ptr shared_dynamic_cast(const boost::shared_ptr& r) { return boost::dynamic_pointer_cast(r); } template boost::shared_ptr shared_static_cast(const boost::shared_ptr& r) { return boost::static_pointer_cast(r); } // Use this to convert an object to its corresponding boost::shared_ptr template boost::shared_ptr shared_from(T* r) { return r ? boost::static_pointer_cast(r->shared_from_this()) : boost::shared_ptr(); } template weak_ptr weak_from(T* r) { return r ? boost::static_pointer_cast(r->shared_from_this()) : boost::shared_ptr(); } // Use this to downcast an object to a shared_ptr template shared_ptr shared_from_polymorphic_downcast(enable_shared_from_this* r) { return r ? shared_polymorphic_downcast(r->shared_from_this()) : shared_ptr(); } template shared_ptr shared_from_static_cast(enable_shared_from_this* r) { return r ? shared_static_cast(r->shared_from_this()) : shared_ptr(); } template shared_ptr shared_from_dynamic_cast(enable_shared_from_this* r) { return r ? shared_dynamic_cast(r->shared_from_this()) : shared_ptr(); } template inline bool weak_equal(const weak_ptr& lhs, const weak_ptr& rhs) { return !(lhs < rhs) && !(rhs < lhs); } class RBXInterface ICreator { public: virtual shared_ptr create() const = 0; }; template class RBXBaseClass Creatable { public: class Deleter { public: void operator()(Class* instance) { Class::predelete(instance); delete instance; } }; template static shared_ptr create() { shared_ptr obj = shared_ptr(new T(), Deleter()); shared_ptr (*thisFunction)() = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } template static shared_ptr create(P1 p1) { shared_ptr obj = shared_ptr(new T(p1), Deleter()); shared_ptr (*thisFunction)(P1) = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } template static shared_ptr create(P1 p1, P2 p2) { shared_ptr obj = shared_ptr(new T(p1, p2), Deleter()); shared_ptr (*thisFunction)(P1, P2) = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } template static shared_ptr create(P1 p1, P2 p2, P3 p3) { shared_ptr obj = shared_ptr(new T(p1, p2, p3), Deleter()); shared_ptr (*thisFunction)(P1, P2, P3) = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } template static shared_ptr create(P1 p1, P2 p2, P3 p3, P4 p4) { shared_ptr obj = shared_ptr(new T(p1, p2, p3, p4), Deleter()); shared_ptr (*thisFunction)(P1, P2, P3, P4) = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } template static shared_ptr create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) { shared_ptr obj = shared_ptr(new T(p1, p2, p3, p4, p5), Deleter()); shared_ptr (*thisFunction)(P1, P2, P3, P4, P5) = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } template static shared_ptr create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) { shared_ptr obj = shared_ptr(new T(p1, p2, p3, p4, p5, p6), Deleter()); shared_ptr (*thisFunction)(P1, P2, P3, P4, P5, P6) = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } template static shared_ptr create(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7) { shared_ptr obj = shared_ptr(new T(p1, p2, p3, p4, p5, p6, p7), Deleter()); shared_ptr (*thisFunction)(P1, P2, P3, P4, P5, P6, P7) = &create; checkRbxCaller >(reinterpret_cast(thisFunction)); return obj; } static std::map& getCreators() { // TODO: replace with a faster lookup map, like the Loki AssocVector? static std::map creators; return creators; } static shared_ptr createByName(const Name& name, CreatorRole creatorRole) { std::map::iterator iter = getCreators().find(&name); if (iter!=getCreators().end()){ if(shared_ptr result = shared_polymorphic_downcast(iter->second->create())){ switch(creatorRole) { case ReplicationCreator: return result; case SerializationCreator: if(result->getDescriptor().isSerializable()) return result; break; case ScriptingCreator: if(result->getDescriptor().isScriptCreatable()) return result; break; case EngineCreator: return result; } } } return shared_ptr(); } // Get object creator by className static const ICreator* getCreator(const Name& name) { std::map::iterator iter = getCreators().find(&name); return (iter!=getCreators().end()) ? iter->second : NULL; } private: Creatable(); // this is a utility class }; template class FactoryProduct : public BaseClass { class Creator : public ICreator { private: static int isConstructedTrue() {return 666;} static int isConstructed; // debugging - if constructed, == 666 const RBX::Name& getClassNameUnconstructed() const { return RBX::Name::declare(); } public: static bool wasConstructed() {return isConstructed == isConstructedTrue();} /* override */ shared_ptr create() const { RBXASSERT(wasConstructed()); return Creatable::template create(); } const RBX::Name& getClassName() const { RBXASSERT(wasConstructed()); return RBX::Name::declare(); } Creator() { // Register this creator for create-by-className const RBX::Name& name = getClassNameUnconstructed(); auto& creators = Creatable::getCreators(); RBXASSERT(creators.find(&name)==creators.end()); RBXASSERT(!wasConstructed()); creators[&name] = this; isConstructed = isConstructedTrue(); RBXASSERT(creators.find(&name)!=creators.end()); RBXASSERT(wasConstructed()); } ~Creator() { auto& creators = Creatable::getCreators(); RBXASSERT(wasConstructed()); creators.erase(&getClassName()); } }; private: #ifdef _WIN32 static const Creator creatorPrivate; #else static Creator creatorPrivate; #endif protected: FactoryProduct() { } template FactoryProduct(Arg0 arg0):BaseClass(arg0) { } template FactoryProduct(Arg0 arg0, Arg1 arg1):BaseClass(arg0,arg1) { } virtual ~FactoryProduct() { } static const Creator& static_getCreator() { RBXASSERT(Creator::wasConstructed()); return creatorPrivate; } public: const ICreator& getCreator() { return static_getCreator(); } static const RBX::Name& className() { return static_getCreator().getClassName(); }; static bool isNullClassName() { RBXASSERT(!className().empty()); return false; }; const RBX::Name& getClassName() const { return static_getCreator().getClassName(); }; // Convenient static functions for creating an instance of this class: // TODO: Refactor: rename createInstance --> create, but also need to rename AbstractFactoryProduct::create to something else static shared_ptr createInstance() { return Creatable::template create(); } template static shared_ptr createInstance(P1 p1) { return Creatable::template create(p1); } template static shared_ptr createInstance(P1 p1, P2 p2) { return Creatable::template create(p1, p2); } template static shared_ptr createInstance(P1 p1, P2 p2, P3 p3) { return Creatable::template create(p1, p2, p3); } template static shared_ptr createInstance(P1 p1, P2 p2, P3 p3, P4 p4) { return Creatable::template create(p1, p2, p3, p4); } }; // Static Defination Go Here // creatorPrivate was a const earlier, but that gives gcc error while trying to define the variable with const qualification. // gcc error: expected nested-name-specifier before 'const' // This is not a proper way to fix, but I do not have a choice right now. The variable is in a private section of a class so should be safe. template #ifdef _WIN32 typename const FactoryProduct::Creator FactoryProduct::creatorPrivate; #else typename FactoryProduct::Creator FactoryProduct::creatorPrivate; #endif template int FactoryProduct::Creator::isConstructed; // For objects that should NOT be creatable by a factory template class NonFactoryProduct : public BaseClass { public: NonFactoryProduct():BaseClass() {} template NonFactoryProduct(Arg0 arg0):BaseClass(arg0) {} template NonFactoryProduct(Arg0 arg0, Arg1 arg1):BaseClass(arg0, arg1) {} template NonFactoryProduct(Arg0 arg0, Arg1 arg1, Arg2 arg2):BaseClass(arg0, arg1, arg2) {} template NonFactoryProduct(Arg0 arg0, Arg1 arg1, Arg2 arg2, Arg3 arg3):BaseClass(arg0, arg1, arg2, arg3) {} static const RBX::Name& className() { return RBX::Name::declare(); }; static bool isNullClassName() { RBXASSERT(className().empty() == (sClassName==NULL)); return sClassName==NULL; }; const RBX::Name& getClassName() const { return className(); } }; } // namespace RBX