From 33dc0a3b8dfc2ff4f6d673213dabb9362f5fee4d Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sat, 11 Nov 2017 14:59:12 -0800 Subject: [PATCH 01/11] header guards and namespaces --- .swp | Bin 0 -> 57344 bytes include/class_loader/class_loader.h | 8 ++++---- include/class_loader/class_loader_core.h | 6 +++--- include/class_loader/class_loader_exceptions.h | 6 +++++- .../class_loader/class_loader_register_macro.h | 8 ++++---- .../class_loader/console_bridge_compatibility.h | 6 +++--- include/class_loader/meta_object.h | 6 +++--- .../class_loader/multi_library_class_loader.h | 8 ++++---- src/class_loader.cpp | 2 +- src/meta_object.cpp | 4 ++-- src/multi_library_class_loader.cpp | 2 +- test/base.h | 6 +++--- 12 files changed, 33 insertions(+), 29 deletions(-) create mode 100644 .swp diff --git a/.swp b/.swp new file mode 100644 index 0000000000000000000000000000000000000000..e915bc6a54ce68de9a2e48e84402534e35e60936 GIT binary patch literal 57344 zcmeHQe~cVe9bfsOl!EfZP>`0sUP%hM_U>kO_x5i4L+e$rK&iF`skPb6?oMxqo84Jv zW_!Jm${&aVMn%vdL5!ja#(z-2nvnQ|v|`X0Fw~$yOVA)9i6}9mV1l3To0;qEbauP9 zJ9G1v>?Plu-JRK)&wk%~-}n7|-}k*&9J_w&HkKR7r0{nR{d4~8EvZyhn^9EV`=s^J zxo+Kox+P^>Uo|*0(7-?g$!cK9b!k}|BMhsDR zKm!8}3^Xv%z@lovt}jj9f+wEsKJ{YvxcXhr3-^#Z%l&+rdtB}wz4J>0pQi)o&vf5k z=pMHR&M$G_uW*mkf%9j$?=NzXp9!3QPvHCmf%ETn-+#b89txa4-F?5(Jw6jSf13N= zd;V*I^QXG+huq^C0sVRU_4E|fulu#ZVW5G51_l}!Xkeg$fd&Q|7-(Rifq@1F8W?C` zpn+I4pp;Xob8+YU=HENlq(UPuMRzWwEvTBZMwUXW_tIZ$!uPBrZQyr<~rR-#$ zv7Hs8p_f@j*{?E%S#_nPvZ89ws%njmjxwcIW+kIqRckh5duA(|t@3L|-4Ct3Y)@uy zDps7C@xH*B8|w?017neC54=P)N66`{|ci4C{x43%$l=owaO|g**K=`v+>`sEBNnxG~yYuqMBzR)^05; zx%a@U`TMPP?lFQNS!`%}*)yI6!^C6aH*M+YDtT&)QBzsnG)k&vX|-tB2Ax`rZg>grJ4)b`^?V}O>8XIG!ief4yR9uVc2AX11iBnk@bhS2ZS5V|J zSy4imrg|wh!kp*`C32R8*5Md6Y>^R4Z;QxQrEAT(+y73j(43^#hgL6sUE27T1m6X%`qD_TLY!^K8v+$Z~Xd$;QXHk=l>7*{szdc z;QUX4?@N&Hfb%bd+zihD0yzH;$PsY<<&ZCf@1F*F1f2f|klP_QKvqHijTpesA@@P5 zkSWM{kiQ@%a0qfMWEbR8$eSLfU|eAEexQK`X<(OOD>_q6lZ?kcqE&e&XXMlre9~#d zoMUTzPN}UF*95LjhhJ&bRZ}5@6uiF0ooni>4*w^3wbbHry4LlTf?t`)h9mOgQo-wU zEgnJFE5VDU@OvM3)`MU0gYir(j5T;z@XCzu*4~w#F%Djv^Iz*DHnveVg4g;XhmxS+ z7yLkUbz0F8(yPyz+H}PZUOMi>(ae))D~es1Ga7}4bz-4TwEP;U*TJVqEguuSay%6U z+eIYP9&OP7ky5?h4Y6&$LtdJoZhCXM%vQU74BN0@rT%&onw-g;*BdsW8*Z&dbjaPs zQ-fe~L`dK`^hnaQ5BV`i1HZwn1WCJ^Prud52ea5Y|r z7Gg4P#KYnr)J?UdmMIiwL)S%cL> zk3Yv|D;PmV2$~GwNQLdwbc6~6J%3b1Ps0f9G}xYJ3!p{{VkP(ki2oDke~>s8_`jFm zz6t#Q74ZMRLe@a;MGW8R zz~x^Am){0Cgz^4QLUu#=^E%>jz1LK-Yu6g^uv{mfVW`DYrd5Xx!Yu7J8eY%tW&;rY zf+d@p|H_^@bohJOhU1@XpRK9pCK}WTa0pawjJZVTr`NQb8fu|#n+0lty?N{>-YYLj zR0W&e<;C{hLtsskZEQy6bQ+80#D`##WKxx|?tBdPa(i$z_ej*ADv)PM%6Ed?6OMJLESw%%Q7Pn?~SvNjT#H z2ngooY3SSaC+CxWI!qoC^cNA)Xy+lfCP@MH2vR~Pqb&XQdnk1HPAVVAG;^B}I&|A_ z#xz1*a!)+Wf0KOI?PvZjJs39P{}bThe7-yQzc>Hg0RKM* z-oFiUKe+!t!TpPnrI0frHzEdb2r+;QAo~#q_%Y%DDdLdaW)2fPWn0`dlp z|3fxF9z|T>HN*whL4Jq0z;lolkgp&vz;SdG7YM(o+i1bOE~$q4EWkqh(E0oHP$rT5 zh9q14yb|6q&0UJ3x$~R!+}x#J5`ucHTFx)%y?G@68w6+`jxzhZH!NZvIX8~*_!HwIm{dR$)T#~L){y01G!=8M;Lq9b)}oyJuK5Y7-OaJn#f#{6g73s^ zk;RJbc7RSABLgSegp3Y=^IX}a(k42)Gd7z!r7`Nq2#i^3r34p;Q^%tC5RK1+ZTwPOJlW+-GQ5}@cNI1&H99aQ=( zaBmv__twXo2LJyVxc_C4FM~*IZF#31vfyvLWtO& z#PqH*O}n=l>D?{t)y8L* z1*IIx&VFd4Fp1LI1#GPnCA*04UX2MF@XT;vg1aJPg7#ozV!9$}LE|ZD9#0X^hNMLe zR5-xIZk!HA5et<%1_5#Lh0O)T#n-Qo1Q+rDo59213h;j#|9=|Xe;o1+@PAtOzY6|; z6x@G3XF_fQ|NkYp|7ytR!T(xc)O3YkGX;90~1);F~60(L?k#}AzC z+J=RHw#A$FyI`f{d8gA1x2n{g6}<5xt_^_}4pim_u^H)N z&0FpQtsGg~rtyEu`Tr`BYViLHU2&uW^!S#=V>t717!S#=T=f59P2G@TKJpVMvE^vMREcZE~hc3F5E|kc#Bn26X zSU7x%Z!MLSW8MW`KDVZi@N$dLM|k;OP<@0q(X8$+>TjZXAzk3*!}@(xA9!+e|KOcW zGM{+i)nOvZWfc|_3s-}rJZ|!lfwJ4%?;Vr|rT3UoW*nd}SFiQqOB!1Qe zPaY#eCPFCac62H%B}=fTqEg1+r>v4=O}eA3=- zR$S{ueS8^Hu@F(RT6c(u|AUsNzDPtI{C~Mi$oGK%KL+mqQOK1LS_AMo@c)&NX>k9C z!TnE%+ynl9H{@mT|0^N)A_nj>_--&r2Rj8qQqo`}8JcW&Yl_`R~mOH3ZoVz6! zj_(v;pO}nvbR%8y)JG055~dSdpH9A@p{s?WsgVcA4w>6mgxNMLA z3Hb@~;sv5_Ep_1_6*e}~8aE$a=|kLno>Cv;=C-pBar2dlBF7z{BkFf&N`~3xZbK(G z=FYwIGH3VAmMY;4i>5a3!W`$*)5>MG+Wlp0L&N6YxszN`S2VMu>ubk@BcM8|1wA&eE%u% z{Z)`TaQ!F2^)G?Ufa~+;xX*~_5Q}f;RR_L2i&)G&tUkybr?3P)9CD)bq&l|8N*Hg0)jl@R?NzSTj4Ff1;gqCV$yr@>ynjMHsdY^WkgxEP`o@v(ywU*Da z?E{>NF8h2u1l;kRe3xJvEN(l?Z*ImTDWPpDOXaAI0xUrJQh?GGT2<;tRj^fjYWiae$W)2N;GNK^)*PWH}^xAP2b%v4B?)3)l?d&vl>Kbcoej z^7Rv=QDCe%lU;kI;|kd)){+}b@k`x_EIav^6@_Q3ILrNcafZ=Rf0Us)U&R+>$V8U` z71l>)#Y?kj3A3+w24C^QO>rF_X4V|?1gfl}Qr-Y_mV7kq3SK)Ojd=5Ti)x-Wu0Eb) z;JC2K=eCA`%BQ0X{w>PbLrkNjBbd|4ced_rf9Bv^XPP?AZ3beE*?7zVAs_E7vCh=? zE4I2=nRWi!Mj!>utqXoNmx~o3}tn5|fq!&4*i{ ccGHxmf}UMVH*TcTy$2UqC&MLl{ #include @@ -275,7 +275,7 @@ class ClassLoader static bool has_unmananged_instance_been_created_; }; -} +} // namespace class_loader -#endif +#endif // CLASS_LOADER__CLASS_LOADER_H_ diff --git a/include/class_loader/class_loader_core.h b/include/class_loader/class_loader_core.h index 021f1479..db1025fd 100644 --- a/include/class_loader/class_loader_core.h +++ b/include/class_loader/class_loader_core.h @@ -27,8 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef class_loader_private_H_DEFINED -#define class_loader_private_H_DEFINED +#ifndef CLASS_LOADER__CLASS_LOADER_CORE_H_ +#define CLASS_LOADER__CLASS_LOADER_CORE_H_ #include #include @@ -295,4 +295,4 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader); } //End namespace class_loader_private } //End namespace class_loader -#endif +#endif // CLASS_LOADER__CLASS_LOADER_CORE_H_ diff --git a/include/class_loader/class_loader_exceptions.h b/include/class_loader/class_loader_exceptions.h index 3ba9b91d..1d6cfc10 100644 --- a/include/class_loader/class_loader_exceptions.h +++ b/include/class_loader/class_loader_exceptions.h @@ -27,6 +27,9 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef CLASS_LOADER__CLASS_LOADER_EXCEPTIONS_H_ +#define CLASS_LOADER__CLASS_LOADER_EXCEPTIONS_H_ + #include namespace class_loader @@ -82,4 +85,5 @@ class NoClassLoaderExistsException: public ClassLoaderException NoClassLoaderExistsException(const std::string error_desc) : ClassLoaderException(error_desc) {} }; -} +} // namespace class_loader +#endif // CLASS_LOADER__CLASS_LOADER_EXCEPTIONS_H_ diff --git a/include/class_loader/class_loader_register_macro.h b/include/class_loader/class_loader_register_macro.h index 159fde53..94773fac 100644 --- a/include/class_loader/class_loader_register_macro.h +++ b/include/class_loader/class_loader_register_macro.h @@ -27,8 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CLASS_LOADER_REGISTER_MACRO_H_DEFINED -#define CLASS_LOADER_REGISTER_MACRO_H_DEFINED +#ifndef CLASS_LOADER__CLASS_LOADER_REGISTER_MACRO_H_ +#define CLASS_LOADER__CLASS_LOADER_REGISTER_MACRO_H_ #include "class_loader_core.h" #include @@ -50,7 +50,7 @@ namespace \ }\ };\ static ProxyExec##UniqueID g_register_plugin_##UniqueID;\ -} +} // namespace #define CLASS_LOADER_REGISTER_CLASS_INTERNAL_HOP1_WITH_MESSAGE(Derived, Base, UniqueID, Message) CLASS_LOADER_REGISTER_CLASS_INTERNAL_WITH_MESSAGE(Derived, Base, UniqueID, Message) @@ -66,5 +66,5 @@ namespace \ */ #define CLASS_LOADER_REGISTER_CLASS(Derived, Base) CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(Derived, Base, "") -#endif +#endif // CLASS_LOADER__CLASS_LOADER_REGISTER_MACRO_H_ diff --git a/include/class_loader/console_bridge_compatibility.h b/include/class_loader/console_bridge_compatibility.h index e66d6033..9f8610e1 100644 --- a/include/class_loader/console_bridge_compatibility.h +++ b/include/class_loader/console_bridge_compatibility.h @@ -1,5 +1,5 @@ -#ifndef CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H -#define CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H +#ifndef CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H_ +#define CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H_ #include @@ -19,4 +19,4 @@ #define CONSOLE_BRIDGE_logInform logInform #endif -#endif // CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H +#endif // CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H_ diff --git a/include/class_loader/meta_object.h b/include/class_loader/meta_object.h index 8598a5a9..e14089b5 100644 --- a/include/class_loader/meta_object.h +++ b/include/class_loader/meta_object.h @@ -29,8 +29,8 @@ //Note: This header defines a simplication of Poco::MetaObject that allows us to tag MetaObjects with an associated library name. -#ifndef PLUGINS_PRIVATE_META_OBJECT_DEFINED -#define PLUGINS_PRIVATE_META_OBJECT_DEFINED +#ifndef CLASS_LOADER__META_OBJECT_H_ +#define CLASS_LOADER__META_OBJECT_H_ #include #include @@ -199,4 +199,4 @@ class MetaObject: public AbstractMetaObject } // End namespace class_loader_private } // End namespace class_loader -#endif +#endif // CLASS_LOADER__META_OBJECT_H_ diff --git a/include/class_loader/multi_library_class_loader.h b/include/class_loader/multi_library_class_loader.h index 934eb96c..f0c0d74c 100644 --- a/include/class_loader/multi_library_class_loader.h +++ b/include/class_loader/multi_library_class_loader.h @@ -27,8 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef CLASS_LOADER_MULTI_LIBRARY_CLASS_LOADER_H_DEFINED -#define CLASS_LOADER_MULTI_LIBRARY_CLASS_LOADER_H_DEFINED +#ifndef CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_ +#define CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_ #include "class_loader.h" #include @@ -288,5 +288,5 @@ class MultiLibraryClassLoader }; -} -#endif +} // namespace class_loader +#endif // CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_ diff --git a/src/class_loader.cpp b/src/class_loader.cpp index db929c77..37252d30 100644 --- a/src/class_loader.cpp +++ b/src/class_loader.cpp @@ -103,4 +103,4 @@ int ClassLoader::unloadLibraryInternal(bool lock_plugin_ref_count) return(load_ref_count_); } -} +} // namespace class_loader diff --git a/src/meta_object.cpp b/src/meta_object.cpp index c704a59f..47728243 100644 --- a/src/meta_object.cpp +++ b/src/meta_object.cpp @@ -118,7 +118,7 @@ ClassLoaderVector AbstractMetaObjectBase::getAssociatedClassLoaders() return(associated_class_loaders_); } -} +} // namespace class_loader_private -} +} // namespace class_loader diff --git a/src/multi_library_class_loader.cpp b/src/multi_library_class_loader.cpp index 4c625da8..47b609c5 100644 --- a/src/multi_library_class_loader.cpp +++ b/src/multi_library_class_loader.cpp @@ -99,4 +99,4 @@ int MultiLibraryClassLoader::unloadLibrary(const std::string& library_path) return(remaining_unloads); } -} +} // namespace class_loader diff --git a/test/base.h b/test/base.h index aa76a04b..8ed7cee6 100644 --- a/test/base.h +++ b/test/base.h @@ -1,5 +1,5 @@ -#ifndef BASE_H -#define BASE_H +#ifndef BASE_H_ +#define BASE_H_ class Base { @@ -7,4 +7,4 @@ class Base virtual void saySomething() = 0; }; -#endif +#endif // BASE_H_ From e321fa93c890442dccea8002c5efceecdc220dba Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sat, 11 Nov 2017 15:26:19 -0800 Subject: [PATCH 02/11] [cpplint] whitespaces --- include/class_loader/class_loader.h | 1 - include/class_loader/class_loader_core.h | 4 +- .../class_loader_register_macro.h | 2 +- include/class_loader/meta_object.h | 7 ++-- .../class_loader/multi_library_class_loader.h | 4 +- src/class_loader_core.cpp | 38 ++++++++----------- src/multi_library_class_loader.cpp | 5 ++- test/unique_ptr_test.cpp | 1 - test/utest.cpp | 9 ++--- 9 files changed, 30 insertions(+), 41 deletions(-) diff --git a/include/class_loader/class_loader.h b/include/class_loader/class_loader.h index df1bf688..fb26d186 100644 --- a/include/class_loader/class_loader.h +++ b/include/class_loader/class_loader.h @@ -265,7 +265,6 @@ class ClassLoader int unloadLibraryInternal(bool lock_plugin_ref_count); private: - bool ondemand_load_unload_; std::string library_path_; int load_ref_count_; diff --git a/include/class_loader/class_loader_core.h b/include/class_loader/class_loader_core.h index db1025fd..91a01d6c 100644 --- a/include/class_loader/class_loader_core.h +++ b/include/class_loader/class_loader_core.h @@ -216,9 +216,9 @@ Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: ALERT!!! A metaobject (i.e. factory) exists for desired class, but has no owner. This implies that the library containing the class was dlopen()ed by means other than through the class_loader interface. This can happen if you build plugin libraries that contain more than just plugins (i.e. normal code your app links against) -- that intrinsically will trigger a dlopen() prior to main(). You should isolate your plugins into their own library, otherwise it will not be possible to shutdown the library!"); obj = factory->create(); - } - else + } else { throw(class_loader::CreateClassException("Could not create instance of type " + derived_class_name)); + } } CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Created instance of type %s and object pointer = %p", (typeid(obj).name()), obj); diff --git a/include/class_loader/class_loader_register_macro.h b/include/class_loader/class_loader_register_macro.h index 94773fac..71bb667f 100644 --- a/include/class_loader/class_loader_register_macro.h +++ b/include/class_loader/class_loader_register_macro.h @@ -44,7 +44,7 @@ namespace \ typedef Base _base; \ ProxyExec##UniqueID() \ { \ - if(std::string(Message)!="")\ + if(std::string(Message) != "")\ CONSOLE_BRIDGE_logInform("%s", Message);\ class_loader::class_loader_private::registerPlugin<_derived, _base>(#Derived, #Base); \ }\ diff --git a/include/class_loader/meta_object.h b/include/class_loader/meta_object.h index e14089b5..4c0317eb 100644 --- a/include/class_loader/meta_object.h +++ b/include/class_loader/meta_object.h @@ -55,7 +55,6 @@ typedef std::vector ClassLoaderVector; class AbstractMetaObjectBase { public: - /** * @brief Constructor for the class */ @@ -159,8 +158,8 @@ class AbstractMetaObject : public AbstractMetaObjectBase * @return A pointer of parametric type B to a newly created object. */ virtual B* create() const = 0; - /// Create a new instance of a class. - /// Cannot be used for singletons. + /// Create a new instance of a class. + /// Cannot be used for singletons. private: AbstractMetaObject(); @@ -192,7 +191,7 @@ class MetaObject: public AbstractMetaObject */ B* create() const { - return new C; + return new C; } }; diff --git a/include/class_loader/multi_library_class_loader.h b/include/class_loader/multi_library_class_loader.h index f0c0d74c..8213c1a1 100644 --- a/include/class_loader/multi_library_class_loader.h +++ b/include/class_loader/multi_library_class_loader.h @@ -215,9 +215,9 @@ class MultiLibraryClassLoader { available_classes = loader->getAvailableClasses(); return(available_classes); - } - else + } else { throw class_loader::NoClassLoaderExistsException("There is no ClassLoader in MultiLibraryClassLoader bound to library " + library_path + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + } } /** diff --git a/src/class_loader_core.cpp b/src/class_loader_core.cpp index 6fc60925..53b59e06 100644 --- a/src/class_loader_core.cpp +++ b/src/class_loader_core.cpp @@ -194,7 +194,7 @@ MetaObjectVector filterAllMetaObjectsAssociatedWithLibrary(const MetaObjectVecto { MetaObjectVector filtered_objs; for(unsigned int c = 0; c < to_filter.size(); c++) - if(to_filter.at(c)->getAssociatedLibraryPath()==library_path) + if(to_filter.at(c)->getAssociatedLibraryPath() == library_path) filtered_objs.push_back(to_filter.at(c)); return(filtered_objs); } @@ -248,12 +248,12 @@ void destroyMetaObjectsForLibrary(const std::string& library_path, FactoryMap& f //with RTLD_GLOBAL instead of RTLD_LOCAL. We require using the former as the which is required to support //RTTI insertMetaObjectIntoGraveyard(meta_obj); - } - else + } else { factory_itr++; - } - else + } + } else { factory_itr++; + } } } @@ -308,9 +308,9 @@ bool isLibraryLoadedByAnybody(const std::string& library_path) { assert(itr->second->isLoaded() == true); //Ensure Poco actually thinks the library is loaded return(true); - } - else + } else { return(false); + } }; bool isLibraryLoaded(const std::string& library_path, ClassLoader* loader) @@ -318,7 +318,7 @@ bool isLibraryLoaded(const std::string& library_path, ClassLoader* loader) { bool is_lib_loaded_by_anyone = isLibraryLoadedByAnybody(library_path); int num_meta_objs_for_lib = allMetaObjectsForLibrary(library_path).size(); - int num_meta_objs_for_lib_bound_to_loader = allMetaObjectsForLibraryOwnedBy(library_path,loader).size(); + int num_meta_objs_for_lib_bound_to_loader = allMetaObjectsForLibraryOwnedBy(library_path, loader).size(); bool are_meta_objs_bound_to_loader = (num_meta_objs_for_lib == 0) ? true : (num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib); return(is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader); @@ -397,18 +397,17 @@ void purgeGraveyardOfMetaobjects(const std::string& library_path, ClassLoader* l itr = graveyard.erase(itr); if(delete_objs) { - if(is_address_in_graveyard_same_as_global_factory_map) + if(is_address_in_graveyard_same_as_global_factory_map) { CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Newly created metaobject factory in global factory map map has same address as one in graveyard -- metaobject has been purged from graveyard but not deleted."); - else - { + } else { assert(hasANonPurePluginLibraryBeenOpened() == false); CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Also destroying metaobject %p (class = %s, base_class = %s, library_path = %s) in addition to purging it from graveyard.", obj, obj->className().c_str(), obj->baseClassName().c_str(), obj->getAssociatedLibraryPath().c_str()); delete(obj); //Note: This is the only place where metaobjects can be destroyed } } - } - else + } else { itr++; + } } } @@ -431,7 +430,6 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) Poco::SharedLibrary* library_handle = NULL; { - try { setCurrentlyActiveClassLoader(loader); @@ -471,9 +469,7 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Though the library %s was just loaded, it seems no factory metaobjects were registered. Checking factory graveyard for previously loaded metaobjects...", library_path.c_str()); revivePreviouslyCreateMetaobjectsFromGraveyard(library_path, loader); purgeGraveyardOfMetaobjects(library_path, loader, false); //Note: The 'false' indicates we don't want to invoke delete on the metaobject - } - else - { + } else { CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Library %s generated new factory metaobjects on load. Destroying graveyarded objects from previous loads...", library_path.c_str()); purgeGraveyardOfMetaobjects(library_path, loader, true); } @@ -490,9 +486,7 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader) if(hasANonPurePluginLibraryBeenOpened()) { CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Cannot unload %s or ANY other library as a non-pure plugin library was opened. As class_loader has no idea which libraries class factories were exported from, it can safely close any library without potentially unlinking symbols that are still actively being used. You must refactor your plugin libraries to be made exclusively of plugins in order for this error to stop happening.", library_path.c_str()); - } - else - { + } else { CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Unloading library %s on behalf of ClassLoader %p...", library_path.c_str(), loader); boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex()); LibraryVector& open_libraries = getLoadedLibraryVector(); @@ -513,9 +507,9 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader) assert(library->isLoaded() == false); delete(library); itr = open_libraries.erase(itr); - } - else + } else { CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: MetaObjects still remain in memory meaning other ClassLoaders are still using library, keeping library %s open.", library_path.c_str()); + } return; } catch(const Poco::RuntimeException& e) diff --git a/src/multi_library_class_loader.cpp b/src/multi_library_class_loader.cpp index 47b609c5..0c16210c 100644 --- a/src/multi_library_class_loader.cpp +++ b/src/multi_library_class_loader.cpp @@ -53,8 +53,9 @@ std::vector MultiLibraryClassLoader::getRegisteredLibraries() ClassLoader* MultiLibraryClassLoader::getClassLoaderForLibrary(const std::string& library_path) { LibraryToClassLoaderMap::iterator itr = active_class_loaders_.find(library_path); - if (itr != active_class_loaders_.end()) return itr->second; - else return NULL; + if (itr != active_class_loaders_.end()) { + return itr->second; + } else {return NULL;} } ClassLoaderVector MultiLibraryClassLoader::getAllAvailableClassLoaders() diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index acb6b764..077977f6 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -151,7 +151,6 @@ TEST(ClassLoaderUniquePtrTest, threadSafety) loader1.unloadLibrary(); ASSERT_FALSE(loader1.isLibraryLoaded()); - } catch(const class_loader::ClassLoaderException& ex) { diff --git a/test/utest.cpp b/test/utest.cpp index 3513334a..2bbf13ca 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -140,14 +140,12 @@ TEST(ClassLoaderTest, invalidBase) if(loader1.isClassAvailable("Cat")) { FAIL() << "Cat should not be available for InvalidBase"; - } - else if(loader1.isClassAvailable("Cat")) - { + } else if(loader1.isClassAvailable("Cat")) { SUCCEED(); return; - } - else + } else { FAIL() << "Class not available for correct base class."; + } } catch(const class_loader::LibraryLoadException& e) { @@ -196,7 +194,6 @@ TEST(ClassLoaderTest, threadSafety) loader1.unloadLibrary(); ASSERT_FALSE(loader1.isLibraryLoaded()); - } catch(const class_loader::ClassLoaderException& ex) { From 1970901455748dda5bf974513b7ea35b0b2e17bf Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sat, 11 Nov 2017 15:32:52 -0800 Subject: [PATCH 03/11] includes --- include/class_loader/class_loader.h | 14 ++++++++------ include/class_loader/class_loader_core.h | 11 +++++++---- include/class_loader/class_loader_exceptions.h | 1 + include/class_loader/class_loader_register_macro.h | 6 ++++-- include/class_loader/meta_object.h | 3 ++- include/class_loader/multi_library_class_loader.h | 6 +++++- src/class_loader.cpp | 2 ++ src/class_loader_core.cpp | 2 ++ src/meta_object.cpp | 2 ++ src/multi_library_class_loader.cpp | 3 +++ test/plugins1.cpp | 6 ++++-- test/plugins2.cpp | 6 ++++-- test/unique_ptr_test.cpp | 5 ++++- test/utest.cpp | 13 +++++++++---- 14 files changed, 57 insertions(+), 23 deletions(-) diff --git a/include/class_loader/class_loader.h b/include/class_loader/class_loader.h index fb26d186..99a21ba0 100644 --- a/include/class_loader/class_loader.h +++ b/include/class_loader/class_loader.h @@ -30,19 +30,21 @@ #ifndef CLASS_LOADER__CLASS_LOADER_H_ #define CLASS_LOADER__CLASS_LOADER_H_ +#include #include #include -#include -#include #include -#include -#include "class_loader/class_loader_register_macro.h" +#include + +#include "console_bridge/console.h" + #include "class_loader/class_loader_core.h" +#include "class_loader/class_loader_register_macro.h" #include "class_loader/console_bridge_compatibility.h" #if __cplusplus >= 201103L -# include -# include +#include +#include #endif namespace class_loader diff --git a/include/class_loader/class_loader_core.h b/include/class_loader/class_loader_core.h index 91a01d6c..5bf5096e 100644 --- a/include/class_loader/class_loader_core.h +++ b/include/class_loader/class_loader_core.h @@ -30,15 +30,18 @@ #ifndef CLASS_LOADER__CLASS_LOADER_CORE_H_ #define CLASS_LOADER__CLASS_LOADER_CORE_H_ -#include #include -//#include +#include #include -#include #include +#include +#include +#include + +#include "Poco/SharedLibrary.h" + #include "class_loader/meta_object.h" #include "class_loader/class_loader_exceptions.h" -#include /** * @note This header file is the internal implementation of the plugin system which is exposed via the ClassLoader class diff --git a/include/class_loader/class_loader_exceptions.h b/include/class_loader/class_loader_exceptions.h index 1d6cfc10..8591c912 100644 --- a/include/class_loader/class_loader_exceptions.h +++ b/include/class_loader/class_loader_exceptions.h @@ -31,6 +31,7 @@ #define CLASS_LOADER__CLASS_LOADER_EXCEPTIONS_H_ #include +#include namespace class_loader { diff --git a/include/class_loader/class_loader_register_macro.h b/include/class_loader/class_loader_register_macro.h index 71bb667f..484500d9 100644 --- a/include/class_loader/class_loader_register_macro.h +++ b/include/class_loader/class_loader_register_macro.h @@ -30,11 +30,13 @@ #ifndef CLASS_LOADER__CLASS_LOADER_REGISTER_MACRO_H_ #define CLASS_LOADER__CLASS_LOADER_REGISTER_MACRO_H_ -#include "class_loader_core.h" -#include +#include +#include "class_loader/class_loader_core.h" #include "class_loader/console_bridge_compatibility.h" +#include "console_bridge/console.h" + #define CLASS_LOADER_REGISTER_CLASS_INTERNAL_WITH_MESSAGE(Derived, Base, UniqueID, Message) \ namespace \ {\ diff --git a/include/class_loader/meta_object.h b/include/class_loader/meta_object.h index 4c0317eb..45d794f4 100644 --- a/include/class_loader/meta_object.h +++ b/include/class_loader/meta_object.h @@ -33,8 +33,9 @@ #define CLASS_LOADER__META_OBJECT_H_ #include -#include #include +#include +#include #include "class_loader/console_bridge_compatibility.h" diff --git a/include/class_loader/multi_library_class_loader.h b/include/class_loader/multi_library_class_loader.h index 8213c1a1..1d4a6d24 100644 --- a/include/class_loader/multi_library_class_loader.h +++ b/include/class_loader/multi_library_class_loader.h @@ -30,8 +30,12 @@ #ifndef CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_ #define CLASS_LOADER__MULTI_LIBRARY_CLASS_LOADER_H_ -#include "class_loader.h" #include +#include +#include +#include + +#include "class_loader/class_loader.h" namespace class_loader { diff --git a/src/class_loader.cpp b/src/class_loader.cpp index 37252d30..3ab6d4fb 100644 --- a/src/class_loader.cpp +++ b/src/class_loader.cpp @@ -29,6 +29,8 @@ #include "class_loader/class_loader.h" +#include + namespace class_loader { diff --git a/src/class_loader_core.cpp b/src/class_loader_core.cpp index 53b59e06..d7fee055 100644 --- a/src/class_loader_core.cpp +++ b/src/class_loader_core.cpp @@ -30,6 +30,8 @@ #include "class_loader/class_loader_core.h" #include "class_loader/class_loader.h" #include +#include +#include namespace class_loader { diff --git a/src/meta_object.cpp b/src/meta_object.cpp index 47728243..f1836c64 100644 --- a/src/meta_object.cpp +++ b/src/meta_object.cpp @@ -27,6 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + #include "class_loader/meta_object.h" #include "class_loader/class_loader.h" diff --git a/src/multi_library_class_loader.cpp b/src/multi_library_class_loader.cpp index 0c16210c..b960a3de 100644 --- a/src/multi_library_class_loader.cpp +++ b/src/multi_library_class_loader.cpp @@ -29,6 +29,9 @@ #include "class_loader/multi_library_class_loader.h" +#include +#include + namespace class_loader { diff --git a/test/plugins1.cpp b/test/plugins1.cpp index 966a747d..520fe0ab 100644 --- a/test/plugins1.cpp +++ b/test/plugins1.cpp @@ -1,6 +1,8 @@ -#include "base.h" #include -#include + +#include "class_loader/class_loader.h" + +#include "./base.h" class Dog : public Base { diff --git a/test/plugins2.cpp b/test/plugins2.cpp index 95eabfd2..6f51f5ff 100644 --- a/test/plugins2.cpp +++ b/test/plugins2.cpp @@ -1,6 +1,8 @@ -#include "base.h" #include -#include + +#include "class_loader/class_loader.h" + +#include "./base.h" class Robot : public Base { diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index 077977f6..fad1ad69 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -28,7 +28,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include "base.h" #include #include @@ -37,6 +36,10 @@ #include #include +#include +#include + +#include "./base.h" const std::string LIBRARY_1 = "libclass_loader_TestPlugins1.so"; const std::string LIBRARY_2 = "libclass_loader_TestPlugins2.so"; diff --git a/test/utest.cpp b/test/utest.cpp index 2bbf13ca..d794b48c 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -1,10 +1,15 @@ #include #include #include -#include -#include -#include "base.h" -#include +#include +#include + +#include "class_loader/class_loader.h" +#include "class_loader/multi_library_class_loader.h" + +#include "gtest/gtest.h" + +#include "./base.h" const std::string LIBRARY_1 = "libclass_loader_TestPlugins1.so"; const std::string LIBRARY_2 = "libclass_loader_TestPlugins2.so"; From 16db89e9732a0a6b0d3e8784b54f0c585b3b4f6a Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 20:44:01 -0800 Subject: [PATCH 04/11] line length --- include/class_loader/class_loader.h | 45 +++- include/class_loader/class_loader_core.h | 105 ++++++--- .../class_loader_register_macro.h | 9 +- include/class_loader/meta_object.h | 9 +- .../class_loader/multi_library_class_loader.h | 71 ++++-- src/class_loader.cpp | 18 +- src/class_loader_core.cpp | 221 +++++++++++++----- src/meta_object.cpp | 15 +- src/multi_library_class_loader.cpp | 15 +- test/unique_ptr_test.cpp | 10 +- test/utest.cpp | 8 +- 11 files changed, 378 insertions(+), 148 deletions(-) diff --git a/include/class_loader/class_loader.h b/include/class_loader/class_loader.h index 99a21ba0..35274054 100644 --- a/include/class_loader/class_loader.h +++ b/include/class_loader/class_loader.h @@ -130,7 +130,9 @@ class ClassLoader UniquePtr createUniqueInstance(const std::string& derived_class_name) { Base* raw = createRawInstance(derived_class_name, true); - return std::unique_ptr>(raw, boost::bind(&ClassLoader::onPluginDeletion, this, _1)); + return std::unique_ptr>( + raw, + boost::bind(&ClassLoader::onPluginDeletion, this, _1)); } #endif @@ -162,8 +164,9 @@ class ClassLoader bool isClassAvailable(const std::string& class_name) { std::vector available_classes = getAvailableClasses(); - return(std::find(available_classes.begin(), available_classes.end(), class_name) != available_classes.end()); - } + return std::find( + available_classes.begin(), available_classes.end(), class_name) != available_classes.end(); + } /** * @brief Indicates if a library is loaded within the scope of this ClassLoader. Note that the library may already be loaded internally through another ClassLoader, but until loadLibrary() method is called, the ClassLoader cannot create objects from said library. If we want to see if the library has been opened by somebody else, @see isLibraryLoadedByAnyClassloader() @@ -203,7 +206,8 @@ class ClassLoader template void onPluginDeletion(Base* obj) { - CONSOLE_BRIDGE_logDebug("class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n", obj); + CONSOLE_BRIDGE_logDebug( + "class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n", obj); if(obj) { boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_); @@ -212,10 +216,16 @@ class ClassLoader assert(plugin_ref_count_ >= 0); if(plugin_ref_count_ == 0 && isOnDemandLoadUnloadEnabled()) { - if(!ClassLoader::hasUnmanagedInstanceBeenCreated()) + if(!ClassLoader::hasUnmanagedInstanceBeenCreated()) { unloadLibraryInternal(false); - else - CONSOLE_BRIDGE_logWarn("class_loader::ClassLoader: Cannot unload library %s even though last shared pointer went out of scope. This is because createUnmanagedInstance was used within the scope of this process, perhaps by a different ClassLoader. Library will NOT be closed.", getLibraryPath().c_str()); + } else { + CONSOLE_BRIDGE_logWarn( + "class_loader::ClassLoader: " + "Cannot unload library %s even though last shared pointer went out of scope. " + "This is because createUnmanagedInstance was used within the scope of this process," + " perhaps by a different ClassLoader. Library will NOT be closed.", + getLibraryPath().c_str()); + } } } } @@ -236,14 +246,25 @@ class ClassLoader if (!managed) has_unmananged_instance_been_created_ = true; - if (managed && ClassLoader::hasUnmanagedInstanceBeenCreated() && isOnDemandLoadUnloadEnabled()) - CONSOLE_BRIDGE_logInform("class_loader::ClassLoader: An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), however an unmanaged instance was created within this process address space. This means libraries for the managed instances will not be shutdown automatically on final plugin destruction if on demand (lazy) loading/unloading mode is used."); - + if ( + managed && + ClassLoader::hasUnmanagedInstanceBeenCreated() && + isOnDemandLoadUnloadEnabled()) + { + CONSOLE_BRIDGE_logInform( + "class_loader::ClassLoader: " + "An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), " + "however an unmanaged instance was created within this process address space. " + "This means libraries for the managed instances will not be shutdown automatically on " + "final plugin destruction if on demand (lazy) loading/unloading mode is used." + ); + } if (!isLibraryLoaded()) loadLibrary(); - Base* obj = class_loader::class_loader_private::createInstance(derived_class_name, this); - assert(obj != NULL); //Unreachable assertion if createInstance() throws on failure + Base* obj = + class_loader::class_loader_private::createInstance(derived_class_name, this); + assert(obj != NULL); // Unreachable assertion if createInstance() throws on failure if (managed) { diff --git a/include/class_loader/class_loader_core.h b/include/class_loader/class_loader_core.h index 5bf5096e..34a9c484 100644 --- a/include/class_loader/class_loader_core.h +++ b/include/class_loader/class_loader_core.h @@ -50,12 +50,12 @@ namespace class_loader { -class ClassLoader; //Forward declaration +class ClassLoader; // Forward declaration namespace class_loader_private { -//Typedefs +// Typedefs /*****************************************************************************/ typedef std::string LibraryPath; typedef std::string ClassName; @@ -66,11 +66,11 @@ typedef std::pair LibraryPair; typedef std::vector LibraryVector; typedef std::vector MetaObjectVector; -//Debug +// Debug /*****************************************************************************/ void printDebugInfoToScreen(); -//Global storage +// Global storage /*****************************************************************************/ /** @@ -146,7 +146,7 @@ bool hasANonPurePluginLibraryBeenOpened(); */ void hasANonPurePluginLibraryBeenOpened(bool hasIt); -//Plugin Functions +// Plugin Functions /*****************************************************************************/ /** @@ -159,32 +159,64 @@ void hasANonPurePluginLibraryBeenOpened(bool hasIt); template void registerPlugin(const std::string& class_name, const std::string& base_class_name) { - //Note: This function will be automatically invoked when a dlopen() call - //opens a library. Normally it will happen within the scope of loadLibrary(), - //but that may not be guaranteed. - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Registering plugin factory for class = %s, ClassLoader* = %p and library name %s.", class_name.c_str(), getCurrentlyActiveClassLoader(), getCurrentlyLoadingLibraryName().c_str()); + // Note: This function will be automatically invoked when a dlopen() call + // opens a library. Normally it will happen within the scope of loadLibrary(), + // but that may not be guaranteed. + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Registering plugin factory for class = %s, ClassLoader* = %p and library name %s.", + class_name.c_str(), getCurrentlyActiveClassLoader(), + getCurrentlyLoadingLibraryName().c_str()); if(getCurrentlyActiveClassLoader() == NULL) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: ALERT!!! A library containing plugins has been opened through a means other than through the class_loader or pluginlib package. This can happen if you build plugin libraries that contain more than just plugins (i.e. normal code your app links against). This inherently will trigger a dlopen() prior to main() and cause problems as class_loader is not aware of plugin factories that autoregister under the hood. The class_loader package can compensate, but you may run into namespace collision problems (e.g. if you have the same plugin class in two different libraries and you load them both at the same time). The biggest problem is that library can now no longer be safely unloaded as the ClassLoader does not know when non-plugin code is still in use. In fact, no ClassLoader instance in your application will be unable to unload any library once a non-pure one has been opened. Please refactor your code to isolate plugins into their own libraries."); + CONSOLE_BRIDGE_logDebug( + "class_loader.impl: ALERT!!! " + "A library containing plugins has been opened through a means other than through the " + "class_loader or pluginlib package. " + "This can happen if you build plugin libraries that contain more than just plugins " + "(i.e. normal code your app links against). " + "This inherently will trigger a dlopen() prior to main() and cause problems as class_loader " + "is not aware of plugin factories that autoregister under the hood. " + "The class_loader package can compensate, but you may run into namespace collision problems " + "(e.g. if you have the same plugin class in two different libraries and you load them both " + "at the same time). " + "The biggest problem is that library can now no longer be safely unloaded as the " + "ClassLoader does not know when non-plugin code is still in use. " + "In fact, no ClassLoader instance in your application will be unable to unload any library " + "once a non-pure one has been opened. " + "Please refactor your code to isolate plugins into their own libraries."); hasANonPurePluginLibraryBeenOpened(true); } - //Create factory - class_loader_private::AbstractMetaObject* new_factory = new class_loader_private::MetaObject(class_name, base_class_name); + // Create factory + class_loader_private::AbstractMetaObject* new_factory = + new class_loader_private::MetaObject(class_name, base_class_name); new_factory->addOwningClassLoader(getCurrentlyActiveClassLoader()); new_factory->setAssociatedLibraryPath(getCurrentlyLoadingLibraryName()); - //Add it to global factory map map + // Add it to global factory map map getPluginBaseToFactoryMapMapMutex().lock(); FactoryMap& factoryMap = getFactoryMapForBaseClass(); - if(factoryMap.find(class_name) != factoryMap.end()) - CONSOLE_BRIDGE_logWarn("class_loader.class_loader_private: SEVERE WARNING!!! A namespace collision has occured with plugin factory for class %s. New factory will OVERWRITE existing one. This situation occurs when libraries containing plugins are directly linked against an executable (the one running right now generating this message). Please separate plugins out into their own library or just don't link against the library and use either class_loader::ClassLoader/MultiLibraryClassLoader to open.", class_name.c_str()); + if(factoryMap.find(class_name) != factoryMap.end()) { + CONSOLE_BRIDGE_logWarn( + "class_loader.impl: SEVERE WARNING!!! " + "A namespace collision has occured with plugin factory for class %s. " + "New factory will OVERWRITE existing one. " + "This situation occurs when libraries containing plugins are directly linked against an " + "executable (the one running right now generating this message). " + "Please separate plugins out into their own library or just don't link against the library " + "and use either class_loader::ClassLoader/MultiLibraryClassLoader to open.", + class_name.c_str()); + } factoryMap[class_name] = new_factory; getPluginBaseToFactoryMapMapMutex().unlock(); - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Registration of %s complete (Metaobject Address = %p)", class_name.c_str(), new_factory); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Registration of %s complete (Metaobject Address = %p)", + class_name.c_str(), new_factory); } /** @@ -200,11 +232,13 @@ Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) getPluginBaseToFactoryMapMapMutex().lock(); FactoryMap& factoryMap = getFactoryMapForBaseClass(); - if(factoryMap.find(derived_class_name) != factoryMap.end()) - factory = dynamic_cast*>(factoryMap[derived_class_name]); - else - { - CONSOLE_BRIDGE_logError("class_loader.class_loader_private: No metaobject exists for class type %s.", derived_class_name.c_str()); + if(factoryMap.find(derived_class_name) != factoryMap.end()) { + factory = dynamic_cast*>( + factoryMap[derived_class_name]); + } else { + CONSOLE_BRIDGE_logError( + "class_loader.class_loader_private: No metaobject exists for class type %s.", + derived_class_name.c_str()); } getPluginBaseToFactoryMapMapMutex().unlock(); @@ -212,19 +246,32 @@ Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) if(factory != NULL && factory->isOwnedBy(loader)) obj = factory->create(); - if(obj == NULL) //Was never created + if(obj == NULL) // Was never created { if(factory && factory->isOwnedBy(NULL)) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: ALERT!!! A metaobject (i.e. factory) exists for desired class, but has no owner. This implies that the library containing the class was dlopen()ed by means other than through the class_loader interface. This can happen if you build plugin libraries that contain more than just plugins (i.e. normal code your app links against) -- that intrinsically will trigger a dlopen() prior to main(). You should isolate your plugins into their own library, otherwise it will not be possible to shutdown the library!"); + CONSOLE_BRIDGE_logDebug( + "class_loader.impl: ALERT!!! " + "A metaobject (i.e. factory) exists for desired class, but has no owner. " + "This implies that the library containing the class was dlopen()ed by means other than " + "through the class_loader interface. " + "This can happen if you build plugin libraries that contain more than just plugins " + "(i.e. normal code your app links against) -- that intrinsically will trigger a dlopen() " + "prior to main(). " + "You should isolate your plugins into their own library, otherwise it will not be " + "possible to shutdown the library!"); obj = factory->create(); } else { - throw(class_loader::CreateClassException("Could not create instance of type " + derived_class_name)); + throw(class_loader::CreateClassException( + "Could not create instance of type " + derived_class_name)); } } - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Created instance of type %s and object pointer = %p", (typeid(obj).name()), obj); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Created instance of type %s and object pointer = %p", + (typeid(obj).name()), obj); return(obj); } @@ -252,8 +299,8 @@ std::vector getAvailableClasses(ClassLoader* loader) classes_with_no_owner.push_back(itr->first); } - //Added classes not associated with a class loader (Which can happen through - //an unexpected dlopen() to the library) + // Added classes not associated with a class loader (Which can happen through + // an unexpected dlopen() to the library) classes.insert(classes.end(), classes_with_no_owner.begin(), classes_with_no_owner.end()); return(classes); } @@ -295,7 +342,7 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader); void unloadLibrary(const std::string& library_path, ClassLoader* loader); -} //End namespace class_loader_private -} //End namespace class_loader +} // namespace class_loader_private +} // namespace class_loader #endif // CLASS_LOADER__CLASS_LOADER_CORE_H_ diff --git a/include/class_loader/class_loader_register_macro.h b/include/class_loader/class_loader_register_macro.h index 484500d9..79cc7e69 100644 --- a/include/class_loader/class_loader_register_macro.h +++ b/include/class_loader/class_loader_register_macro.h @@ -54,19 +54,22 @@ namespace \ static ProxyExec##UniqueID g_register_plugin_##UniqueID;\ } // namespace -#define CLASS_LOADER_REGISTER_CLASS_INTERNAL_HOP1_WITH_MESSAGE(Derived, Base, UniqueID, Message) CLASS_LOADER_REGISTER_CLASS_INTERNAL_WITH_MESSAGE(Derived, Base, UniqueID, Message) +#define CLASS_LOADER_REGISTER_CLASS_INTERNAL_HOP1_WITH_MESSAGE(Derived, Base, UniqueID, Message) \ + CLASS_LOADER_REGISTER_CLASS_INTERNAL_WITH_MESSAGE(Derived, Base, UniqueID, Message) /** * @macro This macro is same as CLASS_LOADER_REGISTER_CLASS, but will spit out a message when the plugin is registered * at library load time */ -#define CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(Derived, Base, Message) CLASS_LOADER_REGISTER_CLASS_INTERNAL_HOP1_WITH_MESSAGE(Derived, Base, __COUNTER__, Message) +#define CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(Derived, Base, Message) \ + CLASS_LOADER_REGISTER_CLASS_INTERNAL_HOP1_WITH_MESSAGE(Derived, Base, __COUNTER__, Message) /** * @macro This is the macro which must be declared within the source (.cpp) file for each class that is to be exported as plugin. * The macro utilizes a trick where a new struct is generated along with a declaration of static global variable of same type after it. The struct's constructor invokes a registration function with the plugin system. When the plugin system loads a library with registered classes in it, the initialization of static variables forces the invocation of the struct constructors, and all exported classes are automatically registerd. */ -#define CLASS_LOADER_REGISTER_CLASS(Derived, Base) CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(Derived, Base, "") +#define CLASS_LOADER_REGISTER_CLASS(Derived, Base) \ + CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(Derived, Base, "") #endif // CLASS_LOADER__CLASS_LOADER_REGISTER_MACRO_H_ diff --git a/include/class_loader/meta_object.h b/include/class_loader/meta_object.h index 45d794f4..13fcc4c6 100644 --- a/include/class_loader/meta_object.h +++ b/include/class_loader/meta_object.h @@ -27,7 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ -//Note: This header defines a simplication of Poco::MetaObject that allows us to tag MetaObjects with an associated library name. +// Note: This header defines a simplication of Poco::MetaObject +// that allows us to tag MetaObjects with an associated library name. #ifndef CLASS_LOADER__META_OBJECT_H_ #define CLASS_LOADER__META_OBJECT_H_ @@ -42,7 +43,7 @@ namespace class_loader { -class ClassLoader; //Forward declaration +class ClassLoader; // Forward declaration namespace class_loader_private { @@ -196,7 +197,7 @@ class MetaObject: public AbstractMetaObject } }; -} // End namespace class_loader_private -} // End namespace class_loader +} // namespace class_loader_private +} // namespace class_loader #endif // CLASS_LOADER__META_OBJECT_H_ diff --git a/include/class_loader/multi_library_class_loader.h b/include/class_loader/multi_library_class_loader.h index 1d4a6d24..6f6d79e3 100644 --- a/include/class_loader/multi_library_class_loader.h +++ b/include/class_loader/multi_library_class_loader.h @@ -72,10 +72,19 @@ class MultiLibraryClassLoader template boost::shared_ptr createInstance(const std::string& class_name) { - CONSOLE_BRIDGE_logDebug("class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.", class_name.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader::MultiLibraryClassLoader: " + "Attempting to create instance of class type %s.", + class_name.c_str()); ClassLoader* loader = getClassLoaderForClass(class_name); - if (loader == NULL) - throw class_loader::CreateClassException("MultiLibraryClassLoader: Could not create object of class type " + class_name + " as no factory exists for it. Make sure that the library exists and was explicitly loaded through MultiLibraryClassLoader::loadLibrary()"); + if (loader == NULL) { + throw class_loader::CreateClassException( + "MultiLibraryClassLoader: Could not create object of class type " + + class_name + + " as no factory exists for it. Make sure that the library exists and " + "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()"); + } + return loader->createInstance(class_name); } @@ -88,11 +97,16 @@ class MultiLibraryClassLoader * @return A boost::shared_ptr to newly created plugin */ template - boost::shared_ptr createInstance(const std::string& class_name, const std::string& library_path) + boost::shared_ptr + createInstance(const std::string& class_name, const std::string& library_path) { ClassLoader* loader = getClassLoaderForLibrary(library_path); - if (loader == NULL) - throw class_loader::NoClassLoaderExistsException("Could not create instance as there is no ClassLoader in MultiLibraryClassLoader bound to library " + library_path + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + if (loader == NULL) { + throw class_loader::NoClassLoaderExistsException( + "Could not create instance as there is no ClassLoader in " + "MultiLibraryClassLoader bound to library " + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + } return loader->createInstance(class_name); } @@ -107,10 +121,17 @@ class MultiLibraryClassLoader template ClassLoader::UniquePtr createUniqueInstance(const std::string& class_name) { - CONSOLE_BRIDGE_logDebug("class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.", class_name.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.", + class_name.c_str()); ClassLoader* loader = getClassLoaderForClass(class_name); - if (loader == nullptr) - throw class_loader::CreateClassException("MultiLibraryClassLoader: Could not create object of class type " + class_name + " as no factory exists for it. Make sure that the library exists and was explicitly loaded through MultiLibraryClassLoader::loadLibrary()"); + if (loader == nullptr) { + throw class_loader::CreateClassException( + "MultiLibraryClassLoader: Could not create object of class type " + class_name + + " as no factory exists for it. " + "Make sure that the library exists and was explicitly loaded through " + "MultiLibraryClassLoader::loadLibrary()"); + } return loader->createUniqueInstance(class_name); } @@ -123,11 +144,16 @@ class MultiLibraryClassLoader * @return A unique pointer to newly created plugin */ template - ClassLoader::UniquePtr createUniqueInstance(const std::string& class_name, const std::string& library_path) + ClassLoader::UniquePtr + createUniqueInstance(const std::string& class_name, const std::string& library_path) { ClassLoader* loader = getClassLoaderForLibrary(library_path); - if (loader == nullptr) - throw class_loader::NoClassLoaderExistsException("Could not create instance as there is no ClassLoader in MultiLibraryClassLoader bound to library " + library_path + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + if (loader == nullptr) { + throw class_loader::NoClassLoaderExistsException( + "Could not create instance as there is no ClassLoader in " + "MultiLibraryClassLoader bound to library " + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + } return loader->createUniqueInstance(class_name); } #endif @@ -145,7 +171,8 @@ class MultiLibraryClassLoader { ClassLoader* loader = getClassLoaderForClass(class_name); if (loader == NULL) - throw class_loader::CreateClassException("MultiLibraryClassLoader: Could not create class of type " + class_name); + throw class_loader::CreateClassException( + "MultiLibraryClassLoader: Could not create class of type " + class_name); return loader->createUnmanagedInstance(class_name); } @@ -161,8 +188,12 @@ class MultiLibraryClassLoader Base* createUnmanagedInstance(const std::string& class_name, const std::string& library_path) { ClassLoader* loader = getClassLoaderForLibrary(library_path); - if (loader == NULL) - throw class_loader::NoClassLoaderExistsException("Could not create instance as there is no ClassLoader in MultiLibraryClassLoader bound to library " + library_path + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + if (loader == NULL) { + throw class_loader::NoClassLoaderExistsException( + "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader " + "bound to library " + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + } return loader->createUnmanagedInstance(class_name); } @@ -176,7 +207,8 @@ class MultiLibraryClassLoader bool isClassAvailable(const std::string& class_name) { std::vector available_classes = getAvailableClasses(); - return(available_classes.end() != std::find(available_classes.begin(), available_classes.end(), class_name)); + return(available_classes.end() != std::find( + available_classes.begin(), available_classes.end(), class_name)); } /** @@ -200,7 +232,8 @@ class MultiLibraryClassLoader { ClassLoader* current = loaders.at(c); std::vector loader_classes = current->getAvailableClasses(); - available_classes.insert(available_classes.end(), loader_classes.begin(), loader_classes.end()); + available_classes.insert( + available_classes.end(), loader_classes.begin(), loader_classes.end()); } return(available_classes); } @@ -220,7 +253,9 @@ class MultiLibraryClassLoader available_classes = loader->getAvailableClasses(); return(available_classes); } else { - throw class_loader::NoClassLoaderExistsException("There is no ClassLoader in MultiLibraryClassLoader bound to library " + library_path + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); + throw class_loader::NoClassLoaderExistsException( + "There is no ClassLoader in MultiLibraryClassLoader bound to library " + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); } } diff --git a/src/class_loader.cpp b/src/class_loader.cpp index 3ab6d4fb..0ca6f373 100644 --- a/src/class_loader.cpp +++ b/src/class_loader.cpp @@ -52,15 +52,20 @@ library_path_(library_path), load_ref_count_(0), plugin_ref_count_(0) { - CONSOLE_BRIDGE_logDebug("class_loader.ClassLoader: Constructing new ClassLoader (%p) bound to library %s.", this, library_path.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.ClassLoader: " + "Constructing new ClassLoader (%p) bound to library %s.", + this, library_path.c_str()); if(!isOnDemandLoadUnloadEnabled()) loadLibrary(); } ClassLoader::~ClassLoader() { - CONSOLE_BRIDGE_logDebug("class_loader.ClassLoader: Destroying class loader, unloading associated library...\n"); - unloadLibrary(); //TODO: while(unloadLibrary() > 0){} ?? + CONSOLE_BRIDGE_logDebug( + "class_loader.ClassLoader: " + "Destroying class loader, unloading associated library...\n"); + unloadLibrary(); // TODO(mikaelarguedas): while(unloadLibrary() > 0){} ?? } bool ClassLoader::isLibraryLoaded() @@ -93,7 +98,12 @@ int ClassLoader::unloadLibraryInternal(bool lock_plugin_ref_count) plugin_ref_lock = boost::recursive_mutex::scoped_lock(plugin_ref_count_mutex_); if(plugin_ref_count_ > 0) - CONSOLE_BRIDGE_logWarn("class_loader.ClassLoader: SEVERE WARNING!!! Attempting to unload library while objects created by this loader exist in the heap! You should delete your objects before attempting to unload the library or destroying the ClassLoader. The library will NOT be unloaded."); + CONSOLE_BRIDGE_logWarn( + "class_loader.ClassLoader: " + "SEVERE WARNING!!! Attempting to unload library while objects created by this loader " + "exist in the heap! " + "You should delete your objects before attempting to unload the library or " + "destroying the ClassLoader. The library will NOT be unloaded."); else { load_ref_count_ = load_ref_count_ - 1; diff --git a/src/class_loader_core.cpp b/src/class_loader_core.cpp index d7fee055..2b58cd28 100644 --- a/src/class_loader_core.cpp +++ b/src/class_loader_core.cpp @@ -39,7 +39,7 @@ namespace class_loader_private { -//Global data +// Global data /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ @@ -150,7 +150,7 @@ void hasANonPurePluginLibraryBeenOpened(bool hasIt) } -//MetaObject search/insert/removal/query +// MetaObject search/insert/removal/query /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ @@ -159,8 +159,12 @@ MetaObjectVector allMetaObjects(const FactoryMap& factories) /*****************************************************************************/ { MetaObjectVector all_meta_objs; - for(FactoryMap::const_iterator factoryItr = factories.begin(); factoryItr != factories.end(); factoryItr++) + for( + FactoryMap::const_iterator factoryItr = factories.begin(); + factoryItr != factories.end(); factoryItr++ + ) { all_meta_objs.push_back(factoryItr->second); + } return(all_meta_objs); } @@ -181,7 +185,8 @@ MetaObjectVector allMetaObjects() return(all_meta_objs); } -MetaObjectVector filterAllMetaObjectsOwnedBy(const MetaObjectVector& to_filter, const ClassLoader* owner) +MetaObjectVector +filterAllMetaObjectsOwnedBy(const MetaObjectVector& to_filter, const ClassLoader* owner) /*****************************************************************************/ { MetaObjectVector filtered_objs; @@ -191,7 +196,9 @@ MetaObjectVector filterAllMetaObjectsOwnedBy(const MetaObjectVector& to_filter, return(filtered_objs); } -MetaObjectVector filterAllMetaObjectsAssociatedWithLibrary(const MetaObjectVector& to_filter, const std::string& library_path) +MetaObjectVector +filterAllMetaObjectsAssociatedWithLibrary( + const MetaObjectVector& to_filter, const std::string& library_path) /*****************************************************************************/ { MetaObjectVector filtered_objs; @@ -201,19 +208,22 @@ MetaObjectVector filterAllMetaObjectsAssociatedWithLibrary(const MetaObjectVecto return(filtered_objs); } -MetaObjectVector allMetaObjectsForClassLoader(const ClassLoader* owner) +MetaObjectVector +allMetaObjectsForClassLoader(const ClassLoader* owner) /*****************************************************************************/ { return(filterAllMetaObjectsOwnedBy(allMetaObjects(), owner)); } -MetaObjectVector allMetaObjectsForLibrary(const std::string& library_path) +MetaObjectVector +allMetaObjectsForLibrary(const std::string& library_path) /*****************************************************************************/ { return(filterAllMetaObjectsAssociatedWithLibrary(allMetaObjects(), library_path)); } -MetaObjectVector allMetaObjectsForLibraryOwnedBy(const std::string& library_path, const ClassLoader* owner) +MetaObjectVector +allMetaObjectsForLibraryOwnedBy(const std::string& library_path, const ClassLoader* owner) /*****************************************************************************/ { return(filterAllMetaObjectsOwnedBy(allMetaObjectsForLibrary(library_path), owner)); @@ -222,11 +232,15 @@ MetaObjectVector allMetaObjectsForLibraryOwnedBy(const std::string& library_path void insertMetaObjectIntoGraveyard(AbstractMetaObjectBase* meta_obj) /*****************************************************************************/ { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Inserting MetaObject (class = %s, base_class = %s, ptr = %p) into graveyard", meta_obj->className().c_str(), meta_obj->baseClassName().c_str(), meta_obj); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Inserting MetaObject (class = %s, base_class = %s, ptr = %p) into graveyard", + meta_obj->className().c_str(), meta_obj->baseClassName().c_str(), meta_obj); getMetaObjectGraveyard().push_back(meta_obj); } -void destroyMetaObjectsForLibrary(const std::string& library_path, FactoryMap& factories, const ClassLoader* loader) +void destroyMetaObjectsForLibrary( + const std::string& library_path, FactoryMap& factories, const ClassLoader* loader) /*****************************************************************************/ { FactoryMap::iterator factory_itr = factories.begin(); @@ -240,15 +254,19 @@ void destroyMetaObjectsForLibrary(const std::string& library_path, FactoryMap& f { FactoryMap::iterator factory_itr_copy = factory_itr; factory_itr++; - factories.erase(factory_itr_copy); //Note: map::erase does not return iterator like vector::erase does. Hence the ugliness of this code and a need for copy. Should be fixed in next C++ revision - - //Insert into graveyard - //We remove the metaobject from its factory map, but we don't destroy it...instead it saved to - //a "graveyard" to the side. This is due to our static global variable initialization problem - //that causes factories to not be registered when a library is closed and then reopened. This is - //because it's truly not closed due to the use of global symbol binding i.e. calling dlopen - //with RTLD_GLOBAL instead of RTLD_LOCAL. We require using the former as the which is required to support - //RTTI + // TODO(mikaelarguedas) fix this when branching out for melodic + // Note: map::erase does not return iterator like vector::erase does. + // Hence the ugliness of this code and a need for copy. Should be fixed in next C++ revision + factories.erase(factory_itr_copy); + + // Insert into graveyard + // We remove the metaobject from its factory map, but we don't destroy it...instead it + // saved to a "graveyard" to the side. + // This is due to our static global variable initialization problem that causes factories + // to not be registered when a library is closed and then reopened. + // This is because it's truly not closed due to the use of global symbol binding i.e. + // calling dlopen with RTLD_GLOBAL instead of RTLD_LOCAL. + // We require using the former as the which is required to support RTTI insertMetaObjectIntoGraveyard(meta_obj); } else { factory_itr++; @@ -264,9 +282,13 @@ void destroyMetaObjectsForLibrary(const std::string& library_path, const ClassLo { boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex()); - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Removing MetaObjects associated with library %s and class loader %p from global plugin-to-factorymap map.\n", library_path.c_str(), loader); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Removing MetaObjects associated with library %s and class loader %p from global " + "plugin-to-factorymap map.\n", + library_path.c_str(), loader); - //We have to walk through all FactoryMaps to be sure + // We have to walk through all FactoryMaps to be sure BaseToFactoryMapMap& factory_map_map = getGlobalPluginBaseToFactoryMapMap(); BaseToFactoryMapMap::iterator itr; for(itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) @@ -281,7 +303,7 @@ bool areThereAnyExistingMetaObjectsForLibrary(const std::string& library_path) return(allMetaObjectsForLibrary(library_path).size() > 0); } -//Loaded Library Vector manipulation +// Loaded Library Vector manipulation /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ @@ -308,7 +330,7 @@ bool isLibraryLoadedByAnybody(const std::string& library_path) if(itr != open_libraries.end()) { - assert(itr->second->isLoaded() == true); //Ensure Poco actually thinks the library is loaded + assert(itr->second->isLoaded() == true); // Ensure Poco actually thinks the library is loaded return(true); } else { return(false); @@ -320,8 +342,11 @@ bool isLibraryLoaded(const std::string& library_path, ClassLoader* loader) { bool is_lib_loaded_by_anyone = isLibraryLoadedByAnybody(library_path); int num_meta_objs_for_lib = allMetaObjectsForLibrary(library_path).size(); - int num_meta_objs_for_lib_bound_to_loader = allMetaObjectsForLibraryOwnedBy(library_path, loader).size(); - bool are_meta_objs_bound_to_loader = (num_meta_objs_for_lib == 0) ? true : (num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib); + int num_meta_objs_for_lib_bound_to_loader = + allMetaObjectsForLibraryOwnedBy(library_path, loader).size(); + bool are_meta_objs_bound_to_loader = + (num_meta_objs_for_lib == 0) ? true : ( + num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib); return(is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader); } @@ -341,24 +366,31 @@ std::vector getAllLibrariesUsedByClassLoader(const ClassLoader* loa } -//Implementation of Remaining Core plugin_private Functions +// Implementation of Remaining Core plugin_private Functions /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ -void addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(const std::string& library_path, ClassLoader* loader) +void addClassLoaderOwnerForAllExistingMetaObjectsForLibrary( + const std::string& library_path, ClassLoader* loader) /*****************************************************************************/ { MetaObjectVector all_meta_objs = allMetaObjectsForLibrary(library_path); for(unsigned int c = 0; c < all_meta_objs.size(); c++) { AbstractMetaObjectBase* meta_obj = all_meta_objs.at(c); - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Tagging existing MetaObject %p (base = %s, derived = %s) with class loader %p (library path = %s).", meta_obj, meta_obj->baseClassName().c_str(), meta_obj->className().c_str(), loader, loader ? loader->getLibraryPath().c_str() : "NULL"); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Tagging existing MetaObject %p (base = %s, derived = %s) with " + "class loader %p (library path = %s).", + meta_obj, meta_obj->baseClassName().c_str(), meta_obj->className().c_str(), + loader, loader ? loader->getLibraryPath().c_str() : "NULL"); all_meta_objs.at(c)->addOwningClassLoader(loader); } } -void revivePreviouslyCreateMetaobjectsFromGraveyard(const std::string& library_path, ClassLoader* loader) +void revivePreviouslyCreateMetaobjectsFromGraveyard( + const std::string& library_path, ClassLoader* loader) /*****************************************************************************/ { boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex()); @@ -369,7 +401,12 @@ void revivePreviouslyCreateMetaobjectsFromGraveyard(const std::string& library_p AbstractMetaObjectBase* obj = *itr; if(obj->getAssociatedLibraryPath() == library_path) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Resurrected factory metaobject from graveyard, class = %s, base_class = %s ptr = %p...bound to ClassLoader %p (library path = %s)", obj->className().c_str(), obj->baseClassName().c_str(), obj, loader, loader ? loader->getLibraryPath().c_str() : "NULL"); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Resurrected factory metaobject from graveyard, class = %s, base_class = %s ptr = %p..." + "bound to ClassLoader %p (library path = %s)", + obj->className().c_str(), obj->baseClassName().c_str(), obj, + loader, loader ? loader->getLibraryPath().c_str() : "NULL"); obj->addOwningClassLoader(loader); assert(obj->typeidBaseClassName() != "UNSET"); @@ -379,11 +416,13 @@ void revivePreviouslyCreateMetaobjectsFromGraveyard(const std::string& library_p } } -void purgeGraveyardOfMetaobjects(const std::string& library_path, ClassLoader* loader, bool delete_objs) +void purgeGraveyardOfMetaobjects( + const std::string& library_path, ClassLoader* loader, bool delete_objs) /*****************************************************************************/ { MetaObjectVector all_meta_objs = allMetaObjects(); - boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex()); //Note: Lock must happen after call to allMetaObjects as that will lock + // Note: Lock must happen after call to allMetaObjects as that will lock + boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex()); MetaObjectVector& graveyard = getMetaObjectGraveyard(); MetaObjectVector::iterator itr = graveyard.begin(); @@ -393,18 +432,32 @@ void purgeGraveyardOfMetaobjects(const std::string& library_path, ClassLoader* l AbstractMetaObjectBase* obj = *itr; if(obj->getAssociatedLibraryPath() == library_path) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Purging factory metaobject from graveyard, class = %s, base_class = %s ptr = %p...bound to ClassLoader %p (library path = %s)", obj->className().c_str(), obj->baseClassName().c_str(), obj, loader, loader ? loader->getLibraryPath().c_str() : "NULL"); - - bool is_address_in_graveyard_same_as_global_factory_map = std::find(all_meta_objs.begin(), all_meta_objs.end(), *itr) != all_meta_objs.end(); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Purging factory metaobject from graveyard, class = %s, base_class = %s ptr = %p.." + ".bound to ClassLoader %p (library path = %s)", + obj->className().c_str(), obj->baseClassName().c_str(), obj, + loader, loader ? loader->getLibraryPath().c_str() : "NULL"); + + bool is_address_in_graveyard_same_as_global_factory_map = + std::find(all_meta_objs.begin(), all_meta_objs.end(), *itr) != all_meta_objs.end(); itr = graveyard.erase(itr); if(delete_objs) { if(is_address_in_graveyard_same_as_global_factory_map) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Newly created metaobject factory in global factory map map has same address as one in graveyard -- metaobject has been purged from graveyard but not deleted."); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Newly created metaobject factory in global factory map map has same address as " + "one in graveyard -- metaobject has been purged from graveyard but not deleted."); } else { assert(hasANonPurePluginLibraryBeenOpened() == false); - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Also destroying metaobject %p (class = %s, base_class = %s, library_path = %s) in addition to purging it from graveyard.", obj, obj->className().c_str(), obj->baseClassName().c_str(), obj->getAssociatedLibraryPath().c_str()); - delete(obj); //Note: This is the only place where metaobjects can be destroyed + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Also destroying metaobject %p (class = %s, base_class = %s, library_path = %s) " + "in addition to purging it from graveyard.", + obj, obj->className().c_str(), obj->baseClassName().c_str(), + obj->getAssociatedLibraryPath().c_str()); + delete(obj); // Note: This is the only place where metaobjects can be destroyed } } } else { @@ -417,14 +470,19 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) /*****************************************************************************/ { static boost::recursive_mutex loader_mutex; - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Attempting to load library %s on behalf of ClassLoader handle %p...\n", library_path.c_str(), loader); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Attempting to load library %s on behalf of ClassLoader handle %p...\n", + library_path.c_str(), loader); boost::recursive_mutex::scoped_lock loader_lock(loader_mutex); - //If it's already open, just update existing metaobjects to have an additional owner. + // If it's already open, just update existing metaobjects to have an additional owner. if(isLibraryLoadedByAnybody(library_path)) { boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex()); - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Library already in memory, but binding existing MetaObjects to loader if necesesary.\n"); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Library already in memory, but binding existing MetaObjects to loader if necesesary.\n"); addClassLoaderOwnerForAllExistingMetaObjectsForLibrary(library_path, loader); return; } @@ -442,19 +500,22 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) { setCurrentlyLoadingLibraryName(""); setCurrentlyActiveClassLoader(NULL); - throw(class_loader::LibraryLoadException("Could not load library (Poco exception = " + std::string(e.message()) + ")")); + throw(class_loader::LibraryLoadException( + "Could not load library (Poco exception = " + std::string(e.message()) + ")")); } catch(const Poco::LibraryAlreadyLoadedException& e) { setCurrentlyLoadingLibraryName(""); setCurrentlyActiveClassLoader(NULL); - throw(class_loader::LibraryLoadException("Library already loaded (Poco exception = " + std::string(e.message()) + ")")); + throw(class_loader::LibraryLoadException( + "Library already loaded (Poco exception = " + std::string(e.message()) + ")")); } catch(const Poco::NotFoundException& e) { setCurrentlyLoadingLibraryName(""); setCurrentlyActiveClassLoader(NULL); - throw(class_loader::LibraryLoadException("Library not found (Poco exception = " + std::string(e.message()) + ")")); + throw(class_loader::LibraryLoadException( + "Library not found (Poco exception = " + std::string(e.message()) + ")")); } setCurrentlyLoadingLibraryName(""); @@ -462,24 +523,37 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) } assert(library_handle != NULL); - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Successfully loaded library %s into memory (Poco::SharedLibrary handle = %p).", library_path.c_str(), library_handle); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Successfully loaded library %s into memory (Poco::SharedLibrary handle = %p).", + library_path.c_str(), library_handle); - //Graveyard scenario + // Graveyard scenario unsigned int num_lib_objs = allMetaObjectsForLibrary(library_path).size(); if(num_lib_objs == 0) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Though the library %s was just loaded, it seems no factory metaobjects were registered. Checking factory graveyard for previously loaded metaobjects...", library_path.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Though the library %s was just loaded, it seems no factory metaobjects were registered. " + "Checking factory graveyard for previously loaded metaobjects...", + library_path.c_str()); revivePreviouslyCreateMetaobjectsFromGraveyard(library_path, loader); - purgeGraveyardOfMetaobjects(library_path, loader, false); //Note: The 'false' indicates we don't want to invoke delete on the metaobject + // Note: The 'false' indicates we don't want to invoke delete on the metaobject + purgeGraveyardOfMetaobjects(library_path, loader, false); } else { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Library %s generated new factory metaobjects on load. Destroying graveyarded objects from previous loads...", library_path.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Library %s generated new factory metaobjects on load. " + "Destroying graveyarded objects from previous loads...", + library_path.c_str()); purgeGraveyardOfMetaobjects(library_path, loader, true); } - //Insert library into global loaded library vectory + // Insert library into global loaded library vectory boost::recursive_mutex::scoped_lock llv_lock(getLoadedLibraryVectorMutex()); LibraryVector& open_libraries = getLoadedLibraryVector(); - open_libraries.push_back(LibraryPair(library_path, library_handle)); //Note: Poco::SharedLibrary automatically calls load() when library passed to constructor + // Note: Poco::SharedLibrary automatically calls load() when library passed to constructor + open_libraries.push_back(LibraryPair(library_path, library_handle)); } void unloadLibrary(const std::string& library_path, ClassLoader* loader) @@ -487,9 +561,20 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader) { if(hasANonPurePluginLibraryBeenOpened()) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Cannot unload %s or ANY other library as a non-pure plugin library was opened. As class_loader has no idea which libraries class factories were exported from, it can safely close any library without potentially unlinking symbols that are still actively being used. You must refactor your plugin libraries to be made exclusively of plugins in order for this error to stop happening.", library_path.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Cannot unload %s or ANY other library as a non-pure plugin library was opened. " + "As class_loader has no idea which libraries class factories were exported from, " + "it can safely close any library without potentially unlinking symbols that are still " + "actively being used. " + "You must refactor your plugin libraries to be made exclusively of plugins " + "in order for this error to stop happening.", + library_path.c_str()); } else { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Unloading library %s on behalf of ClassLoader %p...", library_path.c_str(), loader); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "Unloading library %s on behalf of ClassLoader %p...", + library_path.c_str(), loader); boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex()); LibraryVector& open_libraries = getLoadedLibraryVector(); LibraryVector::iterator itr = findLoadedLibrary(library_path); @@ -501,31 +586,41 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader) { destroyMetaObjectsForLibrary(library_path, loader); - //Remove from loaded library list as well if no more factories associated with said library + // Remove from loaded library list as well if no more factories associated with said library if(!areThereAnyExistingMetaObjectsForLibrary(library_path)) { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: There are no more MetaObjects left for %s so unloading library and removing from loaded library vector.\n", library_path.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "There are no more MetaObjects left for %s so unloading library and " + "removing from loaded library vector.\n", + library_path.c_str()); library->unload(); assert(library->isLoaded() == false); delete(library); itr = open_libraries.erase(itr); } else { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: MetaObjects still remain in memory meaning other ClassLoaders are still using library, keeping library %s open.", library_path.c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private: " + "MetaObjects still remain in memory meaning other ClassLoaders are still using library" + ", keeping library %s open.", + library_path.c_str()); } return; } catch(const Poco::RuntimeException& e) { delete(library); - throw(class_loader::LibraryUnloadException("Could not unload library (Poco exception = " + std::string(e.message()) + ")")); + throw(class_loader::LibraryUnloadException( + "Could not unload library (Poco exception = " + std::string(e.message()) + ")")); } } - throw(class_loader::LibraryUnloadException("Attempt to unload library that class_loader is unaware of.")); + throw(class_loader::LibraryUnloadException( + "Attempt to unload library that class_loader is unaware of.")); } } -//Other +// Other /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ @@ -542,7 +637,9 @@ void printDebugInfoToScreen() boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex()); LibraryVector libs = getLoadedLibraryVector(); for(unsigned int c = 0; c < libs.size(); c++) - printf("Open library %i = %s (Poco SharedLibrary handle = %p)\n", c, (libs.at(c)).first.c_str(), (libs.at(c)).second); + printf( + "Open library %i = %s (Poco SharedLibrary handle = %p)\n", + c, (libs.at(c)).first.c_str(), (libs.at(c)).second); printf("METAOBJECTS (i.e. FACTORIES) IN MEMORY:\n"); printf("--------------------------------------------------------------------------------\n"); @@ -569,5 +666,5 @@ void printDebugInfoToScreen() -} //End namespace class_loader_private -} //End namespace class_loader +} // namespace class_loader_private +} // namespace class_loader diff --git a/src/meta_object.cpp b/src/meta_object.cpp index f1836c64..db31480f 100644 --- a/src/meta_object.cpp +++ b/src/meta_object.cpp @@ -37,20 +37,27 @@ namespace class_loader namespace class_loader_private { -AbstractMetaObjectBase::AbstractMetaObjectBase(const std::string& class_name, const std::string& base_class_name) : +AbstractMetaObjectBase::AbstractMetaObjectBase( + const std::string& class_name, const std::string& base_class_name) : associated_library_path_("Unknown"), base_class_name_(base_class_name), class_name_(class_name), typeid_base_class_name_("UNSET") /*****************************************************************************/ { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private.AbstractMetaObjectBase: Creating MetaObject %p (base = %s, derived = %s, library path = %s)", this, baseClassName().c_str(), className().c_str(), getAssociatedLibraryPath().c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private.AbstractMetaObjectBase: " + "Creating MetaObject %p (base = %s, derived = %s, library path = %s)", + this, baseClassName().c_str(), className().c_str(), getAssociatedLibraryPath().c_str()); } AbstractMetaObjectBase::~AbstractMetaObjectBase() /*****************************************************************************/ { - CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private.AbstractMetaObjectBase: Destroying MetaObject %p (base = %s, derived = %s, library path = %s)", this, baseClassName().c_str(), className().c_str(), getAssociatedLibraryPath().c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private.AbstractMetaObjectBase: " + "Destroying MetaObject %p (base = %s, derived = %s, library path = %s)", + this, baseClassName().c_str(), className().c_str(), getAssociatedLibraryPath().c_str()); } std::string AbstractMetaObjectBase::className() const @@ -121,6 +128,4 @@ ClassLoaderVector AbstractMetaObjectBase::getAssociatedClassLoaders() } } // namespace class_loader_private - - } // namespace class_loader diff --git a/src/multi_library_class_loader.cpp b/src/multi_library_class_loader.cpp index b960a3de..54027aac 100644 --- a/src/multi_library_class_loader.cpp +++ b/src/multi_library_class_loader.cpp @@ -48,8 +48,12 @@ MultiLibraryClassLoader::~MultiLibraryClassLoader() std::vector MultiLibraryClassLoader::getRegisteredLibraries() { std::vector libraries; - for(LibraryToClassLoaderMap::iterator itr = active_class_loaders_.begin(); itr != active_class_loaders_.end(); itr++) + for( + LibraryToClassLoaderMap::iterator itr = active_class_loaders_.begin(); + itr != active_class_loaders_.end(); itr++ + ) { libraries.push_back(itr->first); + } return(libraries); } @@ -64,8 +68,12 @@ ClassLoader* MultiLibraryClassLoader::getClassLoaderForLibrary(const std::string ClassLoaderVector MultiLibraryClassLoader::getAllAvailableClassLoaders() { ClassLoaderVector loaders; - for(LibraryToClassLoaderMap::iterator itr = active_class_loaders_.begin(); itr != active_class_loaders_.end(); itr++) + for( + LibraryToClassLoaderMap::iterator itr = active_class_loaders_.begin(); + itr != active_class_loaders_.end(); itr++ + ) { loaders.push_back(itr->second); + } return(loaders); } @@ -77,7 +85,8 @@ bool MultiLibraryClassLoader::isLibraryAvailable(const std::string& library_name void MultiLibraryClassLoader::loadLibrary(const std::string& library_path) { if(!isLibraryAvailable(library_path)) - active_class_loaders_[library_path] = new class_loader::ClassLoader(library_path, isOnDemandLoadUnloadEnabled()); + active_class_loaders_[library_path] = + new class_loader::ClassLoader(library_path, isOnDemandLoadUnloadEnabled()); } void MultiLibraryClassLoader::shutdownAllClassLoaders() diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index fad1ad69..ff878033 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -52,7 +52,7 @@ TEST(ClassLoaderUniquePtrTest, basicLoad) try { ClassLoader loader1(LIBRARY_1, false); - loader1.createUniqueInstance("Cat")->saySomething(); //See if lazy load works + loader1.createUniqueInstance("Cat")->saySomething(); // See if lazy load works SUCCEED(); } catch(class_loader::ClassLoaderException& e) @@ -77,7 +77,7 @@ TEST(ClassLoaderUniquePtrTest, correctLazyLoadUnload) ASSERT_TRUE(loader1.isLibraryLoaded()); } - //The library will unload automatically when the only plugin object left is destroyed + // The library will unload automatically when the only plugin object left is destroyed ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); return; } @@ -139,9 +139,9 @@ TEST(ClassLoaderUniquePtrTest, threadSafety) ClassLoader loader1(LIBRARY_1); ASSERT_TRUE(loader1.isLibraryLoaded()); - //Note: Hard to test thread safety to make sure memory isn't corrupted. - //The hope is this test is hard enough that once in a while it'll segfault - //or something if there's some implementation error. + // Note: Hard to test thread safety to make sure memory isn't corrupted. + // The hope is this test is hard enough that once in a while it'll segfault + // or something if there's some implementation error. try { std::vector client_threads; diff --git a/test/utest.cpp b/test/utest.cpp index d794b48c..a6593e64 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -20,7 +20,7 @@ TEST(ClassLoaderTest, basicLoad) try { class_loader::ClassLoader loader1(LIBRARY_1, false); - loader1.createInstance("Cat")->saySomething(); //See if lazy load works + loader1.createInstance("Cat")->saySomething(); // See if lazy load works } catch(class_loader::ClassLoaderException& e) { @@ -70,7 +70,7 @@ TEST(ClassLoaderTest, correctLazyLoadUnload) ASSERT_TRUE(loader1.isLibraryLoaded()); } - //The library will unload automatically when the only plugin object left is destroyed + // The library will unload automatically when the only plugin object left is destroyed ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); return; } @@ -183,7 +183,9 @@ TEST(ClassLoaderTest, threadSafety) class_loader::ClassLoader loader1(LIBRARY_1); ASSERT_TRUE(loader1.isLibraryLoaded()); - //Note: Hard to test thread safety to make sure memory isn't corrupted. The hope is this test is hard enough that once in a while it'll segfault or something if there's some implementation error. + // Note: Hard to test thread safety to make sure memory isn't corrupted. + // The hope is this test is hard enough that once in a while it'll segfault + // or something if there's some implementation error. try { std::vector client_threads; From db54aa25a04454af7bd9a6bcecb66f03a30ccd5a Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 22:03:14 -0800 Subject: [PATCH 05/11] no globl std::string --- test/unique_ptr_test.cpp | 4 ++-- test/utest.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index ff878033..9185aced 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -41,8 +41,8 @@ #include "./base.h" -const std::string LIBRARY_1 = "libclass_loader_TestPlugins1.so"; -const std::string LIBRARY_2 = "libclass_loader_TestPlugins2.so"; +const char LIBRARY_1[] = "libclass_loader_TestPlugins1.so"; +const char LIBRARY_2[] = "libclass_loader_TestPlugins2.so"; using class_loader::ClassLoader; diff --git a/test/utest.cpp b/test/utest.cpp index a6593e64..1e90d6d7 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -11,8 +11,8 @@ #include "./base.h" -const std::string LIBRARY_1 = "libclass_loader_TestPlugins1.so"; -const std::string LIBRARY_2 = "libclass_loader_TestPlugins2.so"; +const char LIBRARY_1[] = "libclass_loader_TestPlugins1.so"; +const char LIBRARY_2[] = "libclass_loader_TestPlugins2.so"; /*****************************************************************************/ TEST(ClassLoaderTest, basicLoad) From c54ed80453f6e53adcc41d9d1e781c38354b31a7 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 22:20:36 -0800 Subject: [PATCH 06/11] add some missing copyrights --- .../console_bridge_compatibility.h | 29 +++++++++++++++++++ test/base.h | 29 +++++++++++++++++++ test/plugins1.cpp | 29 +++++++++++++++++++ test/plugins2.cpp | 29 +++++++++++++++++++ test/utest.cpp | 29 +++++++++++++++++++ 5 files changed, 145 insertions(+) diff --git a/include/class_loader/console_bridge_compatibility.h b/include/class_loader/console_bridge_compatibility.h index 9f8610e1..6467376f 100644 --- a/include/class_loader/console_bridge_compatibility.h +++ b/include/class_loader/console_bridge_compatibility.h @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2017, Open Source Robotics Foundation, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H_ #define CLASS_LOADER__CONSOLE_BRIDGE_COMPATIBILITY_H_ diff --git a/test/base.h b/test/base.h index 8ed7cee6..73d611cc 100644 --- a/test/base.h +++ b/test/base.h @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #ifndef BASE_H_ #define BASE_H_ diff --git a/test/plugins1.cpp b/test/plugins1.cpp index 520fe0ab..4770565a 100644 --- a/test/plugins1.cpp +++ b/test/plugins1.cpp @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #include #include "class_loader/class_loader.h" diff --git a/test/plugins2.cpp b/test/plugins2.cpp index 6f51f5ff..0bf03f10 100644 --- a/test/plugins2.cpp +++ b/test/plugins2.cpp @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #include #include "class_loader/class_loader.h" diff --git a/test/utest.cpp b/test/utest.cpp index 1e90d6d7..bbd141e7 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -1,3 +1,32 @@ +/* + * Copyright (c) 2012, Willow Garage, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the Willow Garage, Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + #include #include #include From 21e6ad691703abc5f77b7896d682595f87ff5e5a Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 22:39:04 -0800 Subject: [PATCH 07/11] ignore explicit cpplint violation and add todo to address them on melodic branch --- include/class_loader/class_loader.h | 4 +++- include/class_loader/class_loader_exceptions.h | 17 ++++++++++++----- .../class_loader/multi_library_class_loader.h | 4 +++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/class_loader/class_loader.h b/include/class_loader/class_loader.h index 35274054..c8d6cc97 100644 --- a/include/class_loader/class_loader.h +++ b/include/class_loader/class_loader.h @@ -47,6 +47,8 @@ #include #endif +// TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release + namespace class_loader { @@ -75,7 +77,7 @@ class ClassLoader * @param library_path - The path of the runtime library to load * @param ondemand_load_unload - Indicates if on-demand (lazy) unloading/loading of libraries occurs as plugins are created/destroyed */ - ClassLoader(const std::string& library_path, bool ondemand_load_unload = false); + ClassLoader(const std::string& library_path, bool ondemand_load_unload = false); // NOLINT /** * @brief Destructor for ClassLoader. All libraries opened by this ClassLoader are unloaded automatically. diff --git a/include/class_loader/class_loader_exceptions.h b/include/class_loader/class_loader_exceptions.h index 8591c912..dcb8302d 100644 --- a/include/class_loader/class_loader_exceptions.h +++ b/include/class_loader/class_loader_exceptions.h @@ -33,6 +33,8 @@ #include #include +// TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release + namespace class_loader { @@ -43,7 +45,8 @@ namespace class_loader class ClassLoaderException: public std::runtime_error { public: - ClassLoaderException(const std::string error_desc) : std::runtime_error(error_desc) {} + ClassLoaderException(const std::string error_desc) // NOLINT(runtime/explicit) + : std::runtime_error(error_desc) {} }; /** @@ -53,7 +56,8 @@ class ClassLoaderException: public std::runtime_error class LibraryLoadException: public ClassLoaderException { public: - LibraryLoadException(const std::string error_desc) : ClassLoaderException(error_desc) {} + LibraryLoadException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; /** @@ -63,7 +67,8 @@ class LibraryLoadException: public ClassLoaderException class LibraryUnloadException: public ClassLoaderException { public: - LibraryUnloadException(const std::string error_desc) : ClassLoaderException(error_desc) {} + LibraryUnloadException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; /** @@ -73,7 +78,8 @@ class LibraryUnloadException: public ClassLoaderException class CreateClassException: public ClassLoaderException { public: - CreateClassException(const std::string error_desc) : ClassLoaderException(error_desc) {} + CreateClassException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; /** @@ -83,7 +89,8 @@ class CreateClassException: public ClassLoaderException class NoClassLoaderExistsException: public ClassLoaderException { public: - NoClassLoaderExistsException(const std::string error_desc) : ClassLoaderException(error_desc) {} + NoClassLoaderExistsException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; } // namespace class_loader diff --git a/include/class_loader/multi_library_class_loader.h b/include/class_loader/multi_library_class_loader.h index 6f6d79e3..da1d5f8d 100644 --- a/include/class_loader/multi_library_class_loader.h +++ b/include/class_loader/multi_library_class_loader.h @@ -37,6 +37,8 @@ #include "class_loader/class_loader.h" +// TODO(mikaelarguedas) : replace no lints with the explicit keyword in an ABI breaking release + namespace class_loader { @@ -55,7 +57,7 @@ class MultiLibraryClassLoader * @brief Constructor for the class * @param enable_ondemand_loadunload - Flag indicates if classes are to be loaded/unloaded automatically as class_loader are created and destroyed */ - MultiLibraryClassLoader(bool enable_ondemand_loadunload); + MultiLibraryClassLoader(bool enable_ondemand_loadunload); // NOLINT(runtime/explicit) /** * @brief Virtual destructor for class From 5eb8614420315085a7a9c1bf5db9dadf64d99a5c Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 23:13:48 -0800 Subject: [PATCH 08/11] uncrustify --- include/class_loader/class_loader.h | 434 ++++++++-------- include/class_loader/class_loader_core.h | 98 ++-- .../class_loader/class_loader_exceptions.h | 40 +- .../class_loader_register_macro.h | 25 +- include/class_loader/meta_object.h | 244 ++++----- .../class_loader/multi_library_class_loader.h | 488 +++++++++--------- src/class_loader.cpp | 36 +- src/class_loader_core.cpp | 286 +++++----- src/meta_object.cpp | 44 +- src/multi_library_class_loader.cpp | 48 +- test/base.h | 4 +- test/plugins1.cpp | 20 +- test/plugins2.cpp | 17 +- test/unique_ptr_test.cpp | 113 ++-- test/utest.cpp | 183 +++---- 15 files changed, 981 insertions(+), 1099 deletions(-) diff --git a/include/class_loader/class_loader.h b/include/class_loader/class_loader.h index c8d6cc97..fc06857d 100644 --- a/include/class_loader/class_loader.h +++ b/include/class_loader/class_loader.h @@ -63,240 +63,240 @@ std::string systemLibrarySuffix(); */ class ClassLoader { - public: +public: #if __cplusplus >= 201103L - template - using DeleterType = std::function; + template + using DeleterType = std::function; - template - using UniquePtr = std::unique_ptr>; + template + using UniquePtr = std::unique_ptr>; #endif - /** - * @brief Constructor for ClassLoader - * @param library_path - The path of the runtime library to load - * @param ondemand_load_unload - Indicates if on-demand (lazy) unloading/loading of libraries occurs as plugins are created/destroyed - */ - ClassLoader(const std::string& library_path, bool ondemand_load_unload = false); // NOLINT - - /** - * @brief Destructor for ClassLoader. All libraries opened by this ClassLoader are unloaded automatically. - */ - virtual ~ClassLoader(); - - /** - * @brief Indicates which classes (i.e. class_loader) that can be loaded by this object - * @return vector of strings indicating names of instantiable classes derived from - */ - template - std::vector getAvailableClasses() - { - return(class_loader::class_loader_private::getAvailableClasses(this)); - } - - /** - * @brief Gets the full-qualified path and name of the library associated with this class loader - */ - std::string getLibraryPath(){return(library_path_);} - - /** - * @brief Generates an instance of loadable classes (i.e. class_loader). - * - * It is not necessary for the user to call loadLibrary() as it will be invoked automatically - * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). - * - * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) - * @return A boost::shared_ptr to newly created plugin object - */ - template - boost::shared_ptr createInstance(const std::string& derived_class_name) - { - return boost::shared_ptr(createRawInstance(derived_class_name, true), - boost::bind(&ClassLoader::onPluginDeletion, this, _1)); - } + /** + * @brief Constructor for ClassLoader + * @param library_path - The path of the runtime library to load + * @param ondemand_load_unload - Indicates if on-demand (lazy) unloading/loading of libraries occurs as plugins are created/destroyed + */ + ClassLoader(const std::string & library_path, bool ondemand_load_unload = false); // NOLINT + + /** + * @brief Destructor for ClassLoader. All libraries opened by this ClassLoader are unloaded automatically. + */ + virtual ~ClassLoader(); + + /** + * @brief Indicates which classes (i.e. class_loader) that can be loaded by this object + * @return vector of strings indicating names of instantiable classes derived from + */ + template + std::vector getAvailableClasses() + { + return class_loader::class_loader_private::getAvailableClasses(this); + } + + /** + * @brief Gets the full-qualified path and name of the library associated with this class loader + */ + std::string getLibraryPath() {return library_path_;} + + /** + * @brief Generates an instance of loadable classes (i.e. class_loader). + * + * It is not necessary for the user to call loadLibrary() as it will be invoked automatically + * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). + * + * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) + * @return A boost::shared_ptr to newly created plugin object + */ + template + boost::shared_ptr createInstance(const std::string & derived_class_name) + { + return boost::shared_ptr( + createRawInstance(derived_class_name, true), + boost::bind(&ClassLoader::onPluginDeletion, this, _1)); + } #if __cplusplus >= 201103L - /** - * @brief Generates an instance of loadable classes (i.e. class_loader). - * - * It is not necessary for the user to call loadLibrary() as it will be invoked automatically - * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). - * - * If you release the wrapped pointer you must manually call the original - * deleter when you want to destroy the released pointer. - * - * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) - * @return A std::unique_ptr to newly created plugin object - */ - template - UniquePtr createUniqueInstance(const std::string& derived_class_name) - { - Base* raw = createRawInstance(derived_class_name, true); - return std::unique_ptr>( - raw, - boost::bind(&ClassLoader::onPluginDeletion, this, _1)); - } + /** + * @brief Generates an instance of loadable classes (i.e. class_loader). + * + * It is not necessary for the user to call loadLibrary() as it will be invoked automatically + * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). + * + * If you release the wrapped pointer you must manually call the original + * deleter when you want to destroy the released pointer. + * + * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) + * @return A std::unique_ptr to newly created plugin object + */ + template + UniquePtr createUniqueInstance(const std::string & derived_class_name) + { + Base * raw = createRawInstance(derived_class_name, true); + return std::unique_ptr>( + raw, + boost::bind(&ClassLoader::onPluginDeletion, this, _1)); + } #endif - /** - * @brief Generates an instance of loadable classes (i.e. class_loader). - * - * It is not necessary for the user to call loadLibrary() as it will be invoked automatically - * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). - * - * Creating an unmanaged instance disables dynamically unloading libraries when - * managed pointers go out of scope for all class loaders in this process. - * - * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) - * @return An unmanaged (i.e. not a shared_ptr) Base* to newly created plugin object. - */ - template - Base* createUnmanagedInstance(const std::string& derived_class_name) - { - return createRawInstance(derived_class_name, false); - } - - /** - * @brief Indicates if a plugin class is available - * @param Base - polymorphic type indicating base class - * @param class_name - the name of the plugin class - * @return true if yes it is available, false otherwise - */ - template - bool isClassAvailable(const std::string& class_name) - { - std::vector available_classes = getAvailableClasses(); - return std::find( - available_classes.begin(), available_classes.end(), class_name) != available_classes.end(); - } - - /** - * @brief Indicates if a library is loaded within the scope of this ClassLoader. Note that the library may already be loaded internally through another ClassLoader, but until loadLibrary() method is called, the ClassLoader cannot create objects from said library. If we want to see if the library has been opened by somebody else, @see isLibraryLoadedByAnyClassloader() - * @param library_path The path to the library to load - * @return true if library is loaded within this ClassLoader object's scope, otherwise false - */ - bool isLibraryLoaded(); - - /** - * @brief Indicates if a library is loaded by some entity in the plugin system (another ClassLoader), but not necessarily loaded by this ClassLoader - * @return true if library is loaded within the scope of the plugin system, otherwise false - */ - bool isLibraryLoadedByAnyClassloader(); - - /** - * @brief Indicates if the library is to be loaded/unloaded on demand...meaning that only to load a lib when the first plugin is created and automatically shut it down when last active plugin is destroyed. - */ - bool isOnDemandLoadUnloadEnabled(){return(ondemand_load_unload_);} - - /** - * @brief Attempts to load a library on behalf of the ClassLoader. If the library is already opened, this method has no effect. If the library has been already opened by some other entity (i.e. another ClassLoader or global interface), this object is given permissions to access any plugin classes loaded by that other entity. This is - * @param library_path The path to the library to load - */ - void loadLibrary(); - - /** - * @brief Attempts to unload a library loaded within scope of the ClassLoader. If the library is not opened, this method has no effect. If the library is opened by other another ClassLoader, the library will NOT be unloaded internally -- however this ClassLoader will no longer be able to instantiate class_loader bound to that library. If there are plugin objects that exist in memory created by this classloader, a warning message will appear and the library will not be unloaded. If loadLibrary() was called multiple times (e.g. in the case of multiple threads or purposefully in a single thread), the user is responsible for calling unloadLibrary() the same number of times. The library will not be unloaded within the context of this classloader until the number of unload calls matches the number of loads. - * @return The number of times more unloadLibrary() has to be called for it to be unbound from this ClassLoader - */ - int unloadLibrary(); - - private: - /** - * @brief Callback method when a plugin created by this class loader is destroyed - * @param obj - A pointer to the deleted object - */ - template - void onPluginDeletion(Base* obj) - { - CONSOLE_BRIDGE_logDebug( - "class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n", obj); - if(obj) - { - boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_); - delete(obj); - plugin_ref_count_ = plugin_ref_count_ - 1; - assert(plugin_ref_count_ >= 0); - if(plugin_ref_count_ == 0 && isOnDemandLoadUnloadEnabled()) - { - if(!ClassLoader::hasUnmanagedInstanceBeenCreated()) { - unloadLibraryInternal(false); - } else { - CONSOLE_BRIDGE_logWarn( - "class_loader::ClassLoader: " - "Cannot unload library %s even though last shared pointer went out of scope. " - "This is because createUnmanagedInstance was used within the scope of this process," - " perhaps by a different ClassLoader. Library will NOT be closed.", - getLibraryPath().c_str()); - } + /** + * @brief Generates an instance of loadable classes (i.e. class_loader). + * + * It is not necessary for the user to call loadLibrary() as it will be invoked automatically + * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). + * + * Creating an unmanaged instance disables dynamically unloading libraries when + * managed pointers go out of scope for all class loaders in this process. + * + * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) + * @return An unmanaged (i.e. not a shared_ptr) Base* to newly created plugin object. + */ + template + Base * createUnmanagedInstance(const std::string & derived_class_name) + { + return createRawInstance(derived_class_name, false); + } + + /** + * @brief Indicates if a plugin class is available + * @param Base - polymorphic type indicating base class + * @param class_name - the name of the plugin class + * @return true if yes it is available, false otherwise + */ + template + bool isClassAvailable(const std::string & class_name) + { + std::vector available_classes = getAvailableClasses(); + return std::find( + available_classes.begin(), available_classes.end(), class_name) != available_classes.end(); + } + + /** + * @brief Indicates if a library is loaded within the scope of this ClassLoader. Note that the library may already be loaded internally through another ClassLoader, but until loadLibrary() method is called, the ClassLoader cannot create objects from said library. If we want to see if the library has been opened by somebody else, @see isLibraryLoadedByAnyClassloader() + * @param library_path The path to the library to load + * @return true if library is loaded within this ClassLoader object's scope, otherwise false + */ + bool isLibraryLoaded(); + + /** + * @brief Indicates if a library is loaded by some entity in the plugin system (another ClassLoader), but not necessarily loaded by this ClassLoader + * @return true if library is loaded within the scope of the plugin system, otherwise false + */ + bool isLibraryLoadedByAnyClassloader(); + + /** + * @brief Indicates if the library is to be loaded/unloaded on demand...meaning that only to load a lib when the first plugin is created and automatically shut it down when last active plugin is destroyed. + */ + bool isOnDemandLoadUnloadEnabled() {return ondemand_load_unload_;} + + /** + * @brief Attempts to load a library on behalf of the ClassLoader. If the library is already opened, this method has no effect. If the library has been already opened by some other entity (i.e. another ClassLoader or global interface), this object is given permissions to access any plugin classes loaded by that other entity. This is + * @param library_path The path to the library to load + */ + void loadLibrary(); + + /** + * @brief Attempts to unload a library loaded within scope of the ClassLoader. If the library is not opened, this method has no effect. If the library is opened by other another ClassLoader, the library will NOT be unloaded internally -- however this ClassLoader will no longer be able to instantiate class_loader bound to that library. If there are plugin objects that exist in memory created by this classloader, a warning message will appear and the library will not be unloaded. If loadLibrary() was called multiple times (e.g. in the case of multiple threads or purposefully in a single thread), the user is responsible for calling unloadLibrary() the same number of times. The library will not be unloaded within the context of this classloader until the number of unload calls matches the number of loads. + * @return The number of times more unloadLibrary() has to be called for it to be unbound from this ClassLoader + */ + int unloadLibrary(); + +private: + /** + * @brief Callback method when a plugin created by this class loader is destroyed + * @param obj - A pointer to the deleted object + */ + template + void onPluginDeletion(Base * obj) + { + CONSOLE_BRIDGE_logDebug( + "class_loader::ClassLoader: Calling onPluginDeletion() for obj ptr = %p.\n", obj); + if (obj) { + boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_); + delete (obj); + plugin_ref_count_ = plugin_ref_count_ - 1; + assert(plugin_ref_count_ >= 0); + if (plugin_ref_count_ == 0 && isOnDemandLoadUnloadEnabled()) { + if (!ClassLoader::hasUnmanagedInstanceBeenCreated()) { + unloadLibraryInternal(false); + } else { + CONSOLE_BRIDGE_logWarn( + "class_loader::ClassLoader: " + "Cannot unload library %s even though last shared pointer went out of scope. " + "This is because createUnmanagedInstance was used within the scope of this process," + " perhaps by a different ClassLoader. Library will NOT be closed.", + getLibraryPath().c_str()); } } } + } + + /** + * @brief Generates an instance of loadable classes (i.e. class_loader). + * + * It is not necessary for the user to call loadLibrary() as it will be invoked automatically + * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). + * + * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) + * @param managed If true, the returned pointer is assumed to be wrapped in a smart pointer by the caller. + * @return A Base* to newly created plugin object + */ + template + Base * createRawInstance(const std::string & derived_class_name, bool managed) + { + if (!managed) { + has_unmananged_instance_been_created_ = true; + } - /** - * @brief Generates an instance of loadable classes (i.e. class_loader). - * - * It is not necessary for the user to call loadLibrary() as it will be invoked automatically - * if the library is not yet loaded (which typically happens when in "On Demand Load/Unload" mode). - * - * @param derived_class_name The name of the class we want to create (@see getAvailableClasses()) - * @param managed If true, the returned pointer is assumed to be wrapped in a smart pointer by the caller. - * @return A Base* to newly created plugin object - */ - template - Base* createRawInstance(const std::string& derived_class_name, bool managed) + if ( + managed && + ClassLoader::hasUnmanagedInstanceBeenCreated() && + isOnDemandLoadUnloadEnabled()) { - if (!managed) - has_unmananged_instance_been_created_ = true; - - if ( - managed && - ClassLoader::hasUnmanagedInstanceBeenCreated() && - isOnDemandLoadUnloadEnabled()) - { - CONSOLE_BRIDGE_logInform( - "class_loader::ClassLoader: " - "An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), " - "however an unmanaged instance was created within this process address space. " - "This means libraries for the managed instances will not be shutdown automatically on " - "final plugin destruction if on demand (lazy) loading/unloading mode is used." - ); - } - if (!isLibraryLoaded()) - loadLibrary(); - - Base* obj = - class_loader::class_loader_private::createInstance(derived_class_name, this); - assert(obj != NULL); // Unreachable assertion if createInstance() throws on failure + CONSOLE_BRIDGE_logInform( + "class_loader::ClassLoader: " + "An attempt is being made to create a managed plugin instance (i.e. boost::shared_ptr), " + "however an unmanaged instance was created within this process address space. " + "This means libraries for the managed instances will not be shutdown automatically on " + "final plugin destruction if on demand (lazy) loading/unloading mode is used." + ); + } + if (!isLibraryLoaded()) { + loadLibrary(); + } - if (managed) - { - boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_); - plugin_ref_count_ = plugin_ref_count_ + 1; - } + Base * obj = + class_loader::class_loader_private::createInstance(derived_class_name, this); + assert(obj != NULL); // Unreachable assertion if createInstance() throws on failure - return obj; + if (managed) { + boost::recursive_mutex::scoped_lock lock(plugin_ref_count_mutex_); + plugin_ref_count_ = plugin_ref_count_ + 1; } - /** - * @brief Getter for if an unmanaged (i.e. unsafe) instance has been created flag - */ - static bool hasUnmanagedInstanceBeenCreated(); - - /** - * @brief As the library may be unloaded in "on-demand load/unload" mode, unload maybe called from createInstance(). The problem is that createInstance() locks the plugin_ref_count as does unloadLibrary(). This method is the implementation of unloadLibrary but with a parameter to decide if plugin_ref_mutex_ should be locked - * @param lock_plugin_ref_count - Set to true if plugin_ref_count_mutex_ should be locked, else false - * @return The number of times unloadLibraryInternal has to be called again for it to be unbound from this ClassLoader - */ - int unloadLibraryInternal(bool lock_plugin_ref_count); - - private: - bool ondemand_load_unload_; - std::string library_path_; - int load_ref_count_; - boost::recursive_mutex load_ref_count_mutex_; - int plugin_ref_count_; - boost::recursive_mutex plugin_ref_count_mutex_; - static bool has_unmananged_instance_been_created_; + return obj; + } + + /** + * @brief Getter for if an unmanaged (i.e. unsafe) instance has been created flag + */ + static bool hasUnmanagedInstanceBeenCreated(); + + /** + * @brief As the library may be unloaded in "on-demand load/unload" mode, unload maybe called from createInstance(). The problem is that createInstance() locks the plugin_ref_count as does unloadLibrary(). This method is the implementation of unloadLibrary but with a parameter to decide if plugin_ref_mutex_ should be locked + * @param lock_plugin_ref_count - Set to true if plugin_ref_count_mutex_ should be locked, else false + * @return The number of times unloadLibraryInternal has to be called again for it to be unbound from this ClassLoader + */ + int unloadLibraryInternal(bool lock_plugin_ref_count); + +private: + bool ondemand_load_unload_; + std::string library_path_; + int load_ref_count_; + boost::recursive_mutex load_ref_count_mutex_; + int plugin_ref_count_; + boost::recursive_mutex plugin_ref_count_mutex_; + static bool has_unmananged_instance_been_created_; }; } // namespace class_loader diff --git a/include/class_loader/class_loader_core.h b/include/class_loader/class_loader_core.h index 34a9c484..0de7856f 100644 --- a/include/class_loader/class_loader_core.h +++ b/include/class_loader/class_loader_core.h @@ -60,11 +60,11 @@ namespace class_loader_private typedef std::string LibraryPath; typedef std::string ClassName; typedef std::string BaseClassName; -typedef std::map FactoryMap; +typedef std::map FactoryMap; typedef std::map BaseToFactoryMapMap; -typedef std::pair LibraryPair; +typedef std::pair LibraryPair; typedef std::vector LibraryVector; -typedef std::vector MetaObjectVector; +typedef std::vector MetaObjectVector; // Debug /*****************************************************************************/ @@ -77,13 +77,13 @@ void printDebugInfoToScreen(); * @brief Gets a handle to a global data structure that holds a map of base class names (Base class describes plugin interface) to a FactoryMap which holds the factories for the various different concrete classes that can be instantiated. Note that the Base class is NOT THE LITERAL CLASSNAME, but rather the result of typeid(Base).name() which sometimes is the literal class name (as on Windows) but is often in mangled form (as on Linux). * @return A reference to the global base to factory map */ -BaseToFactoryMapMap& getGlobalPluginBaseToFactoryMapMap(); +BaseToFactoryMapMap & getGlobalPluginBaseToFactoryMapMap(); /** * @brief Gets a handle to a list of open libraries in the form of LibraryPairs which encode the library path+name and the handle to the underlying Poco::SharedLibrary * @return A reference to the global vector that tracks loaded libraries */ -LibraryVector& getLoadedLibraryVector(); +LibraryVector & getLoadedLibraryVector(); /** * @brief When a library is being loaded, in order for factories to know which library they are being associated with, they use this function to query which library is being loaded. @@ -95,44 +95,44 @@ std::string getCurrentlyLoadingLibraryName(); * @brief When a library is being loaded, in order for factories to know which library they are being associated with, this function is called to set the name of the library currently being loaded. * @param library_name - The name of library that is being loaded currently */ -void setCurrentlyLoadingLibraryName(const std::string& library_name); +void setCurrentlyLoadingLibraryName(const std::string & library_name); /** * @brief Gets the ClassLoader currently in scope which used when a library is being loaded. * @return A pointer to the currently active ClassLoader. */ -ClassLoader* getCurrentlyActiveClassLoader(); +ClassLoader * getCurrentlyActiveClassLoader(); /** * @brief Sets the ClassLoader currently in scope which used when a library is being loaded. * @param loader - pointer to the currently active ClassLoader. */ -void setCurrentlyActiveClassLoader(ClassLoader* loader); +void setCurrentlyActiveClassLoader(ClassLoader * loader); /** * @brief This function extracts a reference to the FactoryMap for appropriate base class out of the global plugin base to factory map. This function should be used by functions in this namespace that need to access the various factories so as to make sure the right key is generated to index into the global map. * @return A reference to the FactoryMap contained within the global Base-to-FactoryMap map. */ -FactoryMap& getFactoryMapForBaseClass(const std::string& typeid_base_class_name); +FactoryMap & getFactoryMapForBaseClass(const std::string & typeid_base_class_name); /** * @brief Same as above but uses a type parameter instead of string for more safety if info is available. * @return A reference to the FactoryMap contained within the global Base-to-FactoryMap map. */ -template -FactoryMap& getFactoryMapForBaseClass() +template +FactoryMap & getFactoryMapForBaseClass() { - return(getFactoryMapForBaseClass(typeid(Base).name())); + return getFactoryMapForBaseClass(typeid(Base).name()); } /** * @brief To provide thread safety, all exposed plugin functions can only be run serially by multiple threads. This is implemented by using critical sections enforced by a single mutex which is locked and released with the following two functions * @return A reference to the global mutex */ -boost::recursive_mutex& getLoadedLibraryVectorMutex(); -boost::recursive_mutex& getPluginBaseToFactoryMapMapMutex(); +boost::recursive_mutex & getLoadedLibraryVectorMutex(); +boost::recursive_mutex & getPluginBaseToFactoryMapMapMutex(); /** * @brief Indicates if a library containing more than just plugins has been opened by the running process @@ -156,8 +156,8 @@ void hasANonPurePluginLibraryBeenOpened(bool hasIt); * @param Base - parameteric type indicating base type of plugin * @param class_name - the literal name of the class being registered (NOT MANGLED) */ -template -void registerPlugin(const std::string& class_name, const std::string& base_class_name) +template +void registerPlugin(const std::string & class_name, const std::string & base_class_name) { // Note: This function will be automatically invoked when a dlopen() call // opens a library. Normally it will happen within the scope of loadLibrary(), @@ -168,8 +168,7 @@ void registerPlugin(const std::string& class_name, const std::string& base_class class_name.c_str(), getCurrentlyActiveClassLoader(), getCurrentlyLoadingLibraryName().c_str()); - if(getCurrentlyActiveClassLoader() == NULL) - { + if (getCurrentlyActiveClassLoader() == NULL) { CONSOLE_BRIDGE_logDebug( "class_loader.impl: ALERT!!! " "A library containing plugins has been opened through a means other than through the " @@ -190,7 +189,7 @@ void registerPlugin(const std::string& class_name, const std::string& base_class } // Create factory - class_loader_private::AbstractMetaObject* new_factory = + class_loader_private::AbstractMetaObject * new_factory = new class_loader_private::MetaObject(class_name, base_class_name); new_factory->addOwningClassLoader(getCurrentlyActiveClassLoader()); new_factory->setAssociatedLibraryPath(getCurrentlyLoadingLibraryName()); @@ -198,8 +197,8 @@ void registerPlugin(const std::string& class_name, const std::string& base_class // Add it to global factory map map getPluginBaseToFactoryMapMapMutex().lock(); - FactoryMap& factoryMap = getFactoryMapForBaseClass(); - if(factoryMap.find(class_name) != factoryMap.end()) { + FactoryMap & factoryMap = getFactoryMapForBaseClass(); + if (factoryMap.find(class_name) != factoryMap.end()) { CONSOLE_BRIDGE_logWarn( "class_loader.impl: SEVERE WARNING!!! " "A namespace collision has occured with plugin factory for class %s. " @@ -225,15 +224,15 @@ void registerPlugin(const std::string& class_name, const std::string& base_class * @param loader - The ClassLoader whose scope we are within * @return A pointer to newly created plugin, note caller is responsible for object destruction */ -template -Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) +template +Base * createInstance(const std::string & derived_class_name, ClassLoader * loader) { - AbstractMetaObject* factory = NULL; + AbstractMetaObject * factory = NULL; getPluginBaseToFactoryMapMapMutex().lock(); - FactoryMap& factoryMap = getFactoryMapForBaseClass(); - if(factoryMap.find(derived_class_name) != factoryMap.end()) { - factory = dynamic_cast*>( + FactoryMap & factoryMap = getFactoryMapForBaseClass(); + if (factoryMap.find(derived_class_name) != factoryMap.end()) { + factory = dynamic_cast *>( factoryMap[derived_class_name]); } else { CONSOLE_BRIDGE_logError( @@ -242,14 +241,13 @@ Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) } getPluginBaseToFactoryMapMapMutex().unlock(); - Base* obj = NULL; - if(factory != NULL && factory->isOwnedBy(loader)) + Base * obj = NULL; + if (factory != NULL && factory->isOwnedBy(loader)) { obj = factory->create(); + } - if(obj == NULL) // Was never created - { - if(factory && factory->isOwnedBy(NULL)) - { + if (obj == NULL) { // Was never created + if (factory && factory->isOwnedBy(NULL)) { CONSOLE_BRIDGE_logDebug( "class_loader.impl: ALERT!!! " "A metaobject (i.e. factory) exists for desired class, but has no owner. " @@ -264,7 +262,7 @@ Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) obj = factory->create(); } else { throw(class_loader::CreateClassException( - "Could not create instance of type " + derived_class_name)); + "Could not create instance of type " + derived_class_name)); } } @@ -273,7 +271,7 @@ Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) "Created instance of type %s and object pointer = %p", (typeid(obj).name()), obj); - return(obj); + return obj; } /** @@ -281,28 +279,28 @@ Base* createInstance(const std::string& derived_class_name, ClassLoader* loader) * @param loader - The pointer to the ClassLoader whose scope we are within, * @return A vector of strings where each string is a plugin we can create */ -template -std::vector getAvailableClasses(ClassLoader* loader) +template +std::vector getAvailableClasses(ClassLoader * loader) { boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex()); - FactoryMap& factory_map = getFactoryMapForBaseClass(); + FactoryMap & factory_map = getFactoryMapForBaseClass(); std::vector classes; std::vector classes_with_no_owner; - for(FactoryMap::const_iterator itr = factory_map.begin(); itr != factory_map.end(); ++itr) - { - AbstractMetaObjectBase* factory = itr->second; - if(factory->isOwnedBy(loader)) + for (FactoryMap::const_iterator itr = factory_map.begin(); itr != factory_map.end(); ++itr) { + AbstractMetaObjectBase * factory = itr->second; + if (factory->isOwnedBy(loader)) { classes.push_back(itr->first); - else if(factory->isOwnedBy(NULL)) + } else if (factory->isOwnedBy(NULL)) { classes_with_no_owner.push_back(itr->first); + } } // Added classes not associated with a class loader (Which can happen through // an unexpected dlopen() to the library) - classes.insert(classes.end(), classes_with_no_owner.begin(), classes_with_no_owner.end()); - return(classes); + classes.insert(classes.end(), classes_with_no_owner.begin(), classes_with_no_owner.end()); + return classes; } /** @@ -310,7 +308,7 @@ std::vector getAvailableClasses(ClassLoader* loader) * @param loader - The ClassLoader whose scope we are within * @return A vector of strings where each string is the path+name of each library that are within a ClassLoader's visible scope */ -std::vector getAllLibrariesUsedByClassLoader(const ClassLoader* loader); +std::vector getAllLibrariesUsedByClassLoader(const ClassLoader * loader); /** * @brief Indicates if passed library loaded within scope of a ClassLoader. The library maybe loaded in memory, but to the class loader it may not be. @@ -318,28 +316,28 @@ std::vector getAllLibrariesUsedByClassLoader(const ClassLoader* loa * @param loader - The pointer to the ClassLoader whose scope we are within * @return true if the library is loaded within loader's scope, else false */ -bool isLibraryLoaded(const std::string& library_path, ClassLoader* loader); +bool isLibraryLoaded(const std::string & library_path, ClassLoader * loader); /** * @brief Indicates if passed library has been loaded by ANY ClassLoader * @param library_path - The name of the library we wish to check is open * @return true if the library is loaded in memory, otherwise false */ -bool isLibraryLoadedByAnybody(const std::string& library_path); +bool isLibraryLoadedByAnybody(const std::string & library_path); /** * @brief Loads a library into memory if it has not already been done so. Attempting to load an already loaded library has no effect. * @param library_path - The name of the library to open * @param loader - The pointer to the ClassLoader whose scope we are within */ -void loadLibrary(const std::string& library_path, ClassLoader* loader); +void loadLibrary(const std::string & library_path, ClassLoader * loader); /** * @brief Unloads a library if it loaded in memory and cleans up its corresponding class factories. If it is not loaded, the function has no effect * @param library_path - The name of the library to open * @param loader - The pointer to the ClassLoader whose scope we are within */ -void unloadLibrary(const std::string& library_path, ClassLoader* loader); +void unloadLibrary(const std::string & library_path, ClassLoader * loader); } // namespace class_loader_private diff --git a/include/class_loader/class_loader_exceptions.h b/include/class_loader/class_loader_exceptions.h index dcb8302d..591bb556 100644 --- a/include/class_loader/class_loader_exceptions.h +++ b/include/class_loader/class_loader_exceptions.h @@ -42,55 +42,55 @@ namespace class_loader * @class ClassLoader sException * @brief A base class for all class_loader exceptions that inherits from std::runtime_exception */ -class ClassLoaderException: public std::runtime_error +class ClassLoaderException : public std::runtime_error { - public: - ClassLoaderException(const std::string error_desc) // NOLINT(runtime/explicit) - : std::runtime_error(error_desc) {} +public: + ClassLoaderException(const std::string error_desc) // NOLINT(runtime/explicit) + : std::runtime_error(error_desc) {} }; /** * @class LibraryLoadException * @brief An exception class thrown when class_loader is unable to load a runtime library */ -class LibraryLoadException: public ClassLoaderException +class LibraryLoadException : public ClassLoaderException { - public: - LibraryLoadException(const std::string error_desc) // NOLINT(runtime/explicit) - : ClassLoaderException(error_desc) {} +public: + LibraryLoadException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; /** * @class LibraryUnloadException * @brief An exception class thrown when class_loader is unable to unload a runtime library */ -class LibraryUnloadException: public ClassLoaderException +class LibraryUnloadException : public ClassLoaderException { - public: - LibraryUnloadException(const std::string error_desc) // NOLINT(runtime/explicit) - : ClassLoaderException(error_desc) {} +public: + LibraryUnloadException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; /** * @class CreateClassException * @brief An exception class thrown when class_loader is unable to create a plugin */ -class CreateClassException: public ClassLoaderException +class CreateClassException : public ClassLoaderException { - public: - CreateClassException(const std::string error_desc) // NOLINT(runtime/explicit) - : ClassLoaderException(error_desc) {} +public: + CreateClassException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; /** * @class NoClassLoaderExistsException * @brief An exception class thrown when a multilibrary class loader does not have a ClassLoader bound to it */ -class NoClassLoaderExistsException: public ClassLoaderException +class NoClassLoaderExistsException : public ClassLoaderException { - public: - NoClassLoaderExistsException(const std::string error_desc) // NOLINT(runtime/explicit) - : ClassLoaderException(error_desc) {} +public: + NoClassLoaderExistsException(const std::string error_desc) // NOLINT(runtime/explicit) + : ClassLoaderException(error_desc) {} }; } // namespace class_loader diff --git a/include/class_loader/class_loader_register_macro.h b/include/class_loader/class_loader_register_macro.h index 79cc7e69..cc7c1f43 100644 --- a/include/class_loader/class_loader_register_macro.h +++ b/include/class_loader/class_loader_register_macro.h @@ -38,21 +38,21 @@ #include "console_bridge/console.h" #define CLASS_LOADER_REGISTER_CLASS_INTERNAL_WITH_MESSAGE(Derived, Base, UniqueID, Message) \ -namespace \ -{\ - struct ProxyExec##UniqueID \ - {\ + namespace \ + { \ + struct ProxyExec ## UniqueID \ + { \ typedef Derived _derived; \ - typedef Base _base; \ - ProxyExec##UniqueID() \ + typedef Base _base; \ + ProxyExec ## UniqueID() \ { \ - if(std::string(Message) != "")\ - CONSOLE_BRIDGE_logInform("%s", Message);\ + if (std::string(Message) != "") { \ + CONSOLE_BRIDGE_logInform("%s", Message);} \ class_loader::class_loader_private::registerPlugin<_derived, _base>(#Derived, #Base); \ - }\ - };\ - static ProxyExec##UniqueID g_register_plugin_##UniqueID;\ -} // namespace + } \ + }; \ + static ProxyExec ## UniqueID g_register_plugin_ ## UniqueID; \ + } // namespace #define CLASS_LOADER_REGISTER_CLASS_INTERNAL_HOP1_WITH_MESSAGE(Derived, Base, UniqueID, Message) \ CLASS_LOADER_REGISTER_CLASS_INTERNAL_WITH_MESSAGE(Derived, Base, UniqueID, Message) @@ -72,4 +72,3 @@ namespace \ CLASS_LOADER_REGISTER_CLASS_WITH_MESSAGE(Derived, Base, "") #endif // CLASS_LOADER__CLASS_LOADER_REGISTER_MACRO_H_ - diff --git a/include/class_loader/meta_object.h b/include/class_loader/meta_object.h index 13fcc4c6..67fedb79 100644 --- a/include/class_loader/meta_object.h +++ b/include/class_loader/meta_object.h @@ -48,7 +48,7 @@ class ClassLoader; // Forward declaration namespace class_loader_private { -typedef std::vector ClassLoaderVector; +typedef std::vector ClassLoaderVector; /** * @class AbstractMetaObjectBase @@ -56,84 +56,84 @@ typedef std::vector ClassLoaderVector; */ class AbstractMetaObjectBase { - public: - /** - * @brief Constructor for the class - */ - AbstractMetaObjectBase(const std::string& class_name, const std::string& base_class_name); - /** - * @brief Destructor for the class. THIS MUST NOT BE VIRTUAL AND OVERRIDDEN BY - * TEMPLATE SUBCLASSES, OTHERWISE THEY WILL PULL IN A REDUNDANT METAOBJECT - * DESTRUCTOR OUTSIDE OF libclass_loader WITHIN THE PLUGIN LIBRARY! T - */ - ~AbstractMetaObjectBase(); - - /** - * @brief Gets the literal name of the class. - * @return The literal name of the class as a C-string. - */ - std::string className() const; - - /** - * @brief gets the base class for the class this factory represents - */ - std::string baseClassName() const; - /** - * @brief Gets the name of the class as typeid(BASE_CLASS).name() would return it - */ - std::string typeidBaseClassName() const; - - /** - * @brief Gets the path to the library associated with this factory - * @return Library path as a std::string - */ - std::string getAssociatedLibraryPath(); - - /** - * @brief Sets the path to the library associated with this factory - */ - void setAssociatedLibraryPath(std::string library_path); - - /** - * @brief Associates a ClassLoader owner with this factory, - * @param loader Handle to the owning ClassLoader. - */ - void addOwningClassLoader(ClassLoader* loader); - - /** - * @brief Removes a ClassLoader that is an owner of this factory - * @param loader Handle to the owning ClassLoader. - */ - void removeOwningClassLoader(const ClassLoader* loader); - - /** - * @brief Indicates if the factory is within the usable scope of a ClassLoader - * @param loader Handle to the owning ClassLoader. - */ - bool isOwnedBy(const ClassLoader* loader); - - /** - * @brief Indicates if the factory is within the usable scope of any ClassLoader - */ - bool isOwnedByAnybody(); - - /** - * A vector of class loaders that own this metaobject - */ - ClassLoaderVector getAssociatedClassLoaders(); - - protected: - /** - * This is needed to make base class polymorphic (i.e. have a vtable) - */ - virtual void dummyMethod(){} - - protected: - ClassLoaderVector associated_class_loaders_; - std::string associated_library_path_; - std::string base_class_name_; - std::string class_name_; - std::string typeid_base_class_name_; +public: + /** + * @brief Constructor for the class + */ + AbstractMetaObjectBase(const std::string & class_name, const std::string & base_class_name); + /** + * @brief Destructor for the class. THIS MUST NOT BE VIRTUAL AND OVERRIDDEN BY + * TEMPLATE SUBCLASSES, OTHERWISE THEY WILL PULL IN A REDUNDANT METAOBJECT + * DESTRUCTOR OUTSIDE OF libclass_loader WITHIN THE PLUGIN LIBRARY! T + */ + ~AbstractMetaObjectBase(); + + /** + * @brief Gets the literal name of the class. + * @return The literal name of the class as a C-string. + */ + std::string className() const; + + /** + * @brief gets the base class for the class this factory represents + */ + std::string baseClassName() const; + /** + * @brief Gets the name of the class as typeid(BASE_CLASS).name() would return it + */ + std::string typeidBaseClassName() const; + + /** + * @brief Gets the path to the library associated with this factory + * @return Library path as a std::string + */ + std::string getAssociatedLibraryPath(); + + /** + * @brief Sets the path to the library associated with this factory + */ + void setAssociatedLibraryPath(std::string library_path); + + /** + * @brief Associates a ClassLoader owner with this factory, + * @param loader Handle to the owning ClassLoader. + */ + void addOwningClassLoader(ClassLoader * loader); + + /** + * @brief Removes a ClassLoader that is an owner of this factory + * @param loader Handle to the owning ClassLoader. + */ + void removeOwningClassLoader(const ClassLoader * loader); + + /** + * @brief Indicates if the factory is within the usable scope of a ClassLoader + * @param loader Handle to the owning ClassLoader. + */ + bool isOwnedBy(const ClassLoader * loader); + + /** + * @brief Indicates if the factory is within the usable scope of any ClassLoader + */ + bool isOwnedByAnybody(); + + /** + * A vector of class loaders that own this metaobject + */ + ClassLoaderVector getAssociatedClassLoaders(); + +protected: + /** + * This is needed to make base class polymorphic (i.e. have a vtable) + */ + virtual void dummyMethod() {} + +protected: + ClassLoaderVector associated_class_loaders_; + std::string associated_library_path_; + std::string base_class_name_; + std::string class_name_; + std::string typeid_base_class_name_; }; /** @@ -141,32 +141,32 @@ class AbstractMetaObjectBase * @brief Abstract base class for factories where polymorphic type variable indicates base class for plugin interface. * @parm B The base class interface for the plugin */ -template +template class AbstractMetaObject : public AbstractMetaObjectBase { - public: - /** - * @brief A constructor for this class - * @param name The literal name of the class. - */ - AbstractMetaObject(const std::string& class_name, const std::string& base_class_name) : - AbstractMetaObjectBase(class_name, base_class_name) - { - AbstractMetaObjectBase::typeid_base_class_name_ = std::string(typeid(B).name()); - } - - /** - * @brief Defines the factory interface that the MetaObject must implement. - * @return A pointer of parametric type B to a newly created object. - */ - virtual B* create() const = 0; - /// Create a new instance of a class. - /// Cannot be used for singletons. - - private: - AbstractMetaObject(); - AbstractMetaObject(const AbstractMetaObject&); - AbstractMetaObject& operator = (const AbstractMetaObject&); +public: + /** + * @brief A constructor for this class + * @param name The literal name of the class. + */ + AbstractMetaObject(const std::string & class_name, const std::string & base_class_name) + : AbstractMetaObjectBase(class_name, base_class_name) + { + AbstractMetaObjectBase::typeid_base_class_name_ = std::string(typeid(B).name()); + } + + /** + * @brief Defines the factory interface that the MetaObject must implement. + * @return A pointer of parametric type B to a newly created object. + */ + virtual B * create() const = 0; + /// Create a new instance of a class. + /// Cannot be used for singletons. + +private: + AbstractMetaObject(); + AbstractMetaObject(const AbstractMetaObject &); + AbstractMetaObject & operator=(const AbstractMetaObject &); }; /** @@ -175,26 +175,26 @@ class AbstractMetaObject : public AbstractMetaObjectBase * @parm C The derived class (the actual plugin) * @parm B The base class interface for the plugin */ -template -class MetaObject: public AbstractMetaObject +template +class MetaObject : public AbstractMetaObject { - public: - /** - * @brief Constructor for the class - */ - MetaObject(const std::string& class_name, const std::string& base_class_name) : - AbstractMetaObject(class_name, base_class_name) - { - } - - /** - * @brief The factory interface to generate an object. The object has type C in reality, though a pointer of the base class type is returned. - * @return A pointer to a newly created plugin with the base class type (type parameter B) - */ - B* create() const - { - return new C; - } +public: + /** + * @brief Constructor for the class + */ + MetaObject(const std::string & class_name, const std::string & base_class_name) + : AbstractMetaObject(class_name, base_class_name) + { + } + + /** + * @brief The factory interface to generate an object. The object has type C in reality, though a pointer of the base class type is returned. + * @return A pointer to a newly created plugin with the base class type (type parameter B) + */ + B * create() const + { + return new C; + } }; } // namespace class_loader_private diff --git a/include/class_loader/multi_library_class_loader.h b/include/class_loader/multi_library_class_loader.h index da1d5f8d..255827ae 100644 --- a/include/class_loader/multi_library_class_loader.h +++ b/include/class_loader/multi_library_class_loader.h @@ -43,8 +43,8 @@ namespace class_loader { typedef std::string LibraryPath; -typedef std::map LibraryToClassLoaderMap; -typedef std::vector ClassLoaderVector; +typedef std::map LibraryToClassLoaderMap; +typedef std::vector ClassLoaderVector; /** * @class MultiLibraryClassLoader @@ -52,280 +52,280 @@ typedef std::vector ClassLoaderVector; */ class MultiLibraryClassLoader { - public: - /** - * @brief Constructor for the class - * @param enable_ondemand_loadunload - Flag indicates if classes are to be loaded/unloaded automatically as class_loader are created and destroyed - */ - MultiLibraryClassLoader(bool enable_ondemand_loadunload); // NOLINT(runtime/explicit) +public: + /** + * @brief Constructor for the class + * @param enable_ondemand_loadunload - Flag indicates if classes are to be loaded/unloaded automatically as class_loader are created and destroyed + */ + MultiLibraryClassLoader(bool enable_ondemand_loadunload); // NOLINT(runtime/explicit) - /** - * @brief Virtual destructor for class - */ - virtual ~MultiLibraryClassLoader(); + /** + * @brief Virtual destructor for class + */ + virtual ~MultiLibraryClassLoader(); - /** - * @brief Creates an instance of an object of given class name with ancestor class Base - * This version does not look in a specific library for the factory, but rather the first open library that defines the classs - * @param Base - polymorphic type indicating base class - * @param class_name - the name of the concrete plugin class we want to instantiate - * @return A boost::shared_ptr to newly created plugin - */ - template - boost::shared_ptr createInstance(const std::string& class_name) - { - CONSOLE_BRIDGE_logDebug( - "class_loader::MultiLibraryClassLoader: " - "Attempting to create instance of class type %s.", - class_name.c_str()); - ClassLoader* loader = getClassLoaderForClass(class_name); - if (loader == NULL) { - throw class_loader::CreateClassException( - "MultiLibraryClassLoader: Could not create object of class type " + - class_name + - " as no factory exists for it. Make sure that the library exists and " - "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()"); - } - - return loader->createInstance(class_name); + /** + * @brief Creates an instance of an object of given class name with ancestor class Base + * This version does not look in a specific library for the factory, but rather the first open library that defines the classs + * @param Base - polymorphic type indicating base class + * @param class_name - the name of the concrete plugin class we want to instantiate + * @return A boost::shared_ptr to newly created plugin + */ + template + boost::shared_ptr createInstance(const std::string & class_name) + { + CONSOLE_BRIDGE_logDebug( + "class_loader::MultiLibraryClassLoader: " + "Attempting to create instance of class type %s.", + class_name.c_str()); + ClassLoader * loader = getClassLoaderForClass(class_name); + if (loader == NULL) { + throw class_loader::CreateClassException( + "MultiLibraryClassLoader: Could not create object of class type " + + class_name + + " as no factory exists for it. Make sure that the library exists and " + "was explicitly loaded through MultiLibraryClassLoader::loadLibrary()"); } - /** - * @brief Creates an instance of an object of given class name with ancestor class Base - * This version takes a specific library to make explicit the factory being used - * @param Base - polymorphic type indicating base class - * @param class_name - the name of the concrete plugin class we want to instantiate - * @param library_path - the library from which we want to create the plugin - * @return A boost::shared_ptr to newly created plugin - */ - template - boost::shared_ptr - createInstance(const std::string& class_name, const std::string& library_path) - { - ClassLoader* loader = getClassLoaderForLibrary(library_path); - if (loader == NULL) { - throw class_loader::NoClassLoaderExistsException( - "Could not create instance as there is no ClassLoader in " - "MultiLibraryClassLoader bound to library " + library_path + - " Ensure you called MultiLibraryClassLoader::loadLibrary()"); - } - return loader->createInstance(class_name); + return loader->createInstance(class_name); + } + + /** + * @brief Creates an instance of an object of given class name with ancestor class Base + * This version takes a specific library to make explicit the factory being used + * @param Base - polymorphic type indicating base class + * @param class_name - the name of the concrete plugin class we want to instantiate + * @param library_path - the library from which we want to create the plugin + * @return A boost::shared_ptr to newly created plugin + */ + template + boost::shared_ptr + createInstance(const std::string & class_name, const std::string & library_path) + { + ClassLoader * loader = getClassLoaderForLibrary(library_path); + if (loader == NULL) { + throw class_loader::NoClassLoaderExistsException( + "Could not create instance as there is no ClassLoader in " + "MultiLibraryClassLoader bound to library " + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); } + return loader->createInstance(class_name); + } #if __cplusplus >= 201103L - /** - * @brief Creates an instance of an object of given class name with ancestor class Base - * This version does not look in a specific library for the factory, but rather the first open library that defines the classs - * @param Base - polymorphic type indicating base class - * @param class_name - the name of the concrete plugin class we want to instantiate - * @return A unique pointer to newly created plugin - */ - template - ClassLoader::UniquePtr createUniqueInstance(const std::string& class_name) - { - CONSOLE_BRIDGE_logDebug( - "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.", - class_name.c_str()); - ClassLoader* loader = getClassLoaderForClass(class_name); - if (loader == nullptr) { - throw class_loader::CreateClassException( - "MultiLibraryClassLoader: Could not create object of class type " + class_name + - " as no factory exists for it. " - "Make sure that the library exists and was explicitly loaded through " - "MultiLibraryClassLoader::loadLibrary()"); - } - return loader->createUniqueInstance(class_name); + /** + * @brief Creates an instance of an object of given class name with ancestor class Base + * This version does not look in a specific library for the factory, but rather the first open library that defines the classs + * @param Base - polymorphic type indicating base class + * @param class_name - the name of the concrete plugin class we want to instantiate + * @return A unique pointer to newly created plugin + */ + template + ClassLoader::UniquePtr createUniqueInstance(const std::string & class_name) + { + CONSOLE_BRIDGE_logDebug( + "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.", + class_name.c_str()); + ClassLoader * loader = getClassLoaderForClass(class_name); + if (loader == nullptr) { + throw class_loader::CreateClassException( + "MultiLibraryClassLoader: Could not create object of class type " + class_name + + " as no factory exists for it. " + "Make sure that the library exists and was explicitly loaded through " + "MultiLibraryClassLoader::loadLibrary()"); } + return loader->createUniqueInstance(class_name); + } - /** - * @brief Creates an instance of an object of given class name with ancestor class Base - * This version takes a specific library to make explicit the factory being used - * @param Base - polymorphic type indicating base class - * @param class_name - the name of the concrete plugin class we want to instantiate - * @param library_path - the library from which we want to create the plugin - * @return A unique pointer to newly created plugin - */ - template - ClassLoader::UniquePtr - createUniqueInstance(const std::string& class_name, const std::string& library_path) - { - ClassLoader* loader = getClassLoaderForLibrary(library_path); - if (loader == nullptr) { - throw class_loader::NoClassLoaderExistsException( - "Could not create instance as there is no ClassLoader in " - "MultiLibraryClassLoader bound to library " + library_path + - " Ensure you called MultiLibraryClassLoader::loadLibrary()"); - } - return loader->createUniqueInstance(class_name); + /** + * @brief Creates an instance of an object of given class name with ancestor class Base + * This version takes a specific library to make explicit the factory being used + * @param Base - polymorphic type indicating base class + * @param class_name - the name of the concrete plugin class we want to instantiate + * @param library_path - the library from which we want to create the plugin + * @return A unique pointer to newly created plugin + */ + template + ClassLoader::UniquePtr + createUniqueInstance(const std::string & class_name, const std::string & library_path) + { + ClassLoader * loader = getClassLoaderForLibrary(library_path); + if (loader == nullptr) { + throw class_loader::NoClassLoaderExistsException( + "Could not create instance as there is no ClassLoader in " + "MultiLibraryClassLoader bound to library " + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); } + return loader->createUniqueInstance(class_name); + } #endif - /** - * @brief Creates an instance of an object of given class name with ancestor class Base - * This version does not look in a specific library for the factory, but rather the first open library that defines the classs - * This version should not be used as the plugin system cannot do automated safe loading/unloadings - * @param Base - polymorphic type indicating base class - * @param class_name - the name of the concrete plugin class we want to instantiate - * @return An unmanaged Base* to newly created plugin - */ - template - Base* createUnmanagedInstance(const std::string& class_name) - { - ClassLoader* loader = getClassLoaderForClass(class_name); - if (loader == NULL) - throw class_loader::CreateClassException( - "MultiLibraryClassLoader: Could not create class of type " + class_name); - return loader->createUnmanagedInstance(class_name); + /** + * @brief Creates an instance of an object of given class name with ancestor class Base + * This version does not look in a specific library for the factory, but rather the first open library that defines the classs + * This version should not be used as the plugin system cannot do automated safe loading/unloadings + * @param Base - polymorphic type indicating base class + * @param class_name - the name of the concrete plugin class we want to instantiate + * @return An unmanaged Base* to newly created plugin + */ + template + Base * createUnmanagedInstance(const std::string & class_name) + { + ClassLoader * loader = getClassLoaderForClass(class_name); + if (loader == NULL) { + throw class_loader::CreateClassException( + "MultiLibraryClassLoader: Could not create class of type " + class_name); } + return loader->createUnmanagedInstance(class_name); + } - /** - * @brief Creates an instance of an object of given class name with ancestor class Base - * This version takes a specific library to make explicit the factory being used - * This version should not be used as the plugin system cannot do automated safe loading/unloadings - * @param Base - polymorphic type indicating Base class - * @param class_name - name of class for which we want to create instance - * @param library_path - the fully qualified path to the runtime library - */ - template - Base* createUnmanagedInstance(const std::string& class_name, const std::string& library_path) - { - ClassLoader* loader = getClassLoaderForLibrary(library_path); - if (loader == NULL) { - throw class_loader::NoClassLoaderExistsException( - "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader " - "bound to library " + library_path + - " Ensure you called MultiLibraryClassLoader::loadLibrary()"); - } - return loader->createUnmanagedInstance(class_name); + /** + * @brief Creates an instance of an object of given class name with ancestor class Base + * This version takes a specific library to make explicit the factory being used + * This version should not be used as the plugin system cannot do automated safe loading/unloadings + * @param Base - polymorphic type indicating Base class + * @param class_name - name of class for which we want to create instance + * @param library_path - the fully qualified path to the runtime library + */ + template + Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path) + { + ClassLoader * loader = getClassLoaderForLibrary(library_path); + if (loader == NULL) { + throw class_loader::NoClassLoaderExistsException( + "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader " + "bound to library " + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); } + return loader->createUnmanagedInstance(class_name); + } - /** - * @brief Indicates if a class has been loaded and can be instantiated - * @param Base - polymorphic type indicating Base class - * @param class_name - name of class that is be inquired about - * @return true if loaded, false otherwise - */ - template - bool isClassAvailable(const std::string& class_name) - { - std::vector available_classes = getAvailableClasses(); - return(available_classes.end() != std::find( - available_classes.begin(), available_classes.end(), class_name)); - } + /** + * @brief Indicates if a class has been loaded and can be instantiated + * @param Base - polymorphic type indicating Base class + * @param class_name - name of class that is be inquired about + * @return true if loaded, false otherwise + */ + template + bool isClassAvailable(const std::string & class_name) + { + std::vector available_classes = getAvailableClasses(); + return available_classes.end() != std::find( + available_classes.begin(), available_classes.end(), class_name); + } - /** - * @brief Indicates if a library has been loaded into memory - * @param library_path - The full qualified path to the runtime library - * @return true if library is loaded, false otherwise - */ - bool isLibraryAvailable(const std::string& library_path); + /** + * @brief Indicates if a library has been loaded into memory + * @param library_path - The full qualified path to the runtime library + * @return true if library is loaded, false otherwise + */ + bool isLibraryAvailable(const std::string & library_path); - /** - * @brief Gets a list of all classes that are loaded by the class loader - * @param Base - polymorphic type indicating Base class - * @return A vector of the available classes - */ - template - std::vector getAvailableClasses() - { - std::vector available_classes; - ClassLoaderVector loaders = getAllAvailableClassLoaders(); - for(unsigned int c = 0; c < loaders.size(); c++) - { - ClassLoader* current = loaders.at(c); - std::vector loader_classes = current->getAvailableClasses(); - available_classes.insert( - available_classes.end(), loader_classes.begin(), loader_classes.end()); - } - return(available_classes); + /** + * @brief Gets a list of all classes that are loaded by the class loader + * @param Base - polymorphic type indicating Base class + * @return A vector of the available classes + */ + template + std::vector getAvailableClasses() + { + std::vector available_classes; + ClassLoaderVector loaders = getAllAvailableClassLoaders(); + for (unsigned int c = 0; c < loaders.size(); c++) { + ClassLoader * current = loaders.at(c); + std::vector loader_classes = current->getAvailableClasses(); + available_classes.insert( + available_classes.end(), loader_classes.begin(), loader_classes.end()); } + return available_classes; + } - /** - * @brief Gets a list of all classes loaded for a particular library - * @param Base - polymorphic type indicating Base class - * @return A vector of the available classes in the passed library - */ - template - std::vector getAvailableClassesForLibrary(const std::string& library_path) - { - ClassLoader* loader = getClassLoaderForLibrary(library_path); - std::vector available_classes; - if(loader) - { - available_classes = loader->getAvailableClasses(); - return(available_classes); - } else { - throw class_loader::NoClassLoaderExistsException( - "There is no ClassLoader in MultiLibraryClassLoader bound to library " + library_path + - " Ensure you called MultiLibraryClassLoader::loadLibrary()"); - } + /** + * @brief Gets a list of all classes loaded for a particular library + * @param Base - polymorphic type indicating Base class + * @return A vector of the available classes in the passed library + */ + template + std::vector getAvailableClassesForLibrary(const std::string & library_path) + { + ClassLoader * loader = getClassLoaderForLibrary(library_path); + std::vector available_classes; + if (loader) { + available_classes = loader->getAvailableClasses(); + return available_classes; + } else { + throw class_loader::NoClassLoaderExistsException( + "There is no ClassLoader in MultiLibraryClassLoader bound to library " + + library_path + + " Ensure you called MultiLibraryClassLoader::loadLibrary()"); } + } - /** - * @brief Gets a list of all libraries opened by this class loader - @ @return A list of libraries opened by this class loader - */ - std::vector getRegisteredLibraries(); - - /** - * @brief Loads a library into memory for this class loader - * @param library_path - the fully qualified path to the runtime library - */ - void loadLibrary(const std::string& library_path); + /** + * @brief Gets a list of all libraries opened by this class loader + @ @return A list of libraries opened by this class loader + */ + std::vector getRegisteredLibraries(); - /** - * @brief Unloads a library for this class loader - * @param library_path - the fully qualified path to the runtime library - */ - int unloadLibrary(const std::string& library_path); + /** + * @brief Loads a library into memory for this class loader + * @param library_path - the fully qualified path to the runtime library + */ + void loadLibrary(const std::string & library_path); + /** + * @brief Unloads a library for this class loader + * @param library_path - the fully qualified path to the runtime library + */ + int unloadLibrary(const std::string & library_path); - private: - /** - * @brief Indicates if on-demand (lazy) load/unload is enabled so libraries are loaded/unloaded automatically as needed - */ - bool isOnDemandLoadUnloadEnabled(){return(enable_ondemand_loadunload_);} +private: + /** + * @brief Indicates if on-demand (lazy) load/unload is enabled so libraries are loaded/unloaded automatically as needed + */ + bool isOnDemandLoadUnloadEnabled() {return enable_ondemand_loadunload_;} - /** - * @brief Gets a handle to the class loader corresponding to a specific runtime library - * @param library_path - the library from which we want to create the plugin - * @return A pointer to the ClassLoader*, == NULL if not found - */ - ClassLoader* getClassLoaderForLibrary(const std::string& library_path); + /** + * @brief Gets a handle to the class loader corresponding to a specific runtime library + * @param library_path - the library from which we want to create the plugin + * @return A pointer to the ClassLoader*, == NULL if not found + */ + ClassLoader * getClassLoaderForLibrary(const std::string & library_path); - /** - * @brief Gets a handle to the class loader corresponding to a specific class - * @param class_name - name of class for which we want to create instance - * @return A pointer to the ClassLoader*, == NULL if not found - */ - template - ClassLoader* getClassLoaderForClass(const std::string& class_name) - { - ClassLoaderVector loaders = getAllAvailableClassLoaders(); - for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) - { - if (!(*i)->isLibraryLoaded()) - (*i)->loadLibrary(); - if ((*i)->isClassAvailable(class_name)) - return *i; + /** + * @brief Gets a handle to the class loader corresponding to a specific class + * @param class_name - name of class for which we want to create instance + * @return A pointer to the ClassLoader*, == NULL if not found + */ + template + ClassLoader * getClassLoaderForClass(const std::string & class_name) + { + ClassLoaderVector loaders = getAllAvailableClassLoaders(); + for (ClassLoaderVector::iterator i = loaders.begin(); i != loaders.end(); ++i) { + if (!(*i)->isLibraryLoaded()) { + (*i)->loadLibrary(); + } + if ((*i)->isClassAvailable(class_name)) { + return *i; } - return NULL; } + return NULL; + } - /** - * @brief Gets all class loaders loaded within scope - */ - ClassLoaderVector getAllAvailableClassLoaders(); + /** + * @brief Gets all class loaders loaded within scope + */ + ClassLoaderVector getAllAvailableClassLoaders(); - /** - * @brief Destroys all ClassLoaders - */ - void shutdownAllClassLoaders(); + /** + * @brief Destroys all ClassLoaders + */ + void shutdownAllClassLoaders(); - private: - bool enable_ondemand_loadunload_; - LibraryToClassLoaderMap active_class_loaders_; - boost::mutex loader_mutex_; +private: + bool enable_ondemand_loadunload_; + LibraryToClassLoaderMap active_class_loaders_; + boost::mutex loader_mutex_; }; diff --git a/src/class_loader.cpp b/src/class_loader.cpp index 0ca6f373..2581aac4 100644 --- a/src/class_loader.cpp +++ b/src/class_loader.cpp @@ -43,21 +43,22 @@ bool ClassLoader::hasUnmanagedInstanceBeenCreated() std::string systemLibrarySuffix() { - return(Poco::SharedLibrary::suffix()); + return Poco::SharedLibrary::suffix(); } -ClassLoader::ClassLoader(const std::string& library_path, bool ondemand_load_unload) : -ondemand_load_unload_(ondemand_load_unload), -library_path_(library_path), -load_ref_count_(0), -plugin_ref_count_(0) +ClassLoader::ClassLoader(const std::string & library_path, bool ondemand_load_unload) +: ondemand_load_unload_(ondemand_load_unload), + library_path_(library_path), + load_ref_count_(0), + plugin_ref_count_(0) { CONSOLE_BRIDGE_logDebug( "class_loader.ClassLoader: " "Constructing new ClassLoader (%p) bound to library %s.", this, library_path.c_str()); - if(!isOnDemandLoadUnloadEnabled()) + if (!isOnDemandLoadUnloadEnabled()) { loadLibrary(); + } } ClassLoader::~ClassLoader() @@ -70,12 +71,12 @@ ClassLoader::~ClassLoader() bool ClassLoader::isLibraryLoaded() { - return(class_loader::class_loader_private::isLibraryLoaded(getLibraryPath(), this)); + return class_loader::class_loader_private::isLibraryLoaded(getLibraryPath(), this); } bool ClassLoader::isLibraryLoadedByAnyClassloader() { - return(class_loader::class_loader_private::isLibraryLoadedByAnybody(getLibraryPath())); + return class_loader::class_loader_private::isLibraryLoadedByAnybody(getLibraryPath()); } void ClassLoader::loadLibrary() @@ -87,32 +88,33 @@ void ClassLoader::loadLibrary() int ClassLoader::unloadLibrary() { - return(unloadLibraryInternal(true)); + return unloadLibraryInternal(true); } int ClassLoader::unloadLibraryInternal(bool lock_plugin_ref_count) { boost::recursive_mutex::scoped_lock load_ref_lock(load_ref_count_mutex_); boost::recursive_mutex::scoped_lock plugin_ref_lock; - if(lock_plugin_ref_count) + if (lock_plugin_ref_count) { plugin_ref_lock = boost::recursive_mutex::scoped_lock(plugin_ref_count_mutex_); + } - if(plugin_ref_count_ > 0) + if (plugin_ref_count_ > 0) { CONSOLE_BRIDGE_logWarn( "class_loader.ClassLoader: " "SEVERE WARNING!!! Attempting to unload library while objects created by this loader " "exist in the heap! " "You should delete your objects before attempting to unload the library or " "destroying the ClassLoader. The library will NOT be unloaded."); - else - { + } else { load_ref_count_ = load_ref_count_ - 1; - if(load_ref_count_ == 0) + if (load_ref_count_ == 0) { class_loader::class_loader_private::unloadLibrary(getLibraryPath(), this); - else if(load_ref_count_ < 0) + } else if (load_ref_count_ < 0) { load_ref_count_ = 0; + } } - return(load_ref_count_); + return load_ref_count_; } } // namespace class_loader diff --git a/src/class_loader_core.cpp b/src/class_loader_core.cpp index 2b58cd28..c83df190 100644 --- a/src/class_loader_core.cpp +++ b/src/class_loader_core.cpp @@ -44,53 +44,54 @@ namespace class_loader_private /*****************************************************************************/ /*****************************************************************************/ -boost::recursive_mutex& getLoadedLibraryVectorMutex() +boost::recursive_mutex & getLoadedLibraryVectorMutex() /*****************************************************************************/ { static boost::recursive_mutex m; return m; } -boost::recursive_mutex& getPluginBaseToFactoryMapMapMutex() +boost::recursive_mutex & getPluginBaseToFactoryMapMapMutex() /*****************************************************************************/ { static boost::recursive_mutex m; return m; } -BaseToFactoryMapMap& getGlobalPluginBaseToFactoryMapMap() +BaseToFactoryMapMap & getGlobalPluginBaseToFactoryMapMap() /*****************************************************************************/ { static BaseToFactoryMapMap instance; return instance; } -FactoryMap& getFactoryMapForBaseClass(const std::string& typeid_base_class_name) +FactoryMap & getFactoryMapForBaseClass(const std::string & typeid_base_class_name) /*****************************************************************************/ { - BaseToFactoryMapMap& factoryMapMap = getGlobalPluginBaseToFactoryMapMap(); + BaseToFactoryMapMap & factoryMapMap = getGlobalPluginBaseToFactoryMapMap(); std::string base_class_name = typeid_base_class_name; - if(factoryMapMap.find(base_class_name) == factoryMapMap.end()) + if (factoryMapMap.find(base_class_name) == factoryMapMap.end()) { factoryMapMap[base_class_name] = FactoryMap(); + } - return(factoryMapMap[base_class_name]); + return factoryMapMap[base_class_name]; } -MetaObjectVector& getMetaObjectGraveyard() +MetaObjectVector & getMetaObjectGraveyard() /*****************************************************************************/ { static MetaObjectVector instance; return instance; } -LibraryVector& getLoadedLibraryVector() +LibraryVector & getLoadedLibraryVector() /*****************************************************************************/ { static LibraryVector instance; return instance; } -std::string& getCurrentlyLoadingLibraryNameReference() +std::string & getCurrentlyLoadingLibraryNameReference() /*****************************************************************************/ { static std::string library_name; @@ -100,37 +101,37 @@ std::string& getCurrentlyLoadingLibraryNameReference() std::string getCurrentlyLoadingLibraryName() /*****************************************************************************/ { - return(getCurrentlyLoadingLibraryNameReference()); + return getCurrentlyLoadingLibraryNameReference(); } -void setCurrentlyLoadingLibraryName(const std::string& library_name) +void setCurrentlyLoadingLibraryName(const std::string & library_name) /*****************************************************************************/ { - std::string& library_name_ref = getCurrentlyLoadingLibraryNameReference(); + std::string & library_name_ref = getCurrentlyLoadingLibraryNameReference(); library_name_ref = library_name; } -ClassLoader*& getCurrentlyActiveClassLoaderReference() +ClassLoader * & getCurrentlyActiveClassLoaderReference() /*****************************************************************************/ { - static ClassLoader* loader = NULL; - return(loader); + static ClassLoader * loader = NULL; + return loader; } -ClassLoader* getCurrentlyActiveClassLoader() +ClassLoader * getCurrentlyActiveClassLoader() /*****************************************************************************/ { - return(getCurrentlyActiveClassLoaderReference()); + return getCurrentlyActiveClassLoaderReference(); } -void setCurrentlyActiveClassLoader(ClassLoader* loader) +void setCurrentlyActiveClassLoader(ClassLoader * loader) /*****************************************************************************/ { - ClassLoader*& loader_ref = getCurrentlyActiveClassLoaderReference(); + ClassLoader * & loader_ref = getCurrentlyActiveClassLoaderReference(); loader_ref = loader; } -bool& hasANonPurePluginLibraryBeenOpenedReference() +bool & hasANonPurePluginLibraryBeenOpenedReference() /*****************************************************************************/ { static bool hasANonPurePluginLibraryBeenOpenedReference = false; @@ -140,7 +141,7 @@ bool& hasANonPurePluginLibraryBeenOpenedReference() bool hasANonPurePluginLibraryBeenOpened() /*****************************************************************************/ { - return(hasANonPurePluginLibraryBeenOpenedReference()); + return hasANonPurePluginLibraryBeenOpenedReference(); } void hasANonPurePluginLibraryBeenOpened(bool hasIt) @@ -155,17 +156,18 @@ void hasANonPurePluginLibraryBeenOpened(bool hasIt) /*****************************************************************************/ /*****************************************************************************/ -MetaObjectVector allMetaObjects(const FactoryMap& factories) +MetaObjectVector allMetaObjects(const FactoryMap & factories) /*****************************************************************************/ { MetaObjectVector all_meta_objs; - for( + for ( FactoryMap::const_iterator factoryItr = factories.begin(); factoryItr != factories.end(); factoryItr++ - ) { - all_meta_objs.push_back(factoryItr->second); + ) + { + all_meta_objs.push_back(factoryItr->second); } - return(all_meta_objs); + return all_meta_objs; } MetaObjectVector allMetaObjects() @@ -174,62 +176,65 @@ MetaObjectVector allMetaObjects() boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex()); MetaObjectVector all_meta_objs; - BaseToFactoryMapMap& factory_map_map = getGlobalPluginBaseToFactoryMapMap(); + BaseToFactoryMapMap & factory_map_map = getGlobalPluginBaseToFactoryMapMap(); BaseToFactoryMapMap::iterator itr; - for(itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) - { + for (itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) { MetaObjectVector objs = allMetaObjects(itr->second); all_meta_objs.insert(all_meta_objs.end(), objs.begin(), objs.end()); } - return(all_meta_objs); + return all_meta_objs; } MetaObjectVector -filterAllMetaObjectsOwnedBy(const MetaObjectVector& to_filter, const ClassLoader* owner) +filterAllMetaObjectsOwnedBy(const MetaObjectVector & to_filter, const ClassLoader * owner) /*****************************************************************************/ { MetaObjectVector filtered_objs; - for(unsigned int c = 0; c < to_filter.size(); c++) - if(to_filter.at(c)->isOwnedBy(owner)) + for (unsigned int c = 0; c < to_filter.size(); c++) { + if (to_filter.at(c)->isOwnedBy(owner)) { filtered_objs.push_back(to_filter.at(c)); - return(filtered_objs); + } + } + return filtered_objs; } MetaObjectVector filterAllMetaObjectsAssociatedWithLibrary( - const MetaObjectVector& to_filter, const std::string& library_path) + const MetaObjectVector & to_filter, const std::string & library_path) /*****************************************************************************/ { MetaObjectVector filtered_objs; - for(unsigned int c = 0; c < to_filter.size(); c++) - if(to_filter.at(c)->getAssociatedLibraryPath() == library_path) + for (unsigned int c = 0; c < to_filter.size(); c++) { + if (to_filter.at(c)->getAssociatedLibraryPath() == library_path) { filtered_objs.push_back(to_filter.at(c)); - return(filtered_objs); + } + } + return filtered_objs; } MetaObjectVector -allMetaObjectsForClassLoader(const ClassLoader* owner) +allMetaObjectsForClassLoader(const ClassLoader * owner) /*****************************************************************************/ { - return(filterAllMetaObjectsOwnedBy(allMetaObjects(), owner)); + return filterAllMetaObjectsOwnedBy(allMetaObjects(), owner); } MetaObjectVector -allMetaObjectsForLibrary(const std::string& library_path) +allMetaObjectsForLibrary(const std::string & library_path) /*****************************************************************************/ { - return(filterAllMetaObjectsAssociatedWithLibrary(allMetaObjects(), library_path)); + return filterAllMetaObjectsAssociatedWithLibrary(allMetaObjects(), library_path); } MetaObjectVector -allMetaObjectsForLibraryOwnedBy(const std::string& library_path, const ClassLoader* owner) +allMetaObjectsForLibraryOwnedBy(const std::string & library_path, const ClassLoader * owner) /*****************************************************************************/ { - return(filterAllMetaObjectsOwnedBy(allMetaObjectsForLibrary(library_path), owner)); + return filterAllMetaObjectsOwnedBy(allMetaObjectsForLibrary(library_path), owner); } -void insertMetaObjectIntoGraveyard(AbstractMetaObjectBase* meta_obj) +void insertMetaObjectIntoGraveyard(AbstractMetaObjectBase * meta_obj) /*****************************************************************************/ { CONSOLE_BRIDGE_logDebug( @@ -240,18 +245,15 @@ void insertMetaObjectIntoGraveyard(AbstractMetaObjectBase* meta_obj) } void destroyMetaObjectsForLibrary( - const std::string& library_path, FactoryMap& factories, const ClassLoader* loader) + const std::string & library_path, FactoryMap & factories, const ClassLoader * loader) /*****************************************************************************/ { FactoryMap::iterator factory_itr = factories.begin(); - while(factory_itr != factories.end()) - { - AbstractMetaObjectBase* meta_obj = factory_itr->second; - if(meta_obj->getAssociatedLibraryPath() == library_path && meta_obj->isOwnedBy(loader)) - { + while (factory_itr != factories.end()) { + AbstractMetaObjectBase * meta_obj = factory_itr->second; + if (meta_obj->getAssociatedLibraryPath() == library_path && meta_obj->isOwnedBy(loader)) { meta_obj->removeOwningClassLoader(loader); - if(!meta_obj->isOwnedByAnybody()) - { + if (!meta_obj->isOwnedByAnybody()) { FactoryMap::iterator factory_itr_copy = factory_itr; factory_itr++; // TODO(mikaelarguedas) fix this when branching out for melodic @@ -277,7 +279,7 @@ void destroyMetaObjectsForLibrary( } } -void destroyMetaObjectsForLibrary(const std::string& library_path, const ClassLoader* loader) +void destroyMetaObjectsForLibrary(const std::string & library_path, const ClassLoader * loader) /*****************************************************************************/ { boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex()); @@ -289,55 +291,55 @@ void destroyMetaObjectsForLibrary(const std::string& library_path, const ClassLo library_path.c_str(), loader); // We have to walk through all FactoryMaps to be sure - BaseToFactoryMapMap& factory_map_map = getGlobalPluginBaseToFactoryMapMap(); + BaseToFactoryMapMap & factory_map_map = getGlobalPluginBaseToFactoryMapMap(); BaseToFactoryMapMap::iterator itr; - for(itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) + for (itr = factory_map_map.begin(); itr != factory_map_map.end(); itr++) { destroyMetaObjectsForLibrary(library_path, itr->second, loader); + } CONSOLE_BRIDGE_logDebug("class_loader.class_loader_private: Metaobjects removed."); } -bool areThereAnyExistingMetaObjectsForLibrary(const std::string& library_path) +bool areThereAnyExistingMetaObjectsForLibrary(const std::string & library_path) /*****************************************************************************/ { - return(allMetaObjectsForLibrary(library_path).size() > 0); + return allMetaObjectsForLibrary(library_path).size() > 0; } // Loaded Library Vector manipulation /*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/ -LibraryVector::iterator findLoadedLibrary(const std::string& library_path) +LibraryVector::iterator findLoadedLibrary(const std::string & library_path) /*****************************************************************************/ { - LibraryVector& open_libraries = getLoadedLibraryVector(); + LibraryVector & open_libraries = getLoadedLibraryVector(); LibraryVector::iterator itr; - for(itr = open_libraries.begin(); itr != open_libraries.end(); itr++ ) - { - if(itr->first == library_path) + for (itr = open_libraries.begin(); itr != open_libraries.end(); itr++) { + if (itr->first == library_path) { break; + } } - return(itr); + return itr; } -bool isLibraryLoadedByAnybody(const std::string& library_path) +bool isLibraryLoadedByAnybody(const std::string & library_path) /*****************************************************************************/ { boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex()); - LibraryVector& open_libraries = getLoadedLibraryVector(); + LibraryVector & open_libraries = getLoadedLibraryVector(); LibraryVector::iterator itr = findLoadedLibrary(library_path); - if(itr != open_libraries.end()) - { + if (itr != open_libraries.end()) { assert(itr->second->isLoaded() == true); // Ensure Poco actually thinks the library is loaded - return(true); + return true; } else { - return(false); + return false; } -}; +} -bool isLibraryLoaded(const std::string& library_path, ClassLoader* loader) +bool isLibraryLoaded(const std::string & library_path, ClassLoader * loader) /*****************************************************************************/ { bool is_lib_loaded_by_anyone = isLibraryLoadedByAnybody(library_path); @@ -346,23 +348,23 @@ bool isLibraryLoaded(const std::string& library_path, ClassLoader* loader) allMetaObjectsForLibraryOwnedBy(library_path, loader).size(); bool are_meta_objs_bound_to_loader = (num_meta_objs_for_lib == 0) ? true : ( - num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib); + num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib); - return(is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader); + return is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader; } -std::vector getAllLibrariesUsedByClassLoader(const ClassLoader* loader) +std::vector getAllLibrariesUsedByClassLoader(const ClassLoader * loader) /*****************************************************************************/ { MetaObjectVector all_loader_meta_objs = allMetaObjectsForClassLoader(loader); std::vector all_libs; - for(unsigned int c = 0; c < all_loader_meta_objs.size(); c++) - { + for (unsigned int c = 0; c < all_loader_meta_objs.size(); c++) { std::string lib_path = all_loader_meta_objs.at(c)->getAssociatedLibraryPath(); - if(std::find(all_libs.begin(), all_libs.end(), lib_path) == all_libs.end()) + if (std::find(all_libs.begin(), all_libs.end(), lib_path) == all_libs.end()) { all_libs.push_back(lib_path); + } } - return(all_libs); + return all_libs; } @@ -372,13 +374,12 @@ std::vector getAllLibrariesUsedByClassLoader(const ClassLoader* loa /*****************************************************************************/ void addClassLoaderOwnerForAllExistingMetaObjectsForLibrary( - const std::string& library_path, ClassLoader* loader) + const std::string & library_path, ClassLoader * loader) /*****************************************************************************/ { MetaObjectVector all_meta_objs = allMetaObjectsForLibrary(library_path); - for(unsigned int c = 0; c < all_meta_objs.size(); c++) - { - AbstractMetaObjectBase* meta_obj = all_meta_objs.at(c); + for (unsigned int c = 0; c < all_meta_objs.size(); c++) { + AbstractMetaObjectBase * meta_obj = all_meta_objs.at(c); CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "Tagging existing MetaObject %p (base = %s, derived = %s) with " @@ -390,17 +391,15 @@ void addClassLoaderOwnerForAllExistingMetaObjectsForLibrary( } void revivePreviouslyCreateMetaobjectsFromGraveyard( - const std::string& library_path, ClassLoader* loader) + const std::string & library_path, ClassLoader * loader) /*****************************************************************************/ { boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex()); - MetaObjectVector& graveyard = getMetaObjectGraveyard(); + MetaObjectVector & graveyard = getMetaObjectGraveyard(); - for(MetaObjectVector::iterator itr = graveyard.begin(); itr != graveyard.end(); itr++) - { - AbstractMetaObjectBase* obj = *itr; - if(obj->getAssociatedLibraryPath() == library_path) - { + for (MetaObjectVector::iterator itr = graveyard.begin(); itr != graveyard.end(); itr++) { + AbstractMetaObjectBase * obj = *itr; + if (obj->getAssociatedLibraryPath() == library_path) { CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "Resurrected factory metaobject from graveyard, class = %s, base_class = %s ptr = %p..." @@ -410,28 +409,26 @@ void revivePreviouslyCreateMetaobjectsFromGraveyard( obj->addOwningClassLoader(loader); assert(obj->typeidBaseClassName() != "UNSET"); - FactoryMap& factory = getFactoryMapForBaseClass(obj->typeidBaseClassName()); + FactoryMap & factory = getFactoryMapForBaseClass(obj->typeidBaseClassName()); factory[obj->className()] = obj; } } } void purgeGraveyardOfMetaobjects( - const std::string& library_path, ClassLoader* loader, bool delete_objs) + const std::string & library_path, ClassLoader * loader, bool delete_objs) /*****************************************************************************/ { MetaObjectVector all_meta_objs = allMetaObjects(); // Note: Lock must happen after call to allMetaObjects as that will lock boost::recursive_mutex::scoped_lock b2fmm_lock(getPluginBaseToFactoryMapMapMutex()); - MetaObjectVector& graveyard = getMetaObjectGraveyard(); + MetaObjectVector & graveyard = getMetaObjectGraveyard(); MetaObjectVector::iterator itr = graveyard.begin(); - while(itr != graveyard.end()) - { - AbstractMetaObjectBase* obj = *itr; - if(obj->getAssociatedLibraryPath() == library_path) - { + while (itr != graveyard.end()) { + AbstractMetaObjectBase * obj = *itr; + if (obj->getAssociatedLibraryPath() == library_path) { CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "Purging factory metaobject from graveyard, class = %s, base_class = %s ptr = %p.." @@ -442,9 +439,8 @@ void purgeGraveyardOfMetaobjects( bool is_address_in_graveyard_same_as_global_factory_map = std::find(all_meta_objs.begin(), all_meta_objs.end(), *itr) != all_meta_objs.end(); itr = graveyard.erase(itr); - if(delete_objs) - { - if(is_address_in_graveyard_same_as_global_factory_map) { + if (delete_objs) { + if (is_address_in_graveyard_same_as_global_factory_map) { CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "Newly created metaobject factory in global factory map map has same address as " @@ -457,7 +453,7 @@ void purgeGraveyardOfMetaobjects( "in addition to purging it from graveyard.", obj, obj->className().c_str(), obj->baseClassName().c_str(), obj->getAssociatedLibraryPath().c_str()); - delete(obj); // Note: This is the only place where metaobjects can be destroyed + delete (obj); // Note: This is the only place where metaobjects can be destroyed } } } else { @@ -466,7 +462,7 @@ void purgeGraveyardOfMetaobjects( } } -void loadLibrary(const std::string& library_path, ClassLoader* loader) +void loadLibrary(const std::string & library_path, ClassLoader * loader) /*****************************************************************************/ { static boost::recursive_mutex loader_mutex; @@ -477,8 +473,7 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) boost::recursive_mutex::scoped_lock loader_lock(loader_mutex); // If it's already open, just update existing metaobjects to have an additional owner. - if(isLibraryLoadedByAnybody(library_path)) - { + if (isLibraryLoadedByAnybody(library_path)) { boost::recursive_mutex::scoped_lock lock(getPluginBaseToFactoryMapMapMutex()); CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " @@ -487,35 +482,28 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) return; } - Poco::SharedLibrary* library_handle = NULL; + Poco::SharedLibrary * library_handle = NULL; { - try - { + try { setCurrentlyActiveClassLoader(loader); setCurrentlyLoadingLibraryName(library_path); library_handle = new Poco::SharedLibrary(library_path); - } - catch(const Poco::LibraryLoadException& e) - { + } catch (const Poco::LibraryLoadException & e) { setCurrentlyLoadingLibraryName(""); setCurrentlyActiveClassLoader(NULL); throw(class_loader::LibraryLoadException( - "Could not load library (Poco exception = " + std::string(e.message()) + ")")); - } - catch(const Poco::LibraryAlreadyLoadedException& e) - { + "Could not load library (Poco exception = " + std::string(e.message()) + ")")); + } catch (const Poco::LibraryAlreadyLoadedException & e) { setCurrentlyLoadingLibraryName(""); setCurrentlyActiveClassLoader(NULL); throw(class_loader::LibraryLoadException( - "Library already loaded (Poco exception = " + std::string(e.message()) + ")")); - } - catch(const Poco::NotFoundException& e) - { + "Library already loaded (Poco exception = " + std::string(e.message()) + ")")); + } catch (const Poco::NotFoundException & e) { setCurrentlyLoadingLibraryName(""); setCurrentlyActiveClassLoader(NULL); throw(class_loader::LibraryLoadException( - "Library not found (Poco exception = " + std::string(e.message()) + ")")); + "Library not found (Poco exception = " + std::string(e.message()) + ")")); } setCurrentlyLoadingLibraryName(""); @@ -530,8 +518,7 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) // Graveyard scenario unsigned int num_lib_objs = allMetaObjectsForLibrary(library_path).size(); - if(num_lib_objs == 0) - { + if (num_lib_objs == 0) { CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "Though the library %s was just loaded, it seems no factory metaobjects were registered. " @@ -551,16 +538,15 @@ void loadLibrary(const std::string& library_path, ClassLoader* loader) // Insert library into global loaded library vectory boost::recursive_mutex::scoped_lock llv_lock(getLoadedLibraryVectorMutex()); - LibraryVector& open_libraries = getLoadedLibraryVector(); + LibraryVector & open_libraries = getLoadedLibraryVector(); // Note: Poco::SharedLibrary automatically calls load() when library passed to constructor open_libraries.push_back(LibraryPair(library_path, library_handle)); } -void unloadLibrary(const std::string& library_path, ClassLoader* loader) +void unloadLibrary(const std::string & library_path, ClassLoader * loader) /*****************************************************************************/ { - if(hasANonPurePluginLibraryBeenOpened()) - { + if (hasANonPurePluginLibraryBeenOpened()) { CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "Cannot unload %s or ANY other library as a non-pure plugin library was opened. " @@ -576,19 +562,16 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader) "Unloading library %s on behalf of ClassLoader %p...", library_path.c_str(), loader); boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex()); - LibraryVector& open_libraries = getLoadedLibraryVector(); + LibraryVector & open_libraries = getLoadedLibraryVector(); LibraryVector::iterator itr = findLoadedLibrary(library_path); - if(itr != open_libraries.end()) - { - Poco::SharedLibrary* library = itr->second; + if (itr != open_libraries.end()) { + Poco::SharedLibrary * library = itr->second; std::string library_path = itr->first; - try - { + try { destroyMetaObjectsForLibrary(library_path, loader); // Remove from loaded library list as well if no more factories associated with said library - if(!areThereAnyExistingMetaObjectsForLibrary(library_path)) - { + if (!areThereAnyExistingMetaObjectsForLibrary(library_path)) { CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "There are no more MetaObjects left for %s so unloading library and " @@ -596,7 +579,7 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader) library_path.c_str()); library->unload(); assert(library->isLoaded() == false); - delete(library); + delete (library); itr = open_libraries.erase(itr); } else { CONSOLE_BRIDGE_logDebug( @@ -606,16 +589,14 @@ void unloadLibrary(const std::string& library_path, ClassLoader* loader) library_path.c_str()); } return; - } - catch(const Poco::RuntimeException& e) - { - delete(library); + } catch (const Poco::RuntimeException & e) { + delete (library); throw(class_loader::LibraryUnloadException( - "Could not unload library (Poco exception = " + std::string(e.message()) + ")")); + "Could not unload library (Poco exception = " + std::string(e.message()) + ")")); } } throw(class_loader::LibraryUnloadException( - "Attempt to unload library that class_loader is unaware of.")); + "Attempt to unload library that class_loader is unaware of.")); } } @@ -636,26 +617,27 @@ void printDebugInfoToScreen() printf("--------------------------------------------------------------------------------\n"); boost::recursive_mutex::scoped_lock lock(getLoadedLibraryVectorMutex()); LibraryVector libs = getLoadedLibraryVector(); - for(unsigned int c = 0; c < libs.size(); c++) + for (unsigned int c = 0; c < libs.size(); c++) { printf( "Open library %i = %s (Poco SharedLibrary handle = %p)\n", c, (libs.at(c)).first.c_str(), (libs.at(c)).second); + } printf("METAOBJECTS (i.e. FACTORIES) IN MEMORY:\n"); printf("--------------------------------------------------------------------------------\n"); MetaObjectVector meta_objs = allMetaObjects(); - for(unsigned int c = 0; c < meta_objs.size(); c++) - { - AbstractMetaObjectBase* obj = meta_objs.at(c); + for (unsigned int c = 0; c < meta_objs.size(); c++) { + AbstractMetaObjectBase * obj = meta_objs.at(c); printf("Metaobject %i (ptr = %p):\n TypeId = %s\n Associated Library = %s\n", - c, - obj, - (typeid(*obj).name()), - obj->getAssociatedLibraryPath().c_str()); + c, + obj, + (typeid(*obj).name()), + obj->getAssociatedLibraryPath().c_str()); ClassLoaderVector loaders = obj->getAssociatedClassLoaders(); - for(unsigned int i = 0; i < loaders.size(); i++) + for (unsigned int i = 0; i < loaders.size(); i++) { printf(" Associated Loader %i = %p\n", i, loaders.at(i)); + } printf("--------------------------------------------------------------------------------\n"); } @@ -664,7 +646,5 @@ void printDebugInfoToScreen() } - - } // namespace class_loader_private } // namespace class_loader diff --git a/src/meta_object.cpp b/src/meta_object.cpp index db31480f..91a45909 100644 --- a/src/meta_object.cpp +++ b/src/meta_object.cpp @@ -38,11 +38,11 @@ namespace class_loader_private { AbstractMetaObjectBase::AbstractMetaObjectBase( - const std::string& class_name, const std::string& base_class_name) : -associated_library_path_("Unknown"), -base_class_name_(base_class_name), -class_name_(class_name), -typeid_base_class_name_("UNSET") + const std::string & class_name, const std::string & base_class_name) +: associated_library_path_("Unknown"), + base_class_name_(base_class_name), + class_name_(class_name), + typeid_base_class_name_("UNSET") /*****************************************************************************/ { CONSOLE_BRIDGE_logDebug( @@ -54,10 +54,10 @@ typeid_base_class_name_("UNSET") AbstractMetaObjectBase::~AbstractMetaObjectBase() /*****************************************************************************/ { - CONSOLE_BRIDGE_logDebug( - "class_loader.class_loader_private.AbstractMetaObjectBase: " - "Destroying MetaObject %p (base = %s, derived = %s, library path = %s)", - this, baseClassName().c_str(), className().c_str(), getAssociatedLibraryPath().c_str()); + CONSOLE_BRIDGE_logDebug( + "class_loader.class_loader_private.AbstractMetaObjectBase: " + "Destroying MetaObject %p (base = %s, derived = %s, library path = %s)", + this, baseClassName().c_str(), className().c_str(), getAssociatedLibraryPath().c_str()); } std::string AbstractMetaObjectBase::className() const @@ -81,7 +81,7 @@ std::string AbstractMetaObjectBase::typeidBaseClassName() const std::string AbstractMetaObjectBase::getAssociatedLibraryPath() /*****************************************************************************/ { - return(associated_library_path_); + return associated_library_path_; } void AbstractMetaObjectBase::setAssociatedLibraryPath(std::string library_path) @@ -90,41 +90,43 @@ void AbstractMetaObjectBase::setAssociatedLibraryPath(std::string library_path) associated_library_path_ = library_path; } -void AbstractMetaObjectBase::addOwningClassLoader(ClassLoader* loader) +void AbstractMetaObjectBase::addOwningClassLoader(ClassLoader * loader) /*****************************************************************************/ { - ClassLoaderVector& v = associated_class_loaders_; - if(std::find(v.begin(), v.end(), loader) == v.end()) + ClassLoaderVector & v = associated_class_loaders_; + if (std::find(v.begin(), v.end(), loader) == v.end()) { v.push_back(loader); + } } -void AbstractMetaObjectBase::removeOwningClassLoader(const ClassLoader* loader) +void AbstractMetaObjectBase::removeOwningClassLoader(const ClassLoader * loader) /*****************************************************************************/ { - ClassLoaderVector& v = associated_class_loaders_; + ClassLoaderVector & v = associated_class_loaders_; ClassLoaderVector::iterator itr = std::find(v.begin(), v.end(), loader); - if(itr != v.end()) + if (itr != v.end()) { v.erase(itr); + } } -bool AbstractMetaObjectBase::isOwnedBy(const ClassLoader* loader) +bool AbstractMetaObjectBase::isOwnedBy(const ClassLoader * loader) /*****************************************************************************/ { - ClassLoaderVector& v = associated_class_loaders_; + ClassLoaderVector & v = associated_class_loaders_; ClassLoaderVector::iterator itr = std::find(v.begin(), v.end(), loader); - return(itr != v.end()); + return itr != v.end(); } bool AbstractMetaObjectBase::isOwnedByAnybody() /*****************************************************************************/ { - return(associated_class_loaders_.size() > 0); + return associated_class_loaders_.size() > 0; } ClassLoaderVector AbstractMetaObjectBase::getAssociatedClassLoaders() /*****************************************************************************/ { - return(associated_class_loaders_); + return associated_class_loaders_; } } // namespace class_loader_private diff --git a/src/multi_library_class_loader.cpp b/src/multi_library_class_loader.cpp index 54027aac..4c4843cb 100644 --- a/src/multi_library_class_loader.cpp +++ b/src/multi_library_class_loader.cpp @@ -35,8 +35,8 @@ namespace class_loader { -MultiLibraryClassLoader::MultiLibraryClassLoader(bool enable_ondemand_loadunload) : -enable_ondemand_loadunload_(enable_ondemand_loadunload) +MultiLibraryClassLoader::MultiLibraryClassLoader(bool enable_ondemand_loadunload) +: enable_ondemand_loadunload_(enable_ondemand_loadunload) { } @@ -48,16 +48,16 @@ MultiLibraryClassLoader::~MultiLibraryClassLoader() std::vector MultiLibraryClassLoader::getRegisteredLibraries() { std::vector libraries; - for( + for ( LibraryToClassLoaderMap::iterator itr = active_class_loaders_.begin(); - itr != active_class_loaders_.end(); itr++ - ) { + itr != active_class_loaders_.end(); itr++) + { libraries.push_back(itr->first); } - return(libraries); + return libraries; } -ClassLoader* MultiLibraryClassLoader::getClassLoaderForLibrary(const std::string& library_path) +ClassLoader * MultiLibraryClassLoader::getClassLoaderForLibrary(const std::string & library_path) { LibraryToClassLoaderMap::iterator itr = active_class_loaders_.find(library_path); if (itr != active_class_loaders_.end()) { @@ -68,48 +68,48 @@ ClassLoader* MultiLibraryClassLoader::getClassLoaderForLibrary(const std::string ClassLoaderVector MultiLibraryClassLoader::getAllAvailableClassLoaders() { ClassLoaderVector loaders; - for( + for ( LibraryToClassLoaderMap::iterator itr = active_class_loaders_.begin(); - itr != active_class_loaders_.end(); itr++ - ) { + itr != active_class_loaders_.end(); itr++) + { loaders.push_back(itr->second); } - return(loaders); + return loaders; } -bool MultiLibraryClassLoader::isLibraryAvailable(const std::string& library_name) +bool MultiLibraryClassLoader::isLibraryAvailable(const std::string & library_name) { - return (getClassLoaderForLibrary(library_name) != NULL); + return getClassLoaderForLibrary(library_name) != NULL; } -void MultiLibraryClassLoader::loadLibrary(const std::string& library_path) +void MultiLibraryClassLoader::loadLibrary(const std::string & library_path) { - if(!isLibraryAvailable(library_path)) + if (!isLibraryAvailable(library_path)) { active_class_loaders_[library_path] = new class_loader::ClassLoader(library_path, isOnDemandLoadUnloadEnabled()); + } } void MultiLibraryClassLoader::shutdownAllClassLoaders() { std::vector available_libraries = getRegisteredLibraries(); - for(unsigned int c = 0; c < available_libraries.size(); c++) + for (unsigned int c = 0; c < available_libraries.size(); c++) { unloadLibrary(available_libraries.at(c)); + } } -int MultiLibraryClassLoader::unloadLibrary(const std::string& library_path) +int MultiLibraryClassLoader::unloadLibrary(const std::string & library_path) { int remaining_unloads = 0; LibraryToClassLoaderMap::iterator itr = active_class_loaders_.find(library_path); - if (itr != active_class_loaders_.end()) - { - ClassLoader* loader = itr->second; - if((remaining_unloads = loader->unloadLibrary()) == 0) - { - delete(loader); + if (itr != active_class_loaders_.end()) { + ClassLoader * loader = itr->second; + if ((remaining_unloads = loader->unloadLibrary()) == 0) { + delete (loader); active_class_loaders_.erase(itr); } } - return(remaining_unloads); + return remaining_unloads; } } // namespace class_loader diff --git a/test/base.h b/test/base.h index 73d611cc..1eaa19b7 100644 --- a/test/base.h +++ b/test/base.h @@ -32,8 +32,8 @@ class Base { - public: - virtual void saySomething() = 0; +public: + virtual void saySomething() = 0; }; #endif // BASE_H_ diff --git a/test/plugins1.cpp b/test/plugins1.cpp index 4770565a..8f1d6f3e 100644 --- a/test/plugins1.cpp +++ b/test/plugins1.cpp @@ -35,32 +35,32 @@ class Dog : public Base { - public: - virtual void saySomething(){std::cout << "Bark" << std::endl;} +public: + virtual void saySomething() {std::cout << "Bark" << std::endl;} }; class Cat : public Base { - public: - virtual void saySomething(){std::cout << "Meow" << std::endl;} +public: + virtual void saySomething() {std::cout << "Meow" << std::endl;} }; class Duck : public Base { - public: - virtual void saySomething(){std::cout << "Quack" << std::endl;} +public: + virtual void saySomething() {std::cout << "Quack" << std::endl;} }; class Cow : public Base { - public: - virtual void saySomething(){std::cout << "Moooo" << std::endl;} +public: + virtual void saySomething() {std::cout << "Moooo" << std::endl;} }; class Sheep : public Base { - public: - virtual void saySomething(){std::cout << "Baaah" << std::endl;} +public: + virtual void saySomething() {std::cout << "Baaah" << std::endl;} }; CLASS_LOADER_REGISTER_CLASS(Dog, Base); diff --git a/test/plugins2.cpp b/test/plugins2.cpp index 0bf03f10..4b9153c8 100644 --- a/test/plugins2.cpp +++ b/test/plugins2.cpp @@ -35,26 +35,26 @@ class Robot : public Base { - public: - virtual void saySomething(){std::cout << "Beep boop" << std::endl;} +public: + virtual void saySomething() {std::cout << "Beep boop" << std::endl;} }; class Alien : public Base { - public: - virtual void saySomething(){std::cout << "Znornoff!!!" << std::endl;} +public: + virtual void saySomething() {std::cout << "Znornoff!!!" << std::endl;} }; class Monster : public Base { - public: - virtual void saySomething(){std::cout << "BEAAAHHHH" << std::endl;} +public: + virtual void saySomething() {std::cout << "BEAAAHHHH" << std::endl;} }; class Zombie : public Base { - public: - virtual void saySomething(){std::cout << "Brains!!!" << std::endl;} +public: + virtual void saySomething() {std::cout << "Brains!!!" << std::endl;} }; @@ -62,4 +62,3 @@ CLASS_LOADER_REGISTER_CLASS(Robot, Base); CLASS_LOADER_REGISTER_CLASS(Alien, Base); CLASS_LOADER_REGISTER_CLASS(Monster, Base); CLASS_LOADER_REGISTER_CLASS(Zombie, Base); - diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index 9185aced..257b5f70 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -47,25 +47,19 @@ const char LIBRARY_2[] = "libclass_loader_TestPlugins2.so"; using class_loader::ClassLoader; /*****************************************************************************/ -TEST(ClassLoaderUniquePtrTest, basicLoad) -{ - try - { +TEST(ClassLoaderUniquePtrTest, basicLoad) { + try { ClassLoader loader1(LIBRARY_1, false); loader1.createUniqueInstance("Cat")->saySomething(); // See if lazy load works SUCCEED(); - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; } } /*****************************************************************************/ -TEST(ClassLoaderUniquePtrTest, correctLazyLoadUnload) -{ - try - { +TEST(ClassLoaderUniquePtrTest, correctLazyLoadUnload) { + try { ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); ClassLoader loader1(LIBRARY_1, true); ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); @@ -80,38 +74,29 @@ TEST(ClassLoaderUniquePtrTest, correctLazyLoadUnload) // The library will unload automatically when the only plugin object left is destroyed ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); return; - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; - } - catch(...) - { + } catch (...) { FAIL() << "Unhandled exception"; } } /*****************************************************************************/ -TEST(ClassLoaderUniquePtrTest, nonExistentPlugin) -{ +TEST(ClassLoaderUniquePtrTest, nonExistentPlugin) { ClassLoader loader1(LIBRARY_1, false); - try - { + try { ClassLoader::UniquePtr obj = loader1.createUniqueInstance("Bear"); - if(obj == NULL) + if (obj == NULL) { FAIL() << "Null object being returned instead of exception thrown."; + } obj->saySomething(); - } - catch(const class_loader::CreateClassException& e) - { + } catch (const class_loader::CreateClassException & e) { SUCCEED(); return; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception caught.\n"; } @@ -125,42 +110,37 @@ void wait(int seconds) boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } -void run(ClassLoader* loader) +void run(ClassLoader * loader) { std::vector classes = loader->getAvailableClasses(); - for(unsigned int c = 0; c < classes.size(); c++) - { + for (unsigned int c = 0; c < classes.size(); c++) { loader->createUniqueInstance(classes.at(c))->saySomething(); } } -TEST(ClassLoaderUniquePtrTest, threadSafety) -{ +TEST(ClassLoaderUniquePtrTest, threadSafety) { ClassLoader loader1(LIBRARY_1); ASSERT_TRUE(loader1.isLibraryLoaded()); // Note: Hard to test thread safety to make sure memory isn't corrupted. // The hope is this test is hard enough that once in a while it'll segfault // or something if there's some implementation error. - try - { + try { std::vector client_threads; - for(unsigned int c = 0; c < 1000; c++) + for (unsigned int c = 0; c < 1000; c++) { client_threads.emplace_back(std::bind(&run, &loader1)); + } - for(unsigned int c = 0; c < client_threads.size(); c++) + for (unsigned int c = 0; c < client_threads.size(); c++) { client_threads.at(c).join(); + } loader1.unloadLibrary(); ASSERT_FALSE(loader1.isLibraryLoaded()); - } - catch(const class_loader::ClassLoaderException& ex) - { + } catch (const class_loader::ClassLoaderException & ex) { FAIL() << "Unexpected ClassLoaderException."; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception."; } } @@ -168,10 +148,8 @@ TEST(ClassLoaderUniquePtrTest, threadSafety) /*****************************************************************************/ -TEST(ClassLoaderUniquePtrTest, loadRefCountingLazy) -{ - try - { +TEST(ClassLoaderUniquePtrTest, loadRefCountingLazy) { + try { ClassLoader loader1(LIBRARY_1, true); ASSERT_FALSE(loader1.isLibraryLoaded()); @@ -201,13 +179,9 @@ TEST(ClassLoaderUniquePtrTest, loadRefCountingLazy) ASSERT_TRUE(loader1.isLibraryLoaded()); return; - } - catch(const class_loader::ClassLoaderException& e) - { + } catch (const class_loader::ClassLoaderException & e) { FAIL() << "Unexpected exception.\n"; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception caught.\n"; } @@ -219,41 +193,33 @@ TEST(ClassLoaderUniquePtrTest, loadRefCountingLazy) void testMultiClassLoader(bool lazy) { - try - { + try { class_loader::MultiLibraryClassLoader loader(lazy); loader.loadLibrary(LIBRARY_1); loader.loadLibrary(LIBRARY_2); - for (int i=0; i < 2; ++i) { + for (int i = 0; i < 2; ++i) { loader.createUniqueInstance("Cat")->saySomething(); loader.createUniqueInstance("Dog")->saySomething(); loader.createUniqueInstance("Robot")->saySomething(); } - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; } SUCCEED(); } -TEST(MultiClassLoaderUniquePtrTest, lazyLoad) -{ +TEST(MultiClassLoaderUniquePtrTest, lazyLoad) { testMultiClassLoader(true); } -TEST(MultiClassLoaderUniquePtrTest, lazyLoadSecondTime) -{ +TEST(MultiClassLoaderUniquePtrTest, lazyLoadSecondTime) { testMultiClassLoader(true); } -TEST(MultiClassLoaderUniquePtrTest, nonLazyLoad) -{ +TEST(MultiClassLoaderUniquePtrTest, nonLazyLoad) { testMultiClassLoader(false); } -TEST(MultiClassLoaderUniquePtrTest, noWarningOnLazyLoad) -{ - try - { +TEST(MultiClassLoaderUniquePtrTest, noWarningOnLazyLoad) { + try { ClassLoader::UniquePtr cat = nullptr, dog = nullptr, rob = nullptr; { class_loader::MultiLibraryClassLoader loader(true); @@ -267,9 +233,7 @@ TEST(MultiClassLoaderUniquePtrTest, noWarningOnLazyLoad) cat->saySomething(); dog->saySomething(); rob->saySomething(); - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; } @@ -279,9 +243,8 @@ TEST(MultiClassLoaderUniquePtrTest, noWarningOnLazyLoad) /*****************************************************************************/ // Run all the tests that were declared with TEST() -int main(int argc, char **argv){ +int main(int argc, char ** argv) +{ testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } - - diff --git a/test/utest.cpp b/test/utest.cpp index bbd141e7..63adb8dc 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -44,15 +44,11 @@ const char LIBRARY_1[] = "libclass_loader_TestPlugins1.so"; const char LIBRARY_2[] = "libclass_loader_TestPlugins2.so"; /*****************************************************************************/ -TEST(ClassLoaderTest, basicLoad) -{ - try - { +TEST(ClassLoaderTest, basicLoad) { + try { class_loader::ClassLoader loader1(LIBRARY_1, false); loader1.createInstance("Cat")->saySomething(); // See if lazy load works - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; } @@ -60,11 +56,9 @@ TEST(ClassLoaderTest, basicLoad) } /*****************************************************************************/ -TEST(ClassLoaderTest, correctNonLazyLoadUnload) -{ - try - { - ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); +TEST(ClassLoaderTest, correctNonLazyLoadUnload) { + try { + ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); class_loader::ClassLoader loader1(LIBRARY_1, false); ASSERT_TRUE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); ASSERT_TRUE(loader1.isLibraryLoaded()); @@ -72,22 +66,16 @@ TEST(ClassLoaderTest, correctNonLazyLoadUnload) ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); ASSERT_FALSE(loader1.isLibraryLoaded()); return; - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; - } - catch(...) - { + } catch (...) { FAIL() << "Unhandled exception"; } } /*****************************************************************************/ -TEST(ClassLoaderTest, correctLazyLoadUnload) -{ - try - { +TEST(ClassLoaderTest, correctLazyLoadUnload) { + try { ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); class_loader::ClassLoader loader1(LIBRARY_1, true); ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); @@ -102,38 +90,29 @@ TEST(ClassLoaderTest, correctLazyLoadUnload) // The library will unload automatically when the only plugin object left is destroyed ASSERT_FALSE(class_loader::class_loader_private::isLibraryLoadedByAnybody(LIBRARY_1)); return; - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; - } - catch(...) - { + } catch (...) { FAIL() << "Unhandled exception"; } } /*****************************************************************************/ -TEST(ClassLoaderTest, nonExistentPlugin) -{ +TEST(ClassLoaderTest, nonExistentPlugin) { class_loader::ClassLoader loader1(LIBRARY_1, false); - try - { + try { boost::shared_ptr obj = loader1.createInstance("Bear"); - if(obj == NULL) + if (obj == NULL) { FAIL() << "Null object being returned instead of exception thrown."; + } obj->saySomething(); - } - catch(const class_loader::CreateClassException& e) - { + } catch (const class_loader::CreateClassException & e) { SUCCEED(); return; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception caught.\n"; } @@ -141,19 +120,13 @@ TEST(ClassLoaderTest, nonExistentPlugin) } /*****************************************************************************/ -TEST(ClassLoaderTest, nonExistentLibrary) -{ - try - { +TEST(ClassLoaderTest, nonExistentLibrary) { + try { class_loader::ClassLoader loader1("libDoesNotExist.so", false); - } - catch(const class_loader::LibraryLoadException& e) - { + } catch (const class_loader::LibraryLoadException & e) { SUCCEED(); return; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception caught.\n"; } @@ -166,27 +139,20 @@ class InvalidBase { }; -TEST(ClassLoaderTest, invalidBase) -{ - try - { +TEST(ClassLoaderTest, invalidBase) { + try { class_loader::ClassLoader loader1(LIBRARY_1, false); - if(loader1.isClassAvailable("Cat")) - { + if (loader1.isClassAvailable("Cat")) { FAIL() << "Cat should not be available for InvalidBase"; - } else if(loader1.isClassAvailable("Cat")) { + } else if (loader1.isClassAvailable("Cat")) { SUCCEED(); return; } else { FAIL() << "Class not available for correct base class."; } - } - catch(const class_loader::LibraryLoadException& e) - { + } catch (const class_loader::LibraryLoadException & e) { FAIL() << "Unexpected exception"; - } - catch(...) - { + } catch (...) { FAIL() << "Unexpected and unknown exception caught.\n"; } } @@ -198,55 +164,49 @@ void wait(int seconds) boost::this_thread::sleep(boost::posix_time::seconds(seconds)); } -void run(class_loader::ClassLoader* loader) +void run(class_loader::ClassLoader * loader) { std::vector classes = loader->getAvailableClasses(); - for(unsigned int c = 0; c < classes.size(); c++) - { + for (unsigned int c = 0; c < classes.size(); c++) { loader->createInstance(classes.at(c))->saySomething(); } } -TEST(ClassLoaderTest, threadSafety) -{ +TEST(ClassLoaderTest, threadSafety) { class_loader::ClassLoader loader1(LIBRARY_1); ASSERT_TRUE(loader1.isLibraryLoaded()); // Note: Hard to test thread safety to make sure memory isn't corrupted. // The hope is this test is hard enough that once in a while it'll segfault // or something if there's some implementation error. - try - { - std::vector client_threads; + try { + std::vector client_threads; - for(unsigned int c = 0; c < 1000; c++) + for (unsigned int c = 0; c < 1000; c++) { client_threads.push_back(new boost::thread(boost::bind(&run, &loader1))); + } - for(unsigned int c = 0; c < client_threads.size(); c++) + for (unsigned int c = 0; c < client_threads.size(); c++) { client_threads.at(c)->join(); + } - for(unsigned int c = 0; c < client_threads.size(); c++) - delete(client_threads.at(c)); + for (unsigned int c = 0; c < client_threads.size(); c++) { + delete (client_threads.at(c)); + } loader1.unloadLibrary(); ASSERT_FALSE(loader1.isLibraryLoaded()); - } - catch(const class_loader::ClassLoaderException& ex) - { + } catch (const class_loader::ClassLoaderException & ex) { FAIL() << "Unexpected ClassLoaderException."; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception."; } } /*****************************************************************************/ -TEST(ClassLoaderTest, loadRefCountingNonLazy) -{ - try - { +TEST(ClassLoaderTest, loadRefCountingNonLazy) { + try { class_loader::ClassLoader loader1(LIBRARY_1, false); ASSERT_TRUE(loader1.isLibraryLoaded()); @@ -270,13 +230,9 @@ TEST(ClassLoaderTest, loadRefCountingNonLazy) ASSERT_TRUE(loader1.isLibraryLoaded()); return; - } - catch(const class_loader::ClassLoaderException& e) - { + } catch (const class_loader::ClassLoaderException & e) { FAIL() << "Unexpected exception.\n"; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception caught.\n"; } @@ -285,10 +241,8 @@ TEST(ClassLoaderTest, loadRefCountingNonLazy) /*****************************************************************************/ -TEST(ClassLoaderTest, loadRefCountingLazy) -{ - try - { +TEST(ClassLoaderTest, loadRefCountingLazy) { + try { class_loader::ClassLoader loader1(LIBRARY_1, true); ASSERT_FALSE(loader1.isLibraryLoaded()); @@ -318,13 +272,9 @@ TEST(ClassLoaderTest, loadRefCountingLazy) ASSERT_TRUE(loader1.isLibraryLoaded()); return; - } - catch(const class_loader::ClassLoaderException& e) - { + } catch (const class_loader::ClassLoaderException & e) { FAIL() << "Unexpected exception.\n"; - } - catch(...) - { + } catch (...) { FAIL() << "Unknown exception caught.\n"; } @@ -336,41 +286,33 @@ TEST(ClassLoaderTest, loadRefCountingLazy) void testMultiClassLoader(bool lazy) { - try - { + try { class_loader::MultiLibraryClassLoader loader(lazy); loader.loadLibrary(LIBRARY_1); loader.loadLibrary(LIBRARY_2); - for (int i=0; i < 2; ++i) { + for (int i = 0; i < 2; ++i) { loader.createInstance("Cat")->saySomething(); loader.createInstance("Dog")->saySomething(); loader.createInstance("Robot")->saySomething(); } - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; } SUCCEED(); } -TEST(MultiClassLoaderTest, lazyLoad) -{ +TEST(MultiClassLoaderTest, lazyLoad) { testMultiClassLoader(true); } -TEST(MultiClassLoaderTest, lazyLoadSecondTime) -{ +TEST(MultiClassLoaderTest, lazyLoadSecondTime) { testMultiClassLoader(true); } -TEST(MultiClassLoaderTest, nonLazyLoad) -{ +TEST(MultiClassLoaderTest, nonLazyLoad) { testMultiClassLoader(false); } -TEST(MultiClassLoaderTest, noWarningOnLazyLoad) -{ - try - { +TEST(MultiClassLoaderTest, noWarningOnLazyLoad) { + try { boost::shared_ptr cat, dog, rob; { class_loader::MultiLibraryClassLoader loader(true); @@ -384,9 +326,7 @@ TEST(MultiClassLoaderTest, noWarningOnLazyLoad) cat->saySomething(); dog->saySomething(); rob->saySomething(); - } - catch(class_loader::ClassLoaderException& e) - { + } catch (class_loader::ClassLoaderException & e) { FAIL() << "ClassLoaderException: " << e.what() << "\n"; } @@ -396,9 +336,8 @@ TEST(MultiClassLoaderTest, noWarningOnLazyLoad) /*****************************************************************************/ // Run all the tests that were declared with TEST() -int main(int argc, char **argv){ +int main(int argc, char ** argv) +{ testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); } - - From f4d4c98c18c2899933308c8094673adada45cbdf Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 23:16:10 -0800 Subject: [PATCH 09/11] unused variables warnings --- test/unique_ptr_test.cpp | 6 +++--- test/utest.cpp | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index 257b5f70..28c477ff 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -93,7 +93,7 @@ TEST(ClassLoaderUniquePtrTest, nonExistentPlugin) { } obj->saySomething(); - } catch (const class_loader::CreateClassException & e) { + } catch (const class_loader::CreateClassException &) { SUCCEED(); return; } catch (...) { @@ -138,7 +138,7 @@ TEST(ClassLoaderUniquePtrTest, threadSafety) { loader1.unloadLibrary(); ASSERT_FALSE(loader1.isLibraryLoaded()); - } catch (const class_loader::ClassLoaderException & ex) { + } catch (const class_loader::ClassLoaderException &) { FAIL() << "Unexpected ClassLoaderException."; } catch (...) { FAIL() << "Unknown exception."; @@ -179,7 +179,7 @@ TEST(ClassLoaderUniquePtrTest, loadRefCountingLazy) { ASSERT_TRUE(loader1.isLibraryLoaded()); return; - } catch (const class_loader::ClassLoaderException & e) { + } catch (const class_loader::ClassLoaderException &) { FAIL() << "Unexpected exception.\n"; } catch (...) { FAIL() << "Unknown exception caught.\n"; diff --git a/test/utest.cpp b/test/utest.cpp index 63adb8dc..8d7c717e 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -109,7 +109,7 @@ TEST(ClassLoaderTest, nonExistentPlugin) { } obj->saySomething(); - } catch (const class_loader::CreateClassException & e) { + } catch (const class_loader::CreateClassException &) { SUCCEED(); return; } catch (...) { @@ -123,7 +123,7 @@ TEST(ClassLoaderTest, nonExistentPlugin) { TEST(ClassLoaderTest, nonExistentLibrary) { try { class_loader::ClassLoader loader1("libDoesNotExist.so", false); - } catch (const class_loader::LibraryLoadException & e) { + } catch (const class_loader::LibraryLoadException &) { SUCCEED(); return; } catch (...) { @@ -150,7 +150,7 @@ TEST(ClassLoaderTest, invalidBase) { } else { FAIL() << "Class not available for correct base class."; } - } catch (const class_loader::LibraryLoadException & e) { + } catch (const class_loader::LibraryLoadException &) { FAIL() << "Unexpected exception"; } catch (...) { FAIL() << "Unexpected and unknown exception caught.\n"; @@ -196,7 +196,7 @@ TEST(ClassLoaderTest, threadSafety) { loader1.unloadLibrary(); ASSERT_FALSE(loader1.isLibraryLoaded()); - } catch (const class_loader::ClassLoaderException & ex) { + } catch (const class_loader::ClassLoaderException &) { FAIL() << "Unexpected ClassLoaderException."; } catch (...) { FAIL() << "Unknown exception."; @@ -230,7 +230,7 @@ TEST(ClassLoaderTest, loadRefCountingNonLazy) { ASSERT_TRUE(loader1.isLibraryLoaded()); return; - } catch (const class_loader::ClassLoaderException & e) { + } catch (const class_loader::ClassLoaderException &) { FAIL() << "Unexpected exception.\n"; } catch (...) { FAIL() << "Unknown exception caught.\n"; @@ -272,7 +272,7 @@ TEST(ClassLoaderTest, loadRefCountingLazy) { ASSERT_TRUE(loader1.isLibraryLoaded()); return; - } catch (const class_loader::ClassLoaderException & e) { + } catch (const class_loader::ClassLoaderException &) { FAIL() << "Unexpected exception.\n"; } catch (...) { FAIL() << "Unknown exception caught.\n"; From eac8e466bd435905da09d0f435d132bcaf3d0b43 Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 23:29:35 -0800 Subject: [PATCH 10/11] litterals on left side of operator --- include/class_loader/class_loader.h | 2 +- include/class_loader/class_loader_core.h | 4 ++-- include/class_loader/multi_library_class_loader.h | 12 ++++++------ src/class_loader.cpp | 2 +- src/class_loader_core.cpp | 4 ++-- src/multi_library_class_loader.cpp | 2 +- test/unique_ptr_test.cpp | 2 +- test/utest.cpp | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/class_loader/class_loader.h b/include/class_loader/class_loader.h index fc06857d..d87ae6ca 100644 --- a/include/class_loader/class_loader.h +++ b/include/class_loader/class_loader.h @@ -216,7 +216,7 @@ class ClassLoader delete (obj); plugin_ref_count_ = plugin_ref_count_ - 1; assert(plugin_ref_count_ >= 0); - if (plugin_ref_count_ == 0 && isOnDemandLoadUnloadEnabled()) { + if (0 == plugin_ref_count_ && isOnDemandLoadUnloadEnabled()) { if (!ClassLoader::hasUnmanagedInstanceBeenCreated()) { unloadLibraryInternal(false); } else { diff --git a/include/class_loader/class_loader_core.h b/include/class_loader/class_loader_core.h index 0de7856f..df7d2cf2 100644 --- a/include/class_loader/class_loader_core.h +++ b/include/class_loader/class_loader_core.h @@ -168,7 +168,7 @@ void registerPlugin(const std::string & class_name, const std::string & base_cla class_name.c_str(), getCurrentlyActiveClassLoader(), getCurrentlyLoadingLibraryName().c_str()); - if (getCurrentlyActiveClassLoader() == NULL) { + if (NULL == getCurrentlyActiveClassLoader()) { CONSOLE_BRIDGE_logDebug( "class_loader.impl: ALERT!!! " "A library containing plugins has been opened through a means other than through the " @@ -246,7 +246,7 @@ Base * createInstance(const std::string & derived_class_name, ClassLoader * load obj = factory->create(); } - if (obj == NULL) { // Was never created + if (NULL == obj) { // Was never created if (factory && factory->isOwnedBy(NULL)) { CONSOLE_BRIDGE_logDebug( "class_loader.impl: ALERT!!! " diff --git a/include/class_loader/multi_library_class_loader.h b/include/class_loader/multi_library_class_loader.h index 255827ae..80536681 100644 --- a/include/class_loader/multi_library_class_loader.h +++ b/include/class_loader/multi_library_class_loader.h @@ -79,7 +79,7 @@ class MultiLibraryClassLoader "Attempting to create instance of class type %s.", class_name.c_str()); ClassLoader * loader = getClassLoaderForClass(class_name); - if (loader == NULL) { + if (NULL == loader) { throw class_loader::CreateClassException( "MultiLibraryClassLoader: Could not create object of class type " + class_name + @@ -103,7 +103,7 @@ class MultiLibraryClassLoader createInstance(const std::string & class_name, const std::string & library_path) { ClassLoader * loader = getClassLoaderForLibrary(library_path); - if (loader == NULL) { + if (NULL == loader) { throw class_loader::NoClassLoaderExistsException( "Could not create instance as there is no ClassLoader in " "MultiLibraryClassLoader bound to library " + library_path + @@ -127,7 +127,7 @@ class MultiLibraryClassLoader "class_loader::MultiLibraryClassLoader: Attempting to create instance of class type %s.", class_name.c_str()); ClassLoader * loader = getClassLoaderForClass(class_name); - if (loader == nullptr) { + if (nullptr == loader) { throw class_loader::CreateClassException( "MultiLibraryClassLoader: Could not create object of class type " + class_name + " as no factory exists for it. " @@ -150,7 +150,7 @@ class MultiLibraryClassLoader createUniqueInstance(const std::string & class_name, const std::string & library_path) { ClassLoader * loader = getClassLoaderForLibrary(library_path); - if (loader == nullptr) { + if (nullptr == loader) { throw class_loader::NoClassLoaderExistsException( "Could not create instance as there is no ClassLoader in " "MultiLibraryClassLoader bound to library " + library_path + @@ -172,7 +172,7 @@ class MultiLibraryClassLoader Base * createUnmanagedInstance(const std::string & class_name) { ClassLoader * loader = getClassLoaderForClass(class_name); - if (loader == NULL) { + if (NULL == loader) { throw class_loader::CreateClassException( "MultiLibraryClassLoader: Could not create class of type " + class_name); } @@ -191,7 +191,7 @@ class MultiLibraryClassLoader Base * createUnmanagedInstance(const std::string & class_name, const std::string & library_path) { ClassLoader * loader = getClassLoaderForLibrary(library_path); - if (loader == NULL) { + if (NULL == loader) { throw class_loader::NoClassLoaderExistsException( "Could not create instance as there is no ClassLoader in MultiLibraryClassLoader " "bound to library " + library_path + diff --git a/src/class_loader.cpp b/src/class_loader.cpp index 2581aac4..60860fab 100644 --- a/src/class_loader.cpp +++ b/src/class_loader.cpp @@ -108,7 +108,7 @@ int ClassLoader::unloadLibraryInternal(bool lock_plugin_ref_count) "destroying the ClassLoader. The library will NOT be unloaded."); } else { load_ref_count_ = load_ref_count_ - 1; - if (load_ref_count_ == 0) { + if (0 == load_ref_count_) { class_loader::class_loader_private::unloadLibrary(getLibraryPath(), this); } else if (load_ref_count_ < 0) { load_ref_count_ = 0; diff --git a/src/class_loader_core.cpp b/src/class_loader_core.cpp index c83df190..42aca289 100644 --- a/src/class_loader_core.cpp +++ b/src/class_loader_core.cpp @@ -347,7 +347,7 @@ bool isLibraryLoaded(const std::string & library_path, ClassLoader * loader) int num_meta_objs_for_lib_bound_to_loader = allMetaObjectsForLibraryOwnedBy(library_path, loader).size(); bool are_meta_objs_bound_to_loader = - (num_meta_objs_for_lib == 0) ? true : ( + (0 == num_meta_objs_for_lib) ? true : ( num_meta_objs_for_lib_bound_to_loader <= num_meta_objs_for_lib); return is_lib_loaded_by_anyone && are_meta_objs_bound_to_loader; @@ -518,7 +518,7 @@ void loadLibrary(const std::string & library_path, ClassLoader * loader) // Graveyard scenario unsigned int num_lib_objs = allMetaObjectsForLibrary(library_path).size(); - if (num_lib_objs == 0) { + if (0 == num_lib_objs) { CONSOLE_BRIDGE_logDebug( "class_loader.class_loader_private: " "Though the library %s was just loaded, it seems no factory metaobjects were registered. " diff --git a/src/multi_library_class_loader.cpp b/src/multi_library_class_loader.cpp index 4c4843cb..8cbfaa81 100644 --- a/src/multi_library_class_loader.cpp +++ b/src/multi_library_class_loader.cpp @@ -104,7 +104,7 @@ int MultiLibraryClassLoader::unloadLibrary(const std::string & library_path) LibraryToClassLoaderMap::iterator itr = active_class_loaders_.find(library_path); if (itr != active_class_loaders_.end()) { ClassLoader * loader = itr->second; - if ((remaining_unloads = loader->unloadLibrary()) == 0) { + if (0 == (remaining_unloads = loader->unloadLibrary())) { delete (loader); active_class_loaders_.erase(itr); } diff --git a/test/unique_ptr_test.cpp b/test/unique_ptr_test.cpp index 28c477ff..e4073d11 100644 --- a/test/unique_ptr_test.cpp +++ b/test/unique_ptr_test.cpp @@ -88,7 +88,7 @@ TEST(ClassLoaderUniquePtrTest, nonExistentPlugin) { try { ClassLoader::UniquePtr obj = loader1.createUniqueInstance("Bear"); - if (obj == NULL) { + if (nullptr == obj) { FAIL() << "Null object being returned instead of exception thrown."; } diff --git a/test/utest.cpp b/test/utest.cpp index 8d7c717e..256f934b 100644 --- a/test/utest.cpp +++ b/test/utest.cpp @@ -104,7 +104,7 @@ TEST(ClassLoaderTest, nonExistentPlugin) { try { boost::shared_ptr obj = loader1.createInstance("Bear"); - if (obj == NULL) { + if (NULL == obj) { FAIL() << "Null object being returned instead of exception thrown."; } From b27b9aaccf097761fc4ea04215f798b2ee93ea3c Mon Sep 17 00:00:00 2001 From: Mikael Arguedas Date: Sun, 12 Nov 2017 23:33:10 -0800 Subject: [PATCH 11/11] spurious temp file --- .swp | Bin 57344 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .swp diff --git a/.swp b/.swp deleted file mode 100644 index e915bc6a54ce68de9a2e48e84402534e35e60936..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 57344 zcmeHQe~cVe9bfsOl!EfZP>`0sUP%hM_U>kO_x5i4L+e$rK&iF`skPb6?oMxqo84Jv zW_!Jm${&aVMn%vdL5!ja#(z-2nvnQ|v|`X0Fw~$yOVA)9i6}9mV1l3To0;qEbauP9 zJ9G1v>?Plu-JRK)&wk%~-}n7|-}k*&9J_w&HkKR7r0{nR{d4~8EvZyhn^9EV`=s^J zxo+Kox+P^>Uo|*0(7-?g$!cK9b!k}|BMhsDR zKm!8}3^Xv%z@lovt}jj9f+wEsKJ{YvxcXhr3-^#Z%l&+rdtB}wz4J>0pQi)o&vf5k z=pMHR&M$G_uW*mkf%9j$?=NzXp9!3QPvHCmf%ETn-+#b89txa4-F?5(Jw6jSf13N= zd;V*I^QXG+huq^C0sVRU_4E|fulu#ZVW5G51_l}!Xkeg$fd&Q|7-(Rifq@1F8W?C` zpn+I4pp;Xob8+YU=HENlq(UPuMRzWwEvTBZMwUXW_tIZ$!uPBrZQyr<~rR-#$ zv7Hs8p_f@j*{?E%S#_nPvZ89ws%njmjxwcIW+kIqRckh5duA(|t@3L|-4Ct3Y)@uy zDps7C@xH*B8|w?017neC54=P)N66`{|ci4C{x43%$l=owaO|g**K=`v+>`sEBNnxG~yYuqMBzR)^05; zx%a@U`TMPP?lFQNS!`%}*)yI6!^C6aH*M+YDtT&)QBzsnG)k&vX|-tB2Ax`rZg>grJ4)b`^?V}O>8XIG!ief4yR9uVc2AX11iBnk@bhS2ZS5V|J zSy4imrg|wh!kp*`C32R8*5Md6Y>^R4Z;QxQrEAT(+y73j(43^#hgL6sUE27T1m6X%`qD_TLY!^K8v+$Z~Xd$;QXHk=l>7*{szdc z;QUX4?@N&Hfb%bd+zihD0yzH;$PsY<<&ZCf@1F*F1f2f|klP_QKvqHijTpesA@@P5 zkSWM{kiQ@%a0qfMWEbR8$eSLfU|eAEexQK`X<(OOD>_q6lZ?kcqE&e&XXMlre9~#d zoMUTzPN}UF*95LjhhJ&bRZ}5@6uiF0ooni>4*w^3wbbHry4LlTf?t`)h9mOgQo-wU zEgnJFE5VDU@OvM3)`MU0gYir(j5T;z@XCzu*4~w#F%Djv^Iz*DHnveVg4g;XhmxS+ z7yLkUbz0F8(yPyz+H}PZUOMi>(ae))D~es1Ga7}4bz-4TwEP;U*TJVqEguuSay%6U z+eIYP9&OP7ky5?h4Y6&$LtdJoZhCXM%vQU74BN0@rT%&onw-g;*BdsW8*Z&dbjaPs zQ-fe~L`dK`^hnaQ5BV`i1HZwn1WCJ^Prud52ea5Y|r z7Gg4P#KYnr)J?UdmMIiwL)S%cL> zk3Yv|D;PmV2$~GwNQLdwbc6~6J%3b1Ps0f9G}xYJ3!p{{VkP(ki2oDke~>s8_`jFm zz6t#Q74ZMRLe@a;MGW8R zz~x^Am){0Cgz^4QLUu#=^E%>jz1LK-Yu6g^uv{mfVW`DYrd5Xx!Yu7J8eY%tW&;rY zf+d@p|H_^@bohJOhU1@XpRK9pCK}WTa0pawjJZVTr`NQb8fu|#n+0lty?N{>-YYLj zR0W&e<;C{hLtsskZEQy6bQ+80#D`##WKxx|?tBdPa(i$z_ej*ADv)PM%6Ed?6OMJLESw%%Q7Pn?~SvNjT#H z2ngooY3SSaC+CxWI!qoC^cNA)Xy+lfCP@MH2vR~Pqb&XQdnk1HPAVVAG;^B}I&|A_ z#xz1*a!)+Wf0KOI?PvZjJs39P{}bThe7-yQzc>Hg0RKM* z-oFiUKe+!t!TpPnrI0frHzEdb2r+;QAo~#q_%Y%DDdLdaW)2fPWn0`dlp z|3fxF9z|T>HN*whL4Jq0z;lolkgp&vz;SdG7YM(o+i1bOE~$q4EWkqh(E0oHP$rT5 zh9q14yb|6q&0UJ3x$~R!+}x#J5`ucHTFx)%y?G@68w6+`jxzhZH!NZvIX8~*_!HwIm{dR$)T#~L){y01G!=8M;Lq9b)}oyJuK5Y7-OaJn#f#{6g73s^ zk;RJbc7RSABLgSegp3Y=^IX}a(k42)Gd7z!r7`Nq2#i^3r34p;Q^%tC5RK1+ZTwPOJlW+-GQ5}@cNI1&H99aQ=( zaBmv__twXo2LJyVxc_C4FM~*IZF#31vfyvLWtO& z#PqH*O}n=l>D?{t)y8L* z1*IIx&VFd4Fp1LI1#GPnCA*04UX2MF@XT;vg1aJPg7#ozV!9$}LE|ZD9#0X^hNMLe zR5-xIZk!HA5et<%1_5#Lh0O)T#n-Qo1Q+rDo59213h;j#|9=|Xe;o1+@PAtOzY6|; z6x@G3XF_fQ|NkYp|7ytR!T(xc)O3YkGX;90~1);F~60(L?k#}AzC z+J=RHw#A$FyI`f{d8gA1x2n{g6}<5xt_^_}4pim_u^H)N z&0FpQtsGg~rtyEu`Tr`BYViLHU2&uW^!S#=V>t717!S#=T=f59P2G@TKJpVMvE^vMREcZE~hc3F5E|kc#Bn26X zSU7x%Z!MLSW8MW`KDVZi@N$dLM|k;OP<@0q(X8$+>TjZXAzk3*!}@(xA9!+e|KOcW zGM{+i)nOvZWfc|_3s-}rJZ|!lfwJ4%?;Vr|rT3UoW*nd}SFiQqOB!1Qe zPaY#eCPFCac62H%B}=fTqEg1+r>v4=O}eA3=- zR$S{ueS8^Hu@F(RT6c(u|AUsNzDPtI{C~Mi$oGK%KL+mqQOK1LS_AMo@c)&NX>k9C z!TnE%+ynl9H{@mT|0^N)A_nj>_--&r2Rj8qQqo`}8JcW&Yl_`R~mOH3ZoVz6! zj_(v;pO}nvbR%8y)JG055~dSdpH9A@p{s?WsgVcA4w>6mgxNMLA z3Hb@~;sv5_Ep_1_6*e}~8aE$a=|kLno>Cv;=C-pBar2dlBF7z{BkFf&N`~3xZbK(G z=FYwIGH3VAmMY;4i>5a3!W`$*)5>MG+Wlp0L&N6YxszN`S2VMu>ubk@BcM8|1wA&eE%u% z{Z)`TaQ!F2^)G?Ufa~+;xX*~_5Q}f;RR_L2i&)G&tUkybr?3P)9CD)bq&l|8N*Hg0)jl@R?NzSTj4Ff1;gqCV$yr@>ynjMHsdY^WkgxEP`o@v(ywU*Da z?E{>NF8h2u1l;kRe3xJvEN(l?Z*ImTDWPpDOXaAI0xUrJQh?GGT2<;tRj^fjYWiae$W)2N;GNK^)*PWH}^xAP2b%v4B?)3)l?d&vl>Kbcoej z^7Rv=QDCe%lU;kI;|kd)){+}b@k`x_EIav^6@_Q3ILrNcafZ=Rf0Us)U&R+>$V8U` z71l>)#Y?kj3A3+w24C^QO>rF_X4V|?1gfl}Qr-Y_mV7kq3SK)Ojd=5Ti)x-Wu0Eb) z;JC2K=eCA`%BQ0X{w>PbLrkNjBbd|4ced_rf9Bv^XPP?AZ3beE*?7zVAs_E7vCh=? zE4I2=nRWi!Mj!>utqXoNmx~o3}tn5|fq!&4*i{ ccGHxmf}UMVH*TcTy$2UqC&MLl{