otrav.h

00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00041 #ifndef BASE_OTRAV_H
00042 #define BASE_OTRAV_H
00043 
00044 #include "fastlib/base/common.h"
00045 #include "fastlib/base/debug.h"
00046 #include "fastlib/base/cc.h"
00047 #include "fastlib/base/ccmem.h"
00048 
00049 #include <typeinfo>
00050 
00086 #define OT_CUSTOM_PRINT_OBJ(x, name) \
00087     if (true) { \
00088       ot__visitor->Name(name, x); \
00089       ot__visitor->Obj(x); \
00090     } else NOP // require semicolon
00091 
00124 #define OT_OBJ(x) \
00125     OT_CUSTOM_PRINT_OBJ(x, #x)
00126 
00135 #define OT_ENUM_VAL(val) \
00136    case val: \
00137     if (ot__visitor->IS_PRINTER) { \
00138       const char *ot__temp = #val; \
00139       ot__visitor->Obj(ot__temp); \
00140       break; \
00141     } // fall-through to default inside OT_ENUM_EXPERT
00142 
00143 //    if (ot__visitor->IS_PRINTER && ot__enum == val) {
00144 //      const char *ot__temp = #val;
00145 //      ot__visitor->Obj(ot__temp);
00146 //    } else // for series of OT_ENUM_VAL, use in OT_ENUM_EXPERT
00147 
00197 #define OT_ENUM_EXPERT(x, T, print_code) \
00198     if (true) { \
00199       ot__visitor->Name(#x, x); \
00200       switch (x) { \
00201         print_code \
00202        default: \
00203         ot__visitor->Enum(x); \
00204       } \
00205     } else NOP // require semicolon
00206 
00220 #define OT_ENUM(x) \
00221     OT_ENUM_EXPERT(x, int, )
00222 
00241 #define OT_ARRAY_IMPL(x, len, iter_var, loop_code, func, args...) \
00242     if (true) { \
00243       ot__visitor->Name(#x, x); \
00244       index_t ot__len = len; \
00245       if (ot__visitor->Pre##func(x, ot__len, ## args)) { \
00246         for (index_t iter_var = 0; iter_var < ot__len; ++iter_var) { \
00247           ot__visitor->ElemOf(x); \
00248           loop_code; \
00249         } \
00250         ot__visitor->Name(#x, x); \
00251         ot__visitor->Post##func(x, ot__len, ## args); \
00252       } \
00253     } else NOP // require semicolon
00254 
00279 #define OT_STATIC_ARRAY_EXPERT(x, iter_var, elem_code) \
00280     OT_ARRAY_IMPL(x, sizeof(x) / sizeof(*x), \
00281         iter_var, elem_code, StaticArray)
00282 
00294 #define OT_STATIC_ARRAY(x) \
00295     OT_STATIC_ARRAY_EXPERT(x, ot__iter, OT_OBJ((x)[ot__iter]))
00296 
00325 #define OT_PTR_EXPERT(x, nullable, deref_code) \
00326     OT_ARRAY_IMPL(x, 1, ot__iter, deref_code, \
00327         Array, nullable, false, true)
00328 
00343 #define OT_PTR(x) \
00344     OT_PTR_EXPERT(x, true, OT_OBJ(*(x)))
00345 
00390 #define OT_ARRAY_EXPERT(x, len, nullable, iter_var, elem_code) \
00391     OT_ARRAY_IMPL(x, len, iter_var, elem_code, \
00392         Array, nullable, false, false)
00393 
00412 #define OT_ARRAY(x, len) \
00413     OT_ARRAY_EXPERT(x, len, true, ot__iter, OT_OBJ((x)[ot__iter]))
00414 
00447 #define OT_ALLOC_EXPERT(x, len, nullable, iter_var, elem_code) \
00448     OT_ARRAY_IMPL(x, len, iter_var, elem_code, \
00449         Array, nullable, true, false)
00450 
00466 #define OT_ALLOC(x, len) \
00467     OT_ALLOC_EXPERT(x, len, true, ot__iter, OT_OBJ((x)[ot__iter]))
00468 
00500 #define OT_STR_EXPERT(x, nullable, alloc) \
00501     if (true) { \
00502       ot__visitor->Name(#x, x); \
00503       ot__visitor->Str(x, nullable, alloc); \
00504     } else NOP // require semicolon
00505 
00516 #define OT_STR(x) \
00517     OT_STR_EXPERT(x, true, true)
00518 
00519 
00520 
00532 #define OT_CONSTRUCTOR(C) \
00533    public: \
00534     C() { \
00535       ot__private::Unstructor ot__unstructor(this); \
00536       OT__DefaultConstruct(this); \
00537     } \
00538    private:
00539 
00550 #define OT_DESTRUCTOR(C) \
00551    public: \
00552     ~C() { \
00553       DEBUG_DESTRUCT_OK(this); \
00554       ot__private::Destructor<false> ot__destructor(this); \
00555     } \
00556    private:
00557 
00571 #define OT_COPY_CONSTRUCTOR(C) \
00572    public: \
00573     C(const C &src) { \
00574       ot__private::Copier<false> ot__copier(this, &src); \
00575     } \
00576     ASSIGN_VIA_RECURSION_SAFE_COPY_CONSTRUCTION(C) \
00577    private:
00578 
00592 #define OT_DEPRECATED_COPY_CONSTRUCTOR(C) \
00593    public: \
00594     COMPILER_DEPRECATED \
00595     C(const C &src) { \
00596       ot__private::Copier<false> ot__copier(this, &src); \
00597     } \
00598     ASSIGN_VIA_RECURSION_SAFE_COPY_CONSTRUCTION(C) \
00599    private:
00600 
00601 
00602 
00615 #define OT_RENEW_METHOD(C) \
00616    public: \
00617     void Renew() { \
00618       this->~C(); \
00619       new(this) C(); \
00620     } \
00621    private:
00622 
00635 #define OT_COPY_METHOD(C) \
00636    public: \
00637     void InitCopy(const C &src) { \
00638       ot::InitCopy(this, src); \
00639     } \
00640     COMPILER_DEPRECATED \
00641     void Copy(const C &src) { \
00642       ot::InitCopy(this, src); \
00643     } \
00644    private:
00645 
00658 #define OT_PRINT_METHOD(C) \
00659    public: \
00660     template<typename TPrintFormat> \
00661     const char *Print(const char *name, FILE *stream = stdout) { \
00662       return ot::Print<TPrintFormat>(*this, name, stream); \
00663     } \
00664     const char *Print(const char *name, FILE *stream = stdout) { \
00665       return Print<ot::StandardFormat>(name, stream); \
00666     } \
00667    private:
00668 
00669 
00670 
00680 #define OT_FREEZE_METHODS(C) \
00681    public: \
00682     size_t FrozenSize() { \
00683       return ot::FrozenSize(*this); \
00684     } \
00685     size_t Freeze(char *block) { \
00686       return ot::Freeze(block, *this); \
00687     } \
00688     void InitThaw(char *block) { \
00689       ot::InitThaw(this, block); \
00690     } \
00691    private:
00692 
00704 #define OT_SERIALIZE_METHODS(C) \
00705    public: \
00706     size_t SerialSize() { \
00707       return ot::SerialSize(*this); \
00708     } \
00709     size_t Serialize(FILE *stream) { \
00710       return ot::Serialize(*this, stream); \
00711     } \
00712     size_t InitDeserialize(FILE *stream) { \
00713       return ot::InitDeserialize(this, stream); \
00714     } \
00715    private:
00716 
00717 
00718 
00739 #define OT_BECOME_NON_ALIAS(C) \
00740    public: \
00741     friend void OT__BecomeNonAlias(C *ot__obj) { \
00742       ot__obj->OT__BecomeNonAlias_(); \
00743       DEBUG_ASSERT_MSG(!OT__IsAlias(ot__obj), \
00744           "OT_BECOME_NON_ALIAS left OT_IS_ALIAS true for %s.", \
00745           typeid(C).name()); \
00746     } \
00747    private: \
00748     void OT__BecomeNonAlias_()
00749 
00765 #define OT_BECOME_ALIAS(C) \
00766    public: \
00767     friend bool OT__Aliasable(const C *ot__obj) { \
00768       return true; \
00769     } \
00770     friend void OT__BecomeAlias(C *ot__obj) { \
00771       ot__obj->OT__BecomeAlias_(); \
00772       DEBUG_ASSERT_MSG(OT__IsAlias(ot__obj), \
00773           "OT_BECOME_ALIAS left OT_IS_ALIAS false for %s.", \
00774           typeid(C).name()); \
00775     } \
00776    private: \
00777     void OT__BecomeAlias_()
00778 
00795 #define OT_IS_ALIAS(C) \
00796    public: \
00797     friend bool OT__IsAlias(C *ot__obj) { \
00798       return ot__obj->OT__IsAlias_(); \
00799     } \
00800    private: \
00801     bool OT__IsAlias_()
00802 
00852 #define OT_ALIAS_METHODS(C) \
00853    public: \
00854     void InitAlias(const C &src) { \
00855       DEBUG_INIT_OK(this); \
00856       mem::Copy(this, &src); \
00857       ot__private::Aliaser ot__aliaser(this); \
00858     } \
00859     void InitSteal(C *src) { \
00860       DEBUG_INIT_OK(this); \
00861       DEBUG_WARN_MSG_IF(OT__IsAlias(src), \
00862           "Stealing from an alias %s.", typeid(C).name()); \
00863       mem::Copy(this, src); \
00864       ot__private::Aliaser ot__aliaser(src); \
00865     } \
00866     bool IsAlias() { \
00867       return OT__IsAlias(this); \
00868     } \
00869    private:
00870 
00871 
00872 
00909 #define OT_DEFAULT_CONSTRUCT(C) \
00910    public: \
00911     friend void OT__DefaultConstruct(C *ot__obj) { \
00912       ot__obj->OT__DefaultConstruct_(); \
00913     } \
00914    private: \
00915     void OT__DefaultConstruct_()
00916 
00957 #define OT_DEBUG_INIT_OK(C) \
00958    public: \
00959     friend bool OT__DebugInitOK(C *ot__obj) { \
00960       return ot__obj->OT__DebugInitOK_(); \
00961     } \
00962    private: \
00963     bool OT__DebugInitOK_()
00964 
00977 #define DEBUG_INIT_OK(x) \
00978     DEBUG_ASSERT_MSG(OT__DebugInitOK(x), \
00979         "Reinitialization of %s; missing Renew()?", \
00980         typeid(*x).name());
00981 
01015 #define OT_DEBUG_MODIFY_OK(C) \
01016    public: \
01017     friend bool OT__DebugModifyOK(C *ot__obj) { \
01018       return ot__obj->OT__DebugModifyOK_(); \
01019     } \
01020    private: \
01021     bool OT__DebugModifyOK_()
01022 
01036 #define DEBUG_MODIFY_OK(x) \
01037     DEBUG_ASSERT_MSG(OT__DebugModifyOK(x), \
01038         "Modification of alias/locked %s; missing Init?", \
01039         typeid(*x).name());
01040 
01071 #define OT_DEBUG_DESTRUCT_OK(x) \
01072    public: \
01073     friend bool OT__DebugDestructOK(C *ot__obj) { \
01074       return ot__obj->OT__DebugDestructOK_(); \
01075     } \
01076    private: \
01077     bool OT__DebugDestructOK_()
01078 
01089 #define DEBUG_DESTRUCT_OK(x) \
01090     DEBUG_ASSERT_MSG(OT__DebugDestructOK(x), \
01091         "Premature destruction of %s; missing Init?", \
01092         typeid(*x).name());
01093 
01094 
01095 
01135 #define OT_REFILL_TRANSIENTS(C) \
01136    public: \
01137     friend void OT__RefillTransients(C *ot__obj) { \
01138       OT__BecomeNonAlias(ot__obj); \
01139       ot__obj->OT__RefillTransients_(); \
01140     } \
01141    private: \
01142     void OT__RefillTransients_()
01143 
01184 #define OT_TRANSIENTS(C) \
01185    public: \
01186     template<typename TVisitor> \
01187     friend void OT__TraverseTransients(C *ot__obj, TVisitor *ot__visitor) { \
01188       ot__obj->OT__TraverseTransients_(ot__visitor); \
01189     } \
01190    private: \
01191     template<typename TVisitor> \
01192     void OT__TraverseTransients_(TVisitor *ot__visitor)
01193 
01194 
01195 
01209 #define OBJECT_TRAVERSAL_ONLY(C) \
01210    public: \
01211     template<typename TVisitor> \
01212     friend bool OT__PreTraverse(C *ot__dest, const C *ot__src, \
01213                                 index_t ot__len, TVisitor *ot__visitor) { \
01214       return ot__visitor->PreTraverse(ot__dest, ot__src, ot__len); \
01215     } \
01216     template<typename TVisitor> \
01217     friend void OT__TraverseObject(C *ot__obj, TVisitor *ot__visitor) { \
01218       ot__obj->OT__TraverseObject_(ot__visitor); \
01219     } \
01220    private: \
01221     template<typename TVisitor> \
01222     void OT__TraverseObject_(TVisitor *ot__visitor)
01223 
01239 #define OBJECT_TRAVERSAL_CORE(C) \
01240     OT_RENEW_METHOD(C) \
01241     OT_COPY_METHOD(C) \
01242     OT_PRINT_METHOD(C) \
01243     OBJECT_TRAVERSAL_ONLY(C)
01244 
01311 #define OBJECT_TRAVERSAL(C) \
01312     OT_CONSTRUCTOR(C) \
01313     OT_DESTRUCTOR(C) \
01314     OT_COPY_CONSTRUCTOR(C) \
01315     OBJECT_TRAVERSAL_CORE(C)
01316 
01329 #define OBJECT_TRAVERSAL_NO_COPIES(C) \
01330     OT_CONSTRUCTOR(C) \
01331     OT_DESTRUCTOR(C) \
01332     FORBID_ACCIDENTAL_COPIES(C) \
01333     OBJECT_TRAVERSAL_CORE(C)
01334 
01349 #define OBJECT_TRAVERSAL_DEPRECATED_COPIES(C) \
01350     OT_CONSTRUCTOR(C) \
01351     OT_DESTRUCTOR(C) \
01352     OT_DEPRECATED_COPY_CONSTRUCTOR(C) \
01353     OBJECT_TRAVERSAL_CORE(C)
01354 
01380 #define OBJECT_TRAVERSAL_SHALLOW(C) \
01381    public: \
01382     C() { \
01383       mem::DebugPoison(this); \
01384     } \
01385     ~C() { \
01386       DEBUG_DESTRUCT_OK(this); \
01387       mem::DebugPoison(this); \
01388     } \
01389     friend bool OT__Shallow(const C *ot__obj) { \
01390       return true; \
01391     } \
01392    private: \
01393     OT_IS_ALIAS(C) { return false; } \
01394     OT_DEFAULT_CONSTRUCT(C) {} \
01395     OT_REFILL_TRANSIENTS(C) {} \
01396     OT_TRANSIENTS(C) {} \
01397     OBJECT_TRAVERSAL_CORE(C)
01398 
01399 
01400 
01430 #define OT_CUSTOM_PRINT(C) \
01431    private: \
01432     template<typename TPrintFormat> \
01433     void OT__TraverseObject_(ot__private::Printer<TPrintFormat> *ot__visitor)
01434 
01481 #define OT_CUSTOM_DESTRUCT(C) \
01482    private: \
01483     template<bool t_semi> \
01484     void OT__TraverseObject_(ot__private::Destructor<t_semi> *ot__visitor)
01485 
01486 
01487 
01488 #define NEED_OTRAV_IMPL
01489 #include "fastlib/base/otrav_impl.h"
01490 #undef NEED_OTRAV_IMPL
01491 
01492 
01493 
01516 namespace ot {
01554   template<typename TPrintFormat, typename T>
01555   const char *Print(const T &obj, const char *name, FILE *stream = stdout) {
01556     ot__private::Printer<TPrintFormat> ot__printer(obj, name, stream);
01557     return name;
01558   }
01559   template<typename TPrintFormat, typename T>
01560   void Print(const T &obj, FILE *stream = stdout) {
01561     ot__private::Printer<TPrintFormat> ot__printer(obj, "_", stream);
01562   }
01563 
01580   template<typename T>
01581   const char *Print(const T &obj, const char *name, FILE *stream = stdout) {
01582     return Print<ot::StandardFormat>(obj, name, stream);
01583   }
01584   template<typename T>
01585   void Print(const T &obj, FILE *stream = stdout) {
01586     Print<ot::StandardFormat>(obj, stream);
01587   }
01588 
01589 
01590 
01608   template<typename T>
01609   inline void InitCopy(T *dest, const T &src) {
01610     DEBUG_INIT_OK(dest);
01611     ot__private::Copier<false> ot__copier(dest, &src);
01612   }
01613 
01614 
01615 
01625   template<typename T>
01626   inline size_t FrozenSize(const T &obj) {
01627     ot__private::Freezer<true> ot__freezer(NULL, obj);
01628     return ot__freezer.size();
01629   }
01630 
01698   template<typename T>
01699   inline size_t Freeze(char *block, const T &src) {
01700     ot__private::Freezer<false> ot__freezer(block, src);
01701     return ot__freezer.size();
01702   }
01703 
01714   template<typename T>
01715   inline void InitThaw(T *dest, const char *block) {
01716     DEBUG_INIT_OK(dest);
01717     ot__private::Copier<true> 
01718         ot__copier(dest, reinterpret_cast<const T *>(block));
01719   }
01720 
01721 
01722 
01735   template<typename T>
01736   inline T *SemiCopy(char *block, const T *orig) {
01737     DEBUG_WARN_MSG_IF(block == reinterpret_cast<const char *>(orig),
01738         "In-place SemiCopy may leak memory; probably incorrect.");
01739     ot__private::Relocator<false, true> ot__relocator(block, orig);
01740     return reinterpret_cast<T *>(block);
01741   }
01742   template<typename T>
01743   inline T *SemiCopy(char *block, const char *orig) {
01744     return SemiCopy(block, reinterpret_cast<const T *>(orig));
01745   }
01746 
01773   template<typename T>
01774   inline void SemiFreeze(char *block, const T *orig) {
01775     DEBUG_WARN_MSG_IF(block == reinterpret_cast<const char *>(orig),
01776         "In-place SemiFreeze may leak memory; use SemiFreezeDestruct.");
01777     ot__private::Relocator<true, false> ot__relocator(block, orig);
01778   }
01779   template<typename T>
01780   void SemiFreeze(char *block, const char *orig) {
01781     SemiFreeze(block, reinterpret_cast<const T *>(orig));
01782   }
01783 
01795   template<typename T>
01796   inline T *SemiThaw(char *block) {
01797     return SemiCopy(block, reinterpret_cast<const T *>(NULL));
01798   }
01799 
01808   template<typename T>
01809   inline void SemiDestruct(T *obj) {
01810     ot__private::Destructor<true> ot__destructor(obj);
01811   }
01812   template<typename T>
01813   inline void SemiDestruct(char *block) {
01814     SemiDestruct(reinterpret_cast<T *>(block));
01815   }
01816 
01825   template<typename T>
01826   inline char *SemiFreezeDestruct(T *obj) {
01827     ot__private::Relocator<true, true>
01828         ot__relocator(reinterpret_cast<char *>(obj), obj);
01829     return reinterpret_cast<char *>(obj);
01830   }
01831   template<typename T>
01832   inline char *SemiFreezeDestruct(char *block) {
01833     return SemiFreezeDestruct(reinterpret_cast<T *>(block));
01834   }
01835 
01836 
01837 
01847   template<typename T>
01848   inline size_t SerialSize(const T &obj) {
01849     ot__private::Serializer<true> ot__serializer(obj, NULL);
01850     return ot__serializer.size();
01851   }
01852 
01880   template<typename T>
01881   inline size_t Serialize(const T &obj, FILE *stream) {
01882     ot__private::Serializer<false> ot__serializer(obj, stream);
01883     return ot__serializer.size();
01884   }
01885 
01904   template<typename T>
01905   inline size_t InitDeserialize(T *dest, FILE *stream) {
01906     DEBUG_INIT_OK(dest);
01907     ot__private::Deserializer ot__deserializer(dest, stream);
01908     return ot__deserializer.size();
01909   }
01910 
01911 
01912 
01917   template<typename T>
01918   inline T *Construct(T *array, size_t elems = 1) {
01919     if (OT__ShallowOrPtr(array)) {
01920       return mem::DebugPoison(array, elems);
01921     } else {
01922       return mem::Construct(array, elems);
01923     }
01924   }
01925 
01930   template<typename T>
01931   inline T *Destruct(T *array, size_t elems = 1) {
01932     if (OT__ShallowOrPtr(array)) {
01933       return mem::DebugPoison(array, elems);
01934     } else {
01935       return mem::Destruct(array, elems);
01936     }
01937   }
01938 
01947   template<typename T>
01948   inline T *CopyConstruct(T *dest, const T *src, size_t elems = 1) {
01949     ot__private::Copier<false> ot__copier(dest, src, elems);
01950     return dest;
01951   }
01952 
01960   template<typename T>
01961   inline T *RepeatConstruct(T *array, const T &init, size_t elems) {
01962     for (size_t i = 0; i < elems; ++i) {
01963       ot__private::Copier<false> ot__copier(array + i, &init);
01964     }
01965     return array;
01966   }
01967 
01969 
01971   template<typename T>
01972   COMPILER_DEPRECATED
01973   void Copy(const T &src, T *dest) {
01974     InitCopy(dest, src);
01975   }
01976 
01978   template<typename T>
01979   COMPILER_DEPRECATED
01980   size_t PointerFrozenSize(const T &obj) {
01981     return FrozenSize(obj);
01982   }
01983 
01985   template<typename T>
01986   COMPILER_DEPRECATED
01987   void PointerFreeze(const T &obj, char *block) {
01988     Freeze(block, obj);
01989   }
01990 
01992   template<typename T>
01993   COMPILER_DEPRECATED
01994   void PointerRefreeze(const T *src, char *dest) {
01995     SemiFreeze(dest, src);
01996   }
01997 
01999   template<typename T>
02000   COMPILER_DEPRECATED
02001   T *PointerThaw(char *block) {
02002     return SemiThaw<T>(block);
02003   }
02004 
02006   template<typename T>
02007   COMPILER_DEPRECATED
02008   void PointerRelocate(const char *old_loc, char *new_loc) {
02009     /*
02010      * TODO: Perhaps detect if Shallow, doing nothing, or try function
02011      * FixTransients, which by default deallocates them and
02012      * reallocates them and can be redefined to blank.  Carefully
02013      * consider Swap behavior in cachearray_impl.h.
02014      */
02015     // leaks memory for allocated transients
02016     SemiCopy<T>(new_loc, old_loc);
02017   }
02018 };
02019 
02021 
02022 #define OT_MY_OBJECT OT_OBJ
02023 #define OT_MY_ARRAY OT_STATIC_ARRAY
02024 #define OT_MALLOC_ARRAY OT_ALLOC
02025 #define OT_PTR_NULLABLE OT_PTR
02026 
02027 #define OT_FIX OT_REFILL_TRANSIENTS
02028 
02029 #define OT_DEF OBJECT_TRAVERSAL
02030 #define OT_DEF_BASIC OBJECT_TRAVERSAL
02031 
02032 #endif /* BASE_OTRAV_H */
Generated on Mon Jan 24 12:04:37 2011 for FASTlib by  doxygen 1.6.3