src/Sim/Foundation/Hook/Hook.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 // Available hook method formats :
00034 //   void Hook( HookParameterType* )
00035 //   void Hook( Caller )
00036 //   void Hook( Caller, OpIterator )
00037 //   void Hook( Caller, OpIterator, ParameterType )
00038 //   void Hook( Caller, ParameterType* )
00039 //   void Hook( OpIterator )
00040 //   void Hook( OpIterator, ParameterType* )
00041 //   void Hook( ParameterType* )
00042 //
00043 
00044 
00045 #ifndef SIM_FOUNDATION_HOOK_HOOK_H
00046 #define SIM_FOUNDATION_HOOK_HOOK_H
00047 
00048 #include "Utility/RuntimeError.h"
00049 #include "Sim/Op/OpArray/OpArray.h"
00050 #include "Sim/Foundation/Hook/HookDecl.h"
00051 
00052 namespace Onikiri 
00053 {
00054     //
00055     // A parameter used when a hook is called.
00056     // ParamT has a default type, which is CallerT itself, and is 
00057     // defined in "HookDecl.h" like the following:
00058     //
00059     // template <typename CallerT, typename ParamT = CallerT> 
00060     //
00061     template <typename CallerT, typename ParamT>
00062     class HookParameter
00063     {
00064     public:
00065         typedef CallerT CallerType;
00066         typedef ParamT  ParameterType;
00067 
00068         HookParameter(OpIterator op) 
00069             : m_op(op), m_caller(0), m_parameter(0)
00070         {
00071         }
00072 
00073         HookParameter(CallerType* caller = NULL, ParameterType* parameter = NULL)
00074             : m_op(0), m_caller(caller), m_parameter(parameter)
00075         {
00076         }
00077 
00078         HookParameter(OpIterator op, CallerType* caller = NULL, ParameterType* parameter = NULL)
00079             : m_op(op), m_caller(caller), m_parameter(parameter)
00080         {
00081         }
00082 
00083         OpIterator GetOp() const 
00084         {
00085             // A NULL op can be passed.
00086             return m_op;
00087         }
00088 
00089         CallerType* GetCaller() const
00090         {
00091             ASSERT(m_caller != 0, "caller is not available");
00092             return m_caller;
00093         }
00094 
00095         ParameterType* GetParameter() const
00096         {
00097             ASSERT(m_parameter != 0, "parameter is not available");
00098             return m_parameter;
00099         }
00100 
00101     private:
00102         OpIterator m_op;
00103         CallerType* m_caller;
00104         ParameterType* m_parameter;
00105 
00106     };
00107 
00108     // Hook types
00109     // This type defines a timing when a registered method is called.
00110     struct HookType 
00111     {
00112         enum Type 
00113         {
00114             HOOK_BEFORE,  // Before a hooked body is called.
00115             HOOK_AROUND,  // A hooked body call is totally bypassed.
00116             HOOK_AFTER,   // After a hooked body is called.
00117             HOOK_END      // End sentinel
00118         };
00119     };
00120 
00121     // A hook point. Any class methods can be registered to
00122     // a hook point instance and called.
00123     // ParamT has a default value that is CallerT itself and is 
00124     // defined in "HookDecl.h"
00125     template< typename CallerT, typename ParamT >
00126     class HookPoint
00127     {
00128     public:
00129         typedef CallerT CallerType;
00130         typedef ParamT  ParameterType;
00131         typedef HookParameter<CallerType, ParameterType> HookParameterType;
00132 
00133         // hook NX
00134         class HookFunctionBase
00135         {
00136         public:
00137             virtual ~HookFunctionBase(){};
00138             virtual void operator()(HookParameterType* hookParameter) = 0;
00139         };
00140 
00141         // hook (ClassTypeIuWFNgo|C^)
00142         template <typename ClassType>
00143         class HookFunction : public HookFunctionBase
00144         {
00145         public:
00146             typedef void(ClassType::* FuncType)();
00147             HookFunction(ClassType* object, FuncType func) :
00148               m_object(object), m_func(func)
00149             {
00150             }
00151 
00152             void operator()(HookParameterType* hookParameter)
00153             {
00154                 (m_object->*m_func)();
00155             }
00156         protected:
00157             ClassType* m_object;
00158             FuncType m_func;
00159         };
00160 
00161         // HookParameterType* n
00162         template <typename ClassType>
00163         class HookFunctionWithParam : public HookFunctionBase 
00164         {
00165         public:
00166             typedef void(ClassType::* FuncType)( HookParameterType* );
00167             HookFunctionWithParam(ClassType* object, FuncType func) : 
00168               m_object(object), m_func(func)
00169             {
00170             }
00171 
00172             void operator()(HookParameterType* hookParameter)
00173             {
00174                 (m_object->*m_func)( hookParameter );
00175             }
00176         protected:
00177             ClassType* m_object;
00178             FuncType m_func;
00179         };
00180 
00181         // Caller/OpIterator/ParameterType* n
00182         template <typename ClassType>
00183         class HookFunctionWithSeparateParam : public HookFunctionBase 
00184         {
00185         public:
00186             typedef void(ClassType::* FuncType)( CallerType* caller, OpIterator op, ParameterType* param );
00187             HookFunctionWithSeparateParam(ClassType* object, FuncType func) : 
00188               m_object(object), m_func(func)
00189             {
00190             }
00191 
00192             void operator()(HookParameterType* hookParameter)
00193             {
00194                 (m_object->*m_func)(
00195                     hookParameter->GetCaller(),  
00196                     hookParameter->GetOp(),  
00197                     hookParameter->GetParameter()
00198                 );
00199             }
00200         protected:
00201             ClassType* m_object;
00202             FuncType m_func;
00203         };
00204 
00205         // OpIterator n
00206         template <typename ClassType>
00207         class HookFunctionWithOp : public HookFunctionBase 
00208         {
00209         public:
00210             typedef void(ClassType::* FuncType)( OpIterator op );
00211         protected:
00212             ClassType* m_object;
00213             FuncType m_func;
00214         public:
00215             HookFunctionWithOp(ClassType* object, FuncType func) : 
00216               m_object(object), m_func(func)
00217             {
00218             }
00219 
00220             virtual void operator()(HookParameterType* hookParameter)
00221             {
00222                 (m_object->*m_func)( hookParameter->GetOp() );
00223             }
00224         };
00225 
00226         // Caller n
00227         template <typename ClassType>
00228         class HookFunctionWithCaller : public HookFunctionBase 
00229         {
00230         public:
00231             typedef void(ClassType::* FuncType)( CallerType* caller );
00232             HookFunctionWithCaller(ClassType* object, FuncType func) : 
00233               m_object(object), m_func(func)
00234             {
00235             }
00236 
00237             virtual void operator()(HookParameterType* hookParameter)
00238             {
00239                 (m_object->*m_func)( hookParameter->GetCaller() );
00240             }
00241         protected:
00242             ClassType* m_object;
00243             FuncType m_func;
00244         };
00245 
00246         // Caller/OpIterator n
00247         template <typename ClassType>
00248         class HookFunctionWithCallerAndOp : public HookFunctionBase 
00249         {
00250         public:
00251             typedef void(ClassType::* FuncType)( CallerType* caller, OpIterator op );
00252             HookFunctionWithCallerAndOp(ClassType* object, FuncType func) : 
00253               m_object(object), m_func(func)
00254             {
00255             }
00256 
00257             virtual void operator()(HookParameterType* hookParameter)
00258             {
00259                 (m_object->*m_func)( hookParameter->GetCaller(), hookParameter->GetOp() );
00260             }
00261         protected:
00262             ClassType* m_object;
00263             FuncType m_func;
00264         };
00265 
00266         // OpIterator/ParameterType* n
00267         template <typename ClassType>
00268         class HookFunctionWithOpAndRawParam : public HookFunctionBase 
00269         {
00270         public:
00271             typedef void(ClassType::* FuncType)( OpIterator op, ParameterType* parameter );
00272             HookFunctionWithOpAndRawParam(ClassType* object, FuncType func) : 
00273               m_object(object), m_func(func)
00274             {
00275             }
00276 
00277             virtual void operator()(HookParameterType* hookParameter)
00278             {
00279                 (m_object->*m_func)( hookParameter->GetOp(), hookParameter->GetParameter() );
00280             }
00281         protected:
00282             ClassType* m_object;
00283             FuncType m_func;
00284         };
00285 
00286         // Caller/ParameterType* n
00287         template <typename ClassType>
00288         class HookFunctionWithCallerAndRawParam : public HookFunctionBase 
00289         {
00290         public:
00291             typedef void(ClassType::* FuncType)( CallerType* caller, ParameterType* parameter );
00292             HookFunctionWithCallerAndRawParam(ClassType* object, FuncType func) : 
00293               m_object(object), m_func(func)
00294             {
00295             }
00296 
00297             virtual void operator()(HookParameterType* hookParameter)
00298             {
00299                 (m_object->*m_func)( hookParameter->GetCaller(), hookParameter->GetParameter() );
00300             }
00301         protected:
00302             ClassType* m_object;
00303             FuncType m_func;
00304         };
00305 
00306         // ParameterType* n
00307         template <typename ClassType>
00308         class HookFunctionWithRawParam : public HookFunctionBase 
00309         {
00310         public:
00311             typedef void(ClassType::* FuncType)( ParameterType* parameter );
00312             HookFunctionWithRawParam(ClassType* object, FuncType func) : 
00313               m_object(object), m_func(func)
00314             {
00315             }
00316 
00317             virtual void operator()(HookParameterType* hookParameter)
00318             {
00319                 (m_object->*m_func)( hookParameter->GetParameter() );
00320             }
00321         protected:
00322             ClassType* m_object;
00323             FuncType m_func;
00324         };
00325 
00326         HookPoint()
00327         {
00328             m_hookExists = false;
00329         }
00330 
00331         virtual ~HookPoint()
00332         {
00333             ReleaseHookVector(m_beforeFunction);
00334             ReleaseHookVector(m_aroundFunction);
00335             ReleaseHookVector(m_afterFunction);
00336         }
00337 
00338         // OpIterator  Caller  Parameter COs~gK
00339         void Trigger( OpIterator opIterator, CallerType* caller, ParameterType* parameter, HookType::Type hookType)
00340         {
00341             if( !IsHookExists(hookType) )
00342                 return;
00343 
00344             HookParameterType hookParameter( opIterator, caller, parameter );
00345             Trigger( GetHookFunction(hookType), &hookParameter );
00346         }
00347 
00348         // OpIterator  Caller COs~gK
00349         void Trigger( OpIterator opIterator, CallerType* caller, HookType::Type hookType)
00350         {
00351             if( !IsHookExists(hookType) )
00352                 return;
00353             Trigger( opIterator, caller, 0, hookType);
00354         }
00355 
00356         // Caller  Parameter COs~gK
00357         void Trigger( CallerType* caller, ParameterType* parameter, HookType::Type hookType)
00358         {
00359             if( !IsHookExists(hookType) )
00360                 return;
00361 
00362             HookParameterType hookParameter( OpIterator(0), caller, parameter );
00363             Trigger( GetHookFunction(hookType), &hookParameter );
00364         }
00365 
00366         // Caller COs~gK
00367         void Trigger( CallerType* caller, HookType::Type hookType)
00368         {
00369             if( !IsHookExists(hookType) )
00370                 return;
00371             Trigger( OpIterator(0), caller, 0, hookType );
00372         }
00373 
00374         //
00375         // --- Hook o^
00376         // HookFunction~ Hook \bh`
00377         // HookParameter KCaller/Op/Parameter nKvC
00378         // ev[g
00379         //
00380 
00381         // p[^
00382         template <typename T>
00383         void Register(T* object, typename HookFunction<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00384         {
00385             Register(GetHookFunction(hookType), new HookFunction<T>(object, func), priority);
00386         }
00387 
00388         // p[^ Hook o^
00389         template <typename T>
00390         void Register(T* object, typename HookFunctionWithParam<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00391         {
00392             Register(GetHookFunction(hookType), new HookFunctionWithParam<T>(object, func), priority);
00393         }
00394 
00395         // Caller/OpIterator/ParameterType Hook o^
00396         template <typename T>
00397         void Register(T* object, typename HookFunctionWithSeparateParam<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00398         {
00399             Register(GetHookFunction(hookType), new HookFunctionWithSeparateParam<T>(object, func), priority);
00400         }
00401 
00402         // OpIterator Hook o^
00403         template <typename T>
00404         void Register(T* object, typename HookFunctionWithOp<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00405         {
00406             Register(GetHookFunction(hookType), new HookFunctionWithOp<T>(object, func), priority);
00407         }
00408 
00409         // Caller Hook o^
00410         template <typename T>
00411         void Register(T* object, typename HookFunctionWithCaller<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00412         {
00413             Register(GetHookFunction(hookType), new HookFunctionWithCaller<T>(object, func), priority);
00414         }
00415 
00416         // Caller/OpIterator Hook o^
00417         template <typename T>
00418         void Register(T* object, typename HookFunctionWithCallerAndOp<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00419         {
00420             Register(GetHookFunction(hookType), new HookFunctionWithCallerAndOp<T>(object, func), priority);
00421         }
00422 
00423         // Caller/ParameterType* n
00424         template <typename T>
00425         void Register(T* object, typename HookFunctionWithCallerAndRawParam<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00426         {
00427             Register(GetHookFunction(hookType), new HookFunctionWithCallerAndRawParam<T>(object, func), priority);
00428         }
00429 
00430         // OpIterator/ParameterType* n
00431         template <typename T>
00432         void Register(T* object, typename HookFunctionWithOpAndRawParam<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00433         {
00434             Register(GetHookFunction(hookType), new HookFunctionWithOpAndRawParam<T>(object, func), priority);
00435         }
00436 
00437         // ParameterType* n
00438         template <typename T>
00439         void Register(T* object, typename HookFunctionWithRawParam<T>::FuncType func, int priority, HookType::Type hookType = HookType::HOOK_AFTER)
00440         {
00441             Register(GetHookFunction(hookType), new HookFunctionWithRawParam<T>(object, func), priority);
00442         }
00443 
00444         // Co^
00445         bool HasAround() 
00446         {
00447             return !m_aroundFunction.empty();
00448         }
00449 
00450         // Co^
00451         int CountAround()
00452         {
00453             return static_cast<int>(m_aroundFunction.size());
00454         }
00455 
00456         // tbNo^
00457         INLINE bool IsAnyHookRegistered()
00458         {
00459             return m_hookExists;
00460         }
00461 
00462     private:
00463 
00464         typedef std::pair< HookFunctionBase*, int > HookPair;
00465         typedef std::vector< HookPair > HookVector;
00466 
00467         struct ComparePriority
00468         {
00469             bool operator()( const HookPair& lhv, const HookPair& rhv )
00470             { return lhv.second < rhv.second; }
00471         };
00472 
00473         // HookFunctionBase*  int(D)  pair i[ vector
00474         HookVector m_beforeFunction;
00475         HookVector m_aroundFunction;
00476         HookVector m_afterFunction;
00477         bool m_hookExists;
00478 
00479 
00480         void Register(HookVector& hookVector, HookFunctionBase* hookFunction, int priority)
00481         {
00482             // hook o^
00483             hookVector.push_back( std::make_pair(hookFunction, priority) );
00484             m_hookExists = true;
00485 
00486             // D\[g
00487             // V~[^\[gC
00488             sort(hookVector.begin(), hookVector.end(), ComparePriority());
00489         }
00490 
00491         // o^ Hook 
00492         void Trigger(HookVector& hookVector, HookParameterType* hookParameter)
00493         {
00494             for(typename HookVector::iterator iter = hookVector.begin();
00495                 iter != hookVector.end();
00496                 ++iter)
00497             {
00498                 (*(iter->first))(hookParameter);
00499             }
00500         }
00501 
00502         void ReleaseHookVector(HookVector& hookVector)
00503         {
00504             for(typename HookVector::iterator iter = hookVector.begin();
00505                 iter != hookVector.end();
00506                 ++iter)
00507             {
00508                 delete iter->first;
00509             }
00510             hookVector.clear();
00511         }
00512 
00513         HookVector& GetHookFunction(HookType::Type hookType)
00514         {
00515             if( hookType == HookType::HOOK_AFTER ) {
00516                 return m_afterFunction;
00517             }
00518             if( hookType == HookType::HOOK_BEFORE ) {
00519                 return m_beforeFunction;
00520             }
00521             return m_aroundFunction;
00522         }
00523 
00524         bool IsHookExists(HookType::Type hookType)
00525         {
00526             if( hookType == HookType::HOOK_AFTER ) {
00527                 return m_afterFunction.size() > 0;
00528             }
00529             if( hookType == HookType::HOOK_BEFORE ) {
00530                 return m_beforeFunction.size() > 0;
00531             }
00532             return m_aroundFunction.size() > 0;
00533         }
00534     };
00535 
00536 }; // namespace Onikiri
00537 
00538 #endif // SIM_FOUNDATION_HOOK_HOOK_H
00539 

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