// @(#)root/meta:$Id$
// Author: Markus Frank 20/05/2005

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TIsAProxy
#define ROOT_TIsAProxy

#ifndef ROOT_TVirtualIsAProxy
#include "TVirtualIsAProxy.h"
#endif
#ifndef ROOT_Rtypes
#include "Rtypes.h"
#endif
#include <atomic>

class TClass;

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TIsAProxy implementation class.                                      //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
class TIsAProxy  : public TVirtualIsAProxy {
private:
   template <typename T> using Atomic_t = std::atomic<T>;

   const type_info          *fType;        //Actual typeid of the proxy
   Atomic_t<TClass*>         fClass;       //Actual TClass
   Atomic_t<void*>           fLast;        //points into fSubTypes map for last used values
   Char_t                    fSubTypes[72];//map of known sub-types
   mutable Atomic_t<UInt_t>  fSubTypesReaders; //number of readers of fSubTypes
   Atomic_t<Bool_t>          fSubTypesWriteLockTaken; //True if there is a writer
   Bool_t                    fVirtual;     //Flag if class is virtual
   Atomic_t<Bool_t>          fInit;        //Initialization flag

   void* FindSubType(const type_info*) const;
   void* CacheSubType(const type_info*, TClass*);
protected:
   TIsAProxy(const TIsAProxy&) = delete;
   TIsAProxy& operator=(const TIsAProxy&) = delete;

public:
   // Standard initializing constructor
   TIsAProxy(const type_info &typ);
   // Standard destructor
   virtual ~TIsAProxy();
   // Callbacl to set the class
   virtual void SetClass(TClass *cl);
   // IsA callback
   virtual TClass* operator()(const void *obj);
};

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TInstrumentedIsAProxy implementation class.                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////
template <class T> class TInstrumentedIsAProxy : public TVirtualIsAProxy {

private:
   TClass *fClass;        //Actual TClass

protected:
   TInstrumentedIsAProxy(const TInstrumentedIsAProxy& iip) :
     TVirtualIsAProxy(iip), fClass(iip.fClass) { }
   TInstrumentedIsAProxy& operator=(const TInstrumentedIsAProxy& iip)
     {if(this!=&iip) {TVirtualIsAProxy::operator=(iip); fClass=iip.fClass;}
     return *this;}

public:
   // Standard initializing constructor
   TInstrumentedIsAProxy(TClass *cl) : fClass(cl)      {}
   // Standard destructor
   virtual ~TInstrumentedIsAProxy()                    {}
   // Callbacl to set the class
   virtual void SetClass(TClass *cl)                   { fClass = cl; }
   // IsA callback
   virtual TClass* operator()(const void *obj) {
      return obj==0 ? fClass : ((const T*)obj)->IsA();
   }
};

#endif // ROOT_TIsAProxy
 TIsAProxy.h:1
 TIsAProxy.h:2
 TIsAProxy.h:3
 TIsAProxy.h:4
 TIsAProxy.h:5
 TIsAProxy.h:6
 TIsAProxy.h:7
 TIsAProxy.h:8
 TIsAProxy.h:9
 TIsAProxy.h:10
 TIsAProxy.h:11
 TIsAProxy.h:12
 TIsAProxy.h:13
 TIsAProxy.h:14
 TIsAProxy.h:15
 TIsAProxy.h:16
 TIsAProxy.h:17
 TIsAProxy.h:18
 TIsAProxy.h:19
 TIsAProxy.h:20
 TIsAProxy.h:21
 TIsAProxy.h:22
 TIsAProxy.h:23
 TIsAProxy.h:24
 TIsAProxy.h:25
 TIsAProxy.h:26
 TIsAProxy.h:27
 TIsAProxy.h:28
 TIsAProxy.h:29
 TIsAProxy.h:30
 TIsAProxy.h:31
 TIsAProxy.h:32
 TIsAProxy.h:33
 TIsAProxy.h:34
 TIsAProxy.h:35
 TIsAProxy.h:36
 TIsAProxy.h:37
 TIsAProxy.h:38
 TIsAProxy.h:39
 TIsAProxy.h:40
 TIsAProxy.h:41
 TIsAProxy.h:42
 TIsAProxy.h:43
 TIsAProxy.h:44
 TIsAProxy.h:45
 TIsAProxy.h:46
 TIsAProxy.h:47
 TIsAProxy.h:48
 TIsAProxy.h:49
 TIsAProxy.h:50
 TIsAProxy.h:51
 TIsAProxy.h:52
 TIsAProxy.h:53
 TIsAProxy.h:54
 TIsAProxy.h:55
 TIsAProxy.h:56
 TIsAProxy.h:57
 TIsAProxy.h:58
 TIsAProxy.h:59
 TIsAProxy.h:60
 TIsAProxy.h:61
 TIsAProxy.h:62
 TIsAProxy.h:63
 TIsAProxy.h:64
 TIsAProxy.h:65
 TIsAProxy.h:66
 TIsAProxy.h:67
 TIsAProxy.h:68
 TIsAProxy.h:69
 TIsAProxy.h:70
 TIsAProxy.h:71
 TIsAProxy.h:72
 TIsAProxy.h:73
 TIsAProxy.h:74
 TIsAProxy.h:75
 TIsAProxy.h:76
 TIsAProxy.h:77
 TIsAProxy.h:78
 TIsAProxy.h:79
 TIsAProxy.h:80
 TIsAProxy.h:81
 TIsAProxy.h:82
 TIsAProxy.h:83
 TIsAProxy.h:84
 TIsAProxy.h:85
 TIsAProxy.h:86
 TIsAProxy.h:87
 TIsAProxy.h:88
 TIsAProxy.h:89
 TIsAProxy.h:90