src/Sim/Foundation/Hook/HookUtil.h

説明を見る。
00001 // 
00002 // Copyright (c) 2005-2008 Kenichi Watanabe.
00003 // Copyright (c) 2005-2008 Yasuhiro Watari.
00004 // Copyright (c) 2005-2008 Hironori Ichibayashi.
00005 // Copyright (c) 2008-2009 Kazuo Horio.
00006 // Copyright (c) 2009-2013 Naruki Kurata.
00007 // Copyright (c) 2005-2013 Ryota Shioya.
00008 // Copyright (c) 2005-2013 Masahiro Goshima.
00009 // 
00010 // This software is provided 'as-is', without any express or implied
00011 // warranty. In no event will the authors be held liable for any damages
00012 // arising from the use of this software.
00013 // 
00014 // Permission is granted to anyone to use this software for any purpose,
00015 // including commercial applications, and to alter it and redistribute it
00016 // freely, subject to the following restrictions:
00017 // 
00018 // 1. The origin of this software must not be misrepresented; you must not
00019 // claim that you wrote the original software. If you use this software
00020 // in a product, an acknowledgment in the product documentation would be
00021 // appreciated but is not required.
00022 // 
00023 // 2. Altered source versions must be plainly marked as such, and must not be
00024 // misrepresented as being the original software.
00025 // 
00026 // 3. This notice may not be removed or altered from any source
00027 // distribution.
00028 // 
00029 // 
00030 
00031 
00032 //
00033 // Hook o
00034 //
00035 
00036 
00037 #ifndef SIM_FOUNDATION_HOOK_HOOK_UTIL_H
00038 #define SIM_FOUNDATION_HOOK_HOOK_UTIL_H
00039 
00040 #include "Sim/Foundation/Hook/Hook.h"
00041 
00042 namespace Onikiri
00043 {
00044     //
00045     //  Usage : 
00046     //
00047     //      void Class::MethodBody();
00048     // 
00049     //      HookEntry(
00050     //          this,
00051     //          &Class::MethodBody,
00052     //          &hookPoint
00053     //      );
00054     //
00055     template <
00056         typename ClassType, 
00057         typename HookPointType
00058     >
00059     NOINLINE void HookEntryBody( 
00060         ClassType* obj, 
00061         void (ClassType::*MethodPtr)(), 
00062         HookPointType* hookPoint 
00063     ){
00064         hookPoint->Trigger(obj, HookType::HOOK_BEFORE);
00065 
00066         if( !hookPoint->HasAround() ) {
00067             // {
00068             (obj->*MethodPtr)(); 
00069         } else {
00070             // o^
00071             hookPoint->Trigger(obj, HookType::HOOK_AROUND);
00072         }
00073 
00074         hookPoint->Trigger(obj, HookType::HOOK_AFTER);
00075     }
00076 
00077     //
00078     template <
00079         typename ClassType, 
00080         typename HookPointType
00081     >
00082     INLINE void HookEntry( 
00083         ClassType* obj, 
00084         void (ClassType::*MethodPtr)(), 
00085         HookPointType* hookPoint 
00086     ){
00087         if( hookPoint->IsAnyHookRegistered() ){
00088             HookEntryBody( obj, MethodPtr, hookPoint );
00089         }
00090         else{
00091             // {
00092             (obj->*MethodPtr)(); 
00093         }
00094     }
00095 
00096 
00097     //
00098     //  Usage : 
00099     //
00100     //      void Class::MethodBody( HookParam* hookParam );
00101     // 
00102     //      HookEntry(
00103     //          this,
00104     //          &Class::MethodBody,
00105     //          &hookPoint,
00106     //          &hookParam 
00107     //      );
00108     //
00109     template <
00110         typename ClassType, 
00111         typename HookPointType,
00112         typename HookParamType
00113     >
00114     NOINLINE void HookEntryBody( 
00115         ClassType* obj, 
00116         void (ClassType::*MethodPtr)( HookParamType* param ), 
00117         HookPointType* hookPoint, 
00118         HookParamType* hookParam 
00119     ){
00120         hookPoint->Trigger(obj, hookParam, HookType::HOOK_BEFORE);
00121 
00122         if( !hookPoint->HasAround() ) {
00123             // {
00124             (obj->*MethodPtr)(hookParam); 
00125         } else {
00126             // o^
00127             hookPoint->Trigger(obj, hookParam, HookType::HOOK_AROUND);
00128         }
00129 
00130         hookPoint->Trigger(obj, hookParam, HookType::HOOK_AFTER);
00131     }
00132 
00133     template <
00134         typename ClassType, 
00135         typename HookPointType,
00136         typename HookParamType
00137     >
00138     INLINE void HookEntry( 
00139         ClassType* obj, 
00140         void (ClassType::*MethodPtr)( HookParamType* param ), 
00141         HookPointType* hookPoint, 
00142         HookParamType* hookParam 
00143     ){
00144         if( hookPoint->IsAnyHookRegistered() ){
00145             HookEntryBody( obj, MethodPtr, hookPoint, hookParam );
00146         }
00147         else{
00148             // {
00149             (obj->*MethodPtr)(hookParam); 
00150         }
00151     }
00152 
00153     //
00154     //  Usage : 
00155     //
00156     //      void Class::MethodBody( OpIterator op );
00157     // 
00158     //      HookEntry(
00159     //          op,
00160     //          this,
00161     //          &Class::MethodBody,
00162     //          &hookPoint
00163     //      );
00164     //
00165     template <
00166         typename ClassType, 
00167         typename HookPointType
00168     >
00169     NOINLINE void HookEntryBody( 
00170         ClassType* obj, 
00171         void (ClassType::*MethodPtr)( OpIterator op ), 
00172         HookPointType* hookPoint,
00173         OpIterator op
00174     ){
00175         hookPoint->Trigger( op, obj, HookType::HOOK_BEFORE);
00176 
00177         if( !hookPoint->HasAround() ) {
00178             // {
00179             (obj->*MethodPtr)( op ); 
00180         } else {
00181             // o^
00182             hookPoint->Trigger( op, obj, HookType::HOOK_AROUND);
00183         }
00184 
00185         hookPoint->Trigger( op, obj, HookType::HOOK_AFTER);
00186     }
00187 
00188     template <
00189         typename ClassType, 
00190         typename HookPointType
00191     >
00192     INLINE void HookEntry( 
00193         ClassType* obj, 
00194         void (ClassType::*MethodPtr)( OpIterator op ), 
00195         HookPointType* hookPoint,
00196         OpIterator op
00197     ){
00198         if( hookPoint->IsAnyHookRegistered() ){
00199             HookEntryBody( obj, MethodPtr, hookPoint, op ); 
00200         }
00201         else{
00202             // {
00203             (obj->*MethodPtr)( op ); 
00204         }
00205     }
00206 
00207 
00208     //
00209     //  Usage : 
00210     //
00211     //      void Class::MethodBody( OpIterator op, Parameter param );
00212     // 
00213     //      HookEntry(
00214     //          this,
00215     //          &Class::MethodBody,
00216     //          &hookPoint,
00217     //          op,
00218     //          param
00219     //      );
00220     //
00221     template <
00222         typename ClassType, 
00223         typename HookPointType,
00224         typename Parameter
00225     >
00226     NOINLINE void HookEntryBody( 
00227         ClassType* obj, 
00228         void (ClassType::*MethodPtr)( OpIterator op, Parameter param ), 
00229         HookPointType* hookPoint,
00230         OpIterator op,
00231         Parameter param
00232     ){
00233         hookPoint->Trigger( op, obj, param, HookType::HOOK_BEFORE);
00234 
00235         if( !hookPoint->HasAround() ) {
00236             // {
00237             (obj->*MethodPtr)( op, param ); 
00238         } else {
00239             // o^
00240             hookPoint->Trigger( op, obj, param, HookType::HOOK_AROUND);
00241         }
00242 
00243         hookPoint->Trigger( op, obj, param, HookType::HOOK_AFTER);
00244     }
00245 
00246     template <
00247         typename ClassType, 
00248         typename HookPointType,
00249         typename Parameter
00250     >
00251     INLINE void HookEntry( 
00252         ClassType* obj, 
00253         void (ClassType::*MethodPtr)( OpIterator op, Parameter param ), 
00254         HookPointType* hookPoint,
00255         OpIterator op,
00256         Parameter param
00257     ){
00258         if( hookPoint->IsAnyHookRegistered() ){
00259             HookEntryBody( obj, MethodPtr, hookPoint, op, param ); 
00260         }
00261         else{
00262             // {
00263             (obj->*MethodPtr)( op, param ); 
00264         }
00265     }
00266 
00267     //
00268     // Todo: sort arguments, implement macros with a class and decltype.
00269     //
00270 
00271     //
00272     // hookPoint->Trigger( caller, HookType::HOOK_BEFORE );
00273     //
00274     // if( !hookPoint->HasAround() ) {
00275     //    // Original processes.
00276     // } 
00277     // else {
00278     //    // If an 'AROUND' hook is registered, call it.
00279     //    hookPoint->Trigger( caller, HookType::HOOK_AROUND );
00280     // }
00281     //
00282     // hookPoint->Trigger( caller, HookType::HOOK_AFTER );
00283     //
00284 
00285     //
00286     //  Usage : 
00287     //
00288     //      Hook prototype: void HookMethod();
00289     // 
00290     //      HOOK_SECTION( s_hookPoint ){
00291     //          // Original processes.
00292     //      }
00293     //
00294     template < typename Caller, typename HookPoint >
00295     INLINE bool HookSectionBefore( Caller* caller, HookPoint* hookPoint )
00296     {
00297         hookPoint->Trigger( caller, HookType::HOOK_BEFORE );
00298         if( hookPoint->HasAround() ){
00299             HookSectionAfter( caller, hookPoint );
00300             return true;    // Exit the loop in HOOK_SECTION.
00301         }
00302         else{
00303             return false;   // Not exit the loop, process a original routine.
00304         }
00305     }
00306 
00307     template < typename Caller, typename HookPoint >
00308     INLINE bool HookSectionAfter( Caller* caller, HookPoint* hookPoint )
00309     {
00310         if( hookPoint->HasAround() ){
00311             hookPoint->Trigger( caller, HookType::HOOK_AROUND );
00312         }
00313 
00314         hookPoint->Trigger( caller, HookType::HOOK_AFTER );
00315         return true;
00316     }
00317 
00318     #define HOOK_SECTION( hookPoint ) \
00319         for( \
00320             bool onikiri_exitSection = HookSectionBefore( this, &hookPoint ); \
00321             !onikiri_exitSection; \
00322             onikiri_exitSection = HookSectionAfter( this, &hookPoint ) \
00323         )
00324 
00325 
00326 
00327     //
00328     //  Usage : 
00329     //
00330     //      Hook prototype: void HookMethod( OpIterator op );
00331     // 
00332     //      HOOK_SECTION( s_hookPoint, op ){
00333     //          // Original processes.
00334     //      }
00335     //
00336     template < typename Caller, typename HookPoint >
00337     INLINE bool HookSectionBefore( Caller* caller, HookPoint* hookPoint, OpIterator op )
00338     {
00339         hookPoint->Trigger( op, caller, HookType::HOOK_BEFORE );
00340         if( hookPoint->HasAround() ){
00341             HookSectionAfter( caller, hookPoint, op );
00342             return true;    // Exit the loop in HOOK_SECTION.
00343         }
00344         else{
00345             return false;   // Not exit the loop, process a original routine.
00346         }
00347     }
00348 
00349     template < typename Caller, typename HookPoint >
00350     INLINE bool HookSectionAfter( Caller* caller, HookPoint* hookPoint, OpIterator op  )
00351     {
00352         if( hookPoint->HasAround() ){
00353             hookPoint->Trigger( op, caller, HookType::HOOK_AROUND );
00354         }
00355 
00356         hookPoint->Trigger( op, caller, HookType::HOOK_AFTER );
00357         return true;
00358     }
00359 
00360     #define HOOK_SECTION_OP( hookPoint, op ) \
00361         for( \
00362             bool onikiri_exitSection = HookSectionBefore( this, &hookPoint, op ); \
00363             !onikiri_exitSection; \
00364             onikiri_exitSection = HookSectionAfter( this, &hookPoint, op ) \
00365         )
00366 
00367     
00368     //
00369     //  Usage : 
00370     //
00371     //      Hook prototype: void HookMethod( Parameter* param );
00372     // 
00373     //      HOOK_SECTION( s_hookPoint, param ){
00374     //          // Original processes.
00375     //      }
00376     //
00377     template < typename Caller, typename HookPoint, typename Parameter >
00378     INLINE bool HookSectionBefore( Caller* caller, HookPoint* hookPoint, Parameter* param )
00379     {
00380         hookPoint->Trigger( caller, param, HookType::HOOK_BEFORE );
00381         if( hookPoint->HasAround() ){
00382             HookSectionAfter( caller, hookPoint, param );
00383             return true;    // Exit the loop in HOOK_SECTION.
00384         }
00385         else{
00386             return false;   // Not exit the loop, process a original routine.
00387         }
00388     }
00389 
00390     template < typename Caller, typename HookPoint, typename Parameter >
00391     INLINE bool HookSectionAfter( Caller* caller, HookPoint* hookPoint, Parameter* param )
00392     {
00393         if( hookPoint->HasAround() ){
00394             hookPoint->Trigger( caller, param, HookType::HOOK_AROUND );
00395         }
00396 
00397         hookPoint->Trigger( caller, param, HookType::HOOK_AFTER );
00398         return true;
00399     }
00400 
00401     #define HOOK_SECTION_PARAM( hookPoint, param ) \
00402         for( \
00403             bool onikiri_exitSection = HookSectionBefore( this, &hookPoint, &param ); \
00404             !onikiri_exitSection; \
00405             onikiri_exitSection = HookSectionAfter( this, &hookPoint, &param ) \
00406         )
00407 
00408     //
00409     //  Usage : 
00410     //
00411     //      Hook prototype: void HookMethod( OpIterator op, Parameter* param );
00412     // 
00413     //      HOOK_SECTION( s_hookPoint, op, param ){
00414     //          // Original processes.
00415     //      }
00416     //
00417     template < typename Caller, typename HookPoint, typename Parameter >
00418     INLINE bool HookSectionBefore( Caller* caller, HookPoint* hookPoint, OpIterator op, Parameter* param )
00419     {
00420         hookPoint->Trigger( op, caller, param, HookType::HOOK_BEFORE );
00421         if( hookPoint->HasAround() ){
00422             HookSectionAfter( caller, hookPoint, op, param );
00423             return true;    // Exit the loop in HOOK_SECTION.
00424         }
00425         else{
00426             return false;   // Not exit the loop, process a original routine.
00427         }
00428     }
00429 
00430     template < typename Caller, typename HookPoint, typename Parameter >
00431     INLINE bool HookSectionAfter( Caller* caller, HookPoint* hookPoint, OpIterator op, Parameter* param )
00432     {
00433         if( hookPoint->HasAround() ){
00434             hookPoint->Trigger( op, caller, param, HookType::HOOK_AROUND );
00435         }
00436 
00437         hookPoint->Trigger( op, caller, param, HookType::HOOK_AFTER );
00438         return true;
00439     }
00440 
00441     #define HOOK_SECTION_OP_PARAM( hookPoint, op, param ) \
00442         for( \
00443             bool onikiri_exitSection = HookSectionBefore( this, &hookPoint, op, &param ); \
00444             !onikiri_exitSection; \
00445             onikiri_exitSection = HookSectionAfter( this, &hookPoint, op, &param ) \
00446         )
00447 
00448 }
00449 
00450 #endif
00451 

Onikiri2に対してTue Jun 18 14:34:23 2013に生成されました。  doxygen 1.4.7