TGenCollectionProxy.h

Go to the documentation of this file.
00001 // @(#)root/io:$Id: TGenCollectionProxy.h 36061 2010-10-04 16:05:51Z pcanal $
00002 // Author: Markus Frank  28/10/04
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 #ifndef ROOT_TGenCollectionProxy
00012 #define ROOT_TGenCollectionProxy
00013 
00014 //////////////////////////////////////////////////////////////////////////
00015 //                                                                      //
00016 // TGenCollectionProxy
00017 //
00018 // Proxy around an arbitrary container, which implements basic
00019 // functionality and iteration.
00020 //
00021 // In particular this is used to implement splitting and abstract
00022 // element access of any container. Access to compiled code is necessary
00023 // to implement the abstract iteration sequence and functionality like
00024 // size(), clear(), resize(). resize() may be a void operation.
00025 //
00026 //////////////////////////////////////////////////////////////////////////
00027 
00028 #ifndef ROOT_TVirtualCollectionProxy
00029 #include "TVirtualCollectionProxy.h"
00030 #endif
00031 
00032 #ifndef ROOT_TCollectionProxyInfo
00033 #include "TCollectionProxyInfo.h"
00034 #endif
00035 
00036 #include <typeinfo>
00037 #include <string>
00038 #include <map>
00039 #ifndef __CINT__
00040 #if defined(__APPLE__)
00041 #include <stdlib.h>
00042 #else
00043 #include <malloc.h>
00044 #endif
00045 #endif
00046 class TObjArray;
00047 class TCollectionProxyFactory;
00048 
00049 class TGenCollectionProxy
00050    : public TVirtualCollectionProxy
00051 {
00052 
00053    // Friend declaration
00054    friend class TCollectionProxyFactory;
00055 
00056 public:
00057 
00058 #ifdef R__HPUX
00059    typedef const type_info&      Info_t;
00060 #else
00061    typedef const std::type_info& Info_t;
00062 #endif
00063 
00064    enum {
00065       // Those 'bits' are used in conjunction with CINT's bit to store the 'type'
00066       // info into one int
00067       kBIT_ISSTRING   = 0x20000000,  // We can optimized a value operation when the content are strings
00068       kBIT_ISTSTRING  = 0x40000000,
00069       kBOOL_t = 21
00070    };
00071 
00072    /** @class TGenCollectionProxy::Value TGenCollectionProxy.h TGenCollectionProxy.h
00073     *
00074     * Small helper to describe the Value_type or the key_type
00075     * of an STL container.
00076     *
00077     * @author  M.Frank
00078     * @version 1.0
00079     * @date    10/10/2004
00080     */
00081    struct Value  {
00082       ROOT::NewFunc_t fCtor;       // Method cache for containee constructor
00083       ROOT::DesFunc_t fDtor;       // Method cache for containee destructor
00084       ROOT::DelFunc_t fDelete;     // Method cache for containee delete
00085       unsigned int    fCase;       // type of data of Value_type
00086       TClassRef       fType;       // TClass reference of Value_type in collection
00087       EDataType       fKind;       // kind of ROOT-fundamental type
00088       size_t          fSize;       // fSize of the contained object
00089 
00090       // Copy constructor
00091       Value(const Value& inside);
00092       // Initializing constructor
00093       Value(const std::string& info);
00094       // Delete individual item from STL container
00095       void DeleteItem(void* ptr);
00096       
00097       Bool_t IsValid();
00098    };
00099 
00100    /**@class StreamHelper
00101     *
00102     * Helper class to facilitate I/O
00103     *
00104     * @author  M.Frank
00105     * @version 1.0
00106     * @date    10/10/2004
00107     */
00108    union StreamHelper  {
00109       Bool_t       boolean;
00110       Char_t       s_char;
00111       Short_t      s_short;
00112       Int_t        s_int;
00113       Long_t       s_long;
00114       Long64_t     s_longlong;
00115       Float_t      flt;
00116       Double_t     dbl;
00117       UChar_t      u_char;
00118       UShort_t     u_short;
00119       UInt_t       u_int;
00120       ULong_t      u_long;
00121       ULong64_t    u_longlong;
00122       void*        p_void;
00123       void**       pp_void;
00124       char*        kchar;
00125       TString*     tstr;
00126       void* ptr()  {
00127          return *(&this->p_void);
00128       }
00129       std::string* str()  {
00130          return (std::string*)this;
00131       }
00132       const char* c_str()  {
00133          return ((std::string*)this)->c_str();
00134       }
00135       const char* c_pstr()  {
00136          return (*(std::string**)this)->c_str();
00137       }
00138       void set(void* p)  {
00139          *(&this->p_void) = p;
00140       }
00141       void read_std_string(TBuffer& b) {
00142          TString s;
00143          s.Streamer(b);
00144          ((std::string*)this)->assign(s.Data());
00145       }
00146       void* read_tstring(TBuffer& b)  {
00147          *((TString*)this) = "";
00148          ((TString*)this)->Streamer(b);
00149          return this;
00150       }
00151       void read_std_string_pointer(TBuffer& b) {
00152          TString s;
00153          std::string* str2 = (std::string*)ptr();
00154          if (!str2) str2 = new std::string();
00155          s.Streamer(b);
00156          *str2 = s;
00157          set(str2);
00158       }
00159       void write_std_string_pointer(TBuffer& b)  {
00160          const char* c;
00161          if (ptr()) {
00162             std::string* strptr = (*(std::string**)this);
00163             c = (const char*)(strptr->c_str());
00164          } else c = "";
00165          TString(c).Streamer(b);
00166       }
00167       void read_any_object(Value* v, TBuffer& b)  {
00168          void* p = ptr();
00169          if ( p )  {
00170             if ( v->fDelete )  {    // Compiled content: call Destructor
00171                (*v->fDelete)(p);
00172             }
00173             else if ( v->fType )  { // Emulated content: call TClass::Delete
00174                v->fType->Destructor(p);
00175             }
00176             else if ( v->fDtor )  {
00177                (*v->fDtor)(p);
00178                ::operator delete(p);
00179             }
00180             else  {
00181                ::operator delete(p);
00182             }
00183          }
00184          set( b.ReadObjectAny(v->fType) );
00185       }
00186 
00187       void read_tstring_pointer(Bool_t vsn3, TBuffer& b)  {
00188          TString* s = (TString*)ptr();
00189          if ( vsn3 )  {
00190             if ( !s ) s = new TString();
00191             s->Replace(0, s->Length(), 0, 0);
00192             s->Streamer(b);
00193             set(s);
00194             return;
00195          }
00196          if ( s ) delete s;
00197          set( b.ReadObjectAny(TString::Class()) );
00198       }
00199       void write_tstring_pointer(TBuffer& b)  {
00200          b.WriteObjectAny(ptr(), TString::Class());
00201       }
00202    };
00203 
00204    /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h
00205     *
00206     * Small helper to execute (compiler) generated function for the
00207     * access to STL or other containers.
00208     *
00209     * @author  M.Frank
00210     * @version 1.0
00211     * @date    10/10/2004
00212     */
00213    class Method  {
00214    public:
00215       typedef void* (*Call_t)(void*);
00216       Call_t call;
00217       Method() : call(0)                       {      }
00218       Method(Call_t c) : call(c)               {      }
00219       Method(const Method& m) : call(m.call)   {      }
00220       void* invoke(void* obj) const { return (*call)(obj); }
00221    };
00222 
00223    /** @class TGenCollectionProxy::Method TGenCollectionProxy.h TGenCollectionProxy.h
00224     *
00225     * Small helper to execute (compiler) generated function for the
00226     * access to STL or other containers.
00227     *
00228     * @author  M.Frank
00229     * @version 1.0
00230     * @date    10/10/2004
00231     */
00232    class Method0  {
00233    public:
00234       typedef void* (*Call_t)();
00235       Call_t call;
00236       Method0() : call(0)                       {      }
00237       Method0(Call_t c) : call(c)               {      }
00238       Method0(const Method0& m) : call(m.call)   {      }
00239       void* invoke() const { return (*call)(); }
00240    };
00241  
00242    /** @class TGenCollectionProxy::TStaging
00243     *
00244     * Small helper to stage the content of an associative
00245     * container when reading and before inserting it in the 
00246     * actual collection.
00247     *
00248     * @author  Ph.Canal
00249     * @version 1.0
00250     * @date    20/08/2010
00251     */
00252    class TStaging  {
00253       void   *fTarget;   // Pointer to the collection we are staging for.
00254       void   *fContent;  // Pointer to the content
00255       size_t  fReserved; // Amount of space already reserved.
00256       size_t  fSize;     // Number of elements
00257       size_t  fSizeOf;   // size of each elements
00258    public:
00259       TStaging(size_t size, size_t size_of) : fTarget(0), fContent(0), fReserved(0), fSize(size), fSizeOf(size_of)
00260       {
00261          // Usual constructor.  Reserves the required number of elements.
00262          fReserved = fSize;
00263          fContent = ::malloc(fReserved * fSizeOf);
00264       }
00265       
00266       ~TStaging() {
00267          // Usual destructor
00268          ::free(fContent);
00269       }
00270       
00271       void   *GetContent() {
00272          // Return the location of the array of content.
00273          return fContent;
00274       }
00275       void   *GetEnd() {
00276          // Return the 'end' of the array of content.
00277          return ((char*)fContent) + fSize*fSizeOf;
00278       }
00279       size_t  GetSize() {
00280          // Return the number of elements. 
00281          return fSize;
00282       }
00283       void   *GetTarget() {
00284          // Get the address of the collection we are staging for.
00285          return fTarget;
00286       }
00287       void    Resize(size_t nelement) {
00288          if (fReserved < nelement) {
00289             fReserved = nelement;
00290             fContent = ::realloc(fContent,fReserved * fSizeOf);
00291          }
00292          fSize = nelement;
00293       }
00294       void SetTarget(void *target) {
00295          // Set the collection we are staging for.
00296          fTarget = target;
00297       }
00298    };
00299    
00300 protected:
00301    typedef ROOT::TCollectionProxyInfo::Environ<char[64]> Env_t;
00302    typedef ROOT::TCollectionProxyInfo::EnvironBase EnvironBase_t;
00303    typedef std::vector<TStaging*>          Staged_t;  // Collection of pre-allocated staged array for associative containers.
00304    typedef std::vector<EnvironBase_t*>     Proxies_t;
00305    mutable TObjArray *fReadMemberWise;                                   //Array of bundle of TStreamerInfoActions to stream out (read)
00306    mutable std::map<std::string, TObjArray*> *fConversionReadMemberWise; //Array of bundle of TStreamerInfoActions to stream out (read) derived from another class.
00307    typedef void (*Sizing_t)(void *obj, size_t size);
00308    typedef void* (*Feedfunc_t)(void *from, void *to, size_t size);
00309    typedef void* (*ArrIterfunc_t)(void *from, size_t size);
00310 
00311    std::string   fName;      // Name of the class being proxied.
00312    Bool_t        fPointers;  // Flag to indicate if containee has pointers (key or value)
00313    Method        fClear;     // Method cache for container accessors: clear container
00314    Method        fSize;      // Container accessors: size of container
00315    Sizing_t      fResize;    // Container accessors: resize container
00316    Method        fFirst;     // Container accessors: generic iteration: first
00317    Method        fNext;      // Container accessors: generic iteration: next
00318    ArrIterfunc_t fConstruct; // Container accessors: block construct
00319    Sizing_t      fDestruct;  // Container accessors: block destruct
00320    Feedfunc_t    fFeed;      // Container accessors: block feed
00321    Method        fCollect;   // Method to collect objects from container
00322    Method0       fCreateEnv; // Method to allocate an Environment holder.
00323    Value*        fValue;     // Descriptor of the container value type
00324    Value*        fVal;       // Descriptor of the Value_type
00325    Value*        fKey;       // Descriptor of the key_type
00326    EnvironBase_t*fEnv;       // Address of the currently proxied object
00327    int           fValOffset; // Offset from key to value (in maps)
00328    int           fValDiff;   // Offset between two consecutive value_types (memory layout).
00329    Proxies_t     fProxyList; // Stack of recursive proxies
00330    Proxies_t     fProxyKept; // Optimization: Keep proxies once they were created
00331    Staged_t      fStaged;    // Optimization: Keep staged array once they were created
00332    int           fSTL_type;  // STL container type
00333    Info_t        fTypeinfo;  // Type information
00334    TClass*       fOnFileClass; // On file class
00335    
00336    CreateIterators_t    fFunctionCreateIterators;
00337    DeleteTwoIterators_t fFunctionDeleteTwoIterators;
00338 
00339    // Late initialization of collection proxy
00340    TGenCollectionProxy* Initialize() const;
00341    // Some hack to avoid const-ness.
00342    virtual TGenCollectionProxy* InitializeEx();
00343    // Call to delete/destruct individual contained item.
00344    virtual void DeleteItem(Bool_t force, void* ptr) const;
00345    // Allow to check function pointers.
00346    void CheckFunctions()  const;
00347 private:
00348    TGenCollectionProxy(); // not implemented on purpose.
00349    
00350 public:
00351 
00352    // Virtual copy constructor.
00353    virtual TVirtualCollectionProxy* Generate() const;
00354 
00355    // Copy constructor.
00356    TGenCollectionProxy(const TGenCollectionProxy& copy);
00357 
00358    // Initializing constructor
00359    TGenCollectionProxy(Info_t typ, size_t iter_size);
00360    TGenCollectionProxy(const ROOT::TCollectionProxyInfo &info, TClass *cl);
00361 
00362    // Standard destructor.
00363    virtual ~TGenCollectionProxy();
00364 
00365    // Return a pointer to the TClass representing the container.
00366    virtual TClass *GetCollectionClass();
00367 
00368    // Return the type of collection see TClassEdit::ESTLType
00369    virtual Int_t   GetCollectionType();
00370 
00371    // Return the offset between two consecutive value_types (memory layout).
00372    virtual ULong_t   GetIncrement();
00373 
00374    // Return the sizeof the collection object.
00375    virtual UInt_t Sizeof() const;
00376 
00377    // Push new proxy environment.
00378    virtual void PushProxy(void *objstart);
00379 
00380    // Pop old proxy environment.
00381    virtual void PopProxy();
00382 
00383    // Return true if the content is of type 'pointer to'.
00384    virtual Bool_t HasPointers() const;
00385 
00386    // Return a pointer to the TClass representing the content.
00387    virtual TClass *GetValueClass();
00388 
00389    // Set pointer to the TClass representing the content.
00390    virtual void SetValueClass(TClass *newcl);
00391 
00392    // If the content is a simple numerical value, return its type (see TDataType).
00393    virtual EDataType GetType();
00394 
00395    // Return the address of the value at index 'idx'.
00396    virtual void *At(UInt_t idx);
00397 
00398    // Clear the container.
00399    virtual void Clear(const char *opt = "");
00400 
00401    // Resize the container.
00402    virtual void Resize(UInt_t n, Bool_t force_delete);
00403 
00404    // Return the current size of the container.
00405    virtual UInt_t Size() const;
00406 
00407    // Block allocation of containees.
00408    virtual void* Allocate(UInt_t n, Bool_t forceDelete);
00409 
00410    // Block commit of containees.
00411    virtual void Commit(void* env);
00412 
00413    // Streamer function.
00414    virtual void Streamer(TBuffer &refBuffer);
00415 
00416    // Streamer I/O overload.
00417    virtual void Streamer(TBuffer &refBuffer, void *pObject, int siz);
00418 
00419    // TClassStreamer I/O overload.
00420    virtual void operator()(TBuffer &refBuffer, void *pObject);
00421    
00422    // Routine to read the content of the buffer into 'obj'.
00423    virtual void ReadBuffer(TBuffer &b, void *obj);
00424    virtual void ReadBuffer(TBuffer &b, void *obj, const TClass *onfileClass);
00425 
00426    virtual void SetOnFileClass( TClass* cl ) { fOnFileClass = cl; }
00427    virtual TClass* GetOnFileClass() const { return fOnFileClass; }
00428 
00429    // MemberWise actions
00430    virtual TStreamerInfoActions::TActionSequence *GetConversionReadMemberWiseActions(TClass *oldClass, Int_t version);
00431    virtual TStreamerInfoActions::TActionSequence *GetReadMemberWiseActions(Int_t version);
00432    virtual TStreamerInfoActions::TActionSequence *GetWriteMemberWiseActions();
00433 
00434    // Set of functions to iterate easily throught the collection
00435    
00436    virtual CreateIterators_t GetFunctionCreateIterators(Bool_t read = kTRUE); 
00437    // typedef void (*CreateIterators_t)(void *collection, void **begin_arena, void **end_arena);
00438    // begin_arena and end_arena should contain the location of a memory arena of size fgIteratorSize. 
00439    // If the collection iterator are of that size or less, the iterators will be constructed in place in those location (new with placement)
00440    // Otherwise the iterators will be allocated via a regular new and their address returned by modifying the value of begin_arena and end_arena.
00441    
00442    virtual CopyIterator_t GetFunctionCopyIterator(Bool_t read = kTRUE);
00443    // typedef void* (*CopyIterator_t)(void *dest, const void *source);
00444    // Copy the iterator source, into dest.   dest should contain the location of a memory arena of size fgIteratorSize.
00445    // If the collection iterator is of that size or less, the iterator will be constructed in place in this location (new with placement)
00446    // Otherwise the iterator will be allocated via a regular new and its address returned by modifying the value of dest.
00447    
00448    virtual Next_t GetFunctionNext(Bool_t read = kTRUE);
00449    // typedef void* (*Next_t)(void *iter, const void *end);
00450    // iter and end should be pointers to respectively an iterator to be incremented and the result of collection.end()
00451    // If the iterator has not reached the end of the collection, 'Next' increment the iterator 'iter' and return 0 if 
00452    // the iterator reached the end.
00453    // If the end was not reached, 'Next' returns the address of the content pointed to by the iterator before the 
00454    // incrementation ; if the collection contains pointers, 'Next' will return the value of the pointer.
00455    
00456    virtual DeleteIterator_t GetFunctionDeleteIterator(Bool_t read = kTRUE);
00457    virtual DeleteTwoIterators_t GetFunctionDeleteTwoIterators(Bool_t read = kTRUE);
00458    // typedef void (*DeleteIterator_t)(void *iter);
00459    // typedef void (*DeleteTwoIterators_t)(void *begin, void *end);
00460    // If the size of the iterator is greater than fgIteratorArenaSize, call delete on the addresses,
00461    // Otherwise just call the iterator's destructor.
00462    
00463 };
00464 
00465 template <typename T>
00466 struct AnyCollectionProxy : public TGenCollectionProxy  {
00467    AnyCollectionProxy()
00468       : TGenCollectionProxy(typeid(T::Cont_t),sizeof(T::Iter_t))
00469    {
00470       // Constructor.
00471       fValDiff        = sizeof(T::Value_t);
00472       fValOffset      = T::value_offset();
00473       fSize.call      = T::size;
00474       fResize         = T::resize;
00475       fNext.call      = T::next;
00476       fFirst.call     = T::first;
00477       fClear.call     = T::clear;
00478       fConstruct      = T::construct;
00479       fDestruct       = T::destruct;
00480       fFeed           = T::feed;
00481       CheckFunctions();
00482    }
00483    virtual ~AnyCollectionProxy() {  }
00484 };
00485 
00486 #endif
00487 

Generated on Tue Jul 5 14:26:56 2011 for ROOT_528-00b_version by  doxygen 1.5.1