// @(#)root/cont:$Id$
// Author: Rene Brun   28/09/2001

/*************************************************************************
 * 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_TProcessID
#define ROOT_TProcessID


//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TProcessID                                                           //
//                                                                      //
// Process Identifier object                                            //
//                                                                      //
//////////////////////////////////////////////////////////////////////////


#ifndef ROOT_TNamed
#include "TNamed.h"
#endif
#ifndef ROOT_TObjArray
#include "TObjArray.h"
#endif

#include <atomic>
#include <type_traits>

class TExMap;

namespace ROOT {
   namespace Internal {
     /**
      * \class ROOT::Internal::TAtomicPointer
      * \brief Helper class to manage atomic pointers.
      * \tparam T Pointer type to be made atomic
      *
      * Helper class to manage atomic pointers. The class enforces that the templated type
      * is a pointer.
      */
      template <typename T> class TAtomicPointer {
         private:
            std::atomic<T> fAtomic;

         public:
            TAtomicPointer() : fAtomic(nullptr)
            {
               static_assert(std::is_pointer<T>::value, "Only pointer types supported");
            }

            ~TAtomicPointer() { delete fAtomic.load(); }

            T operator->() const { return fAtomic; }

            operator T() const { return fAtomic; }

            T operator=(const T& t)
            {
               fAtomic = t;
               return t;
            }
      };
   } // End of namespace Internal
} // End of namespace ROOT


class TProcessID : public TNamed {

private:
   TProcessID(const TProcessID &ref);            // TProcessID are not copiable.
   TProcessID& operator=(const TProcessID &ref); // TProcessID are not copiable.

protected:
   std::atomic_int    fCount;                           //!Reference count to this object (from TFile)
   ROOT::Internal::TAtomicPointer<TObjArray*> fObjects; //!Array pointing to the referenced objects
   std::atomic_flag   fLock;                            //!Spin lock for initialization of fObjects

   static TProcessID *fgPID;      //Pointer to current session ProcessID
   static TObjArray  *fgPIDs;     //Table of ProcessIDs
   static TExMap     *fgObjPIDs;  //Table pointer to pids
   static UInt_t      fgNumber;   //Referenced objects count

public:
   TProcessID();
   virtual ~TProcessID();
   void             CheckInit();
   virtual void     Clear(Option_t *option="");
   Int_t            DecrementCount();
   Int_t            IncrementCount();
   Int_t            GetCount() const {return fCount;}
   TObjArray       *GetObjects() const {return fObjects;}
   TObject         *GetObjectWithID(UInt_t uid);
   void             PutObjectWithID(TObject *obj, UInt_t uid=0);
   virtual void     RecursiveRemove(TObject *obj);

   static TProcessID  *AddProcessID();
   static UInt_t       AssignID(TObject *obj);
   static void         Cleanup();
   static UInt_t       GetNProcessIDs();
   static TProcessID  *GetPID();
   static TObjArray   *GetPIDs();
   static TProcessID  *GetProcessID(UShort_t pid);
   static TProcessID  *GetProcessWithUID(const TObject *obj);
   static TProcessID  *GetProcessWithUID(UInt_t uid,const void *obj);
   static TProcessID  *GetSessionProcessID();
   static  UInt_t      GetObjectCount();
   static  Bool_t      IsValid(TProcessID *pid);
   static  void        SetObjectCount(UInt_t number);

   ClassDef(TProcessID,1)  //Process Unique Identifier in time and space
};

#endif
 TProcessID.h:1
 TProcessID.h:2
 TProcessID.h:3
 TProcessID.h:4
 TProcessID.h:5
 TProcessID.h:6
 TProcessID.h:7
 TProcessID.h:8
 TProcessID.h:9
 TProcessID.h:10
 TProcessID.h:11
 TProcessID.h:12
 TProcessID.h:13
 TProcessID.h:14
 TProcessID.h:15
 TProcessID.h:16
 TProcessID.h:17
 TProcessID.h:18
 TProcessID.h:19
 TProcessID.h:20
 TProcessID.h:21
 TProcessID.h:22
 TProcessID.h:23
 TProcessID.h:24
 TProcessID.h:25
 TProcessID.h:26
 TProcessID.h:27
 TProcessID.h:28
 TProcessID.h:29
 TProcessID.h:30
 TProcessID.h:31
 TProcessID.h:32
 TProcessID.h:33
 TProcessID.h:34
 TProcessID.h:35
 TProcessID.h:36
 TProcessID.h:37
 TProcessID.h:38
 TProcessID.h:39
 TProcessID.h:40
 TProcessID.h:41
 TProcessID.h:42
 TProcessID.h:43
 TProcessID.h:44
 TProcessID.h:45
 TProcessID.h:46
 TProcessID.h:47
 TProcessID.h:48
 TProcessID.h:49
 TProcessID.h:50
 TProcessID.h:51
 TProcessID.h:52
 TProcessID.h:53
 TProcessID.h:54
 TProcessID.h:55
 TProcessID.h:56
 TProcessID.h:57
 TProcessID.h:58
 TProcessID.h:59
 TProcessID.h:60
 TProcessID.h:61
 TProcessID.h:62
 TProcessID.h:63
 TProcessID.h:64
 TProcessID.h:65
 TProcessID.h:66
 TProcessID.h:67
 TProcessID.h:68
 TProcessID.h:69
 TProcessID.h:70
 TProcessID.h:71
 TProcessID.h:72
 TProcessID.h:73
 TProcessID.h:74
 TProcessID.h:75
 TProcessID.h:76
 TProcessID.h:77
 TProcessID.h:78
 TProcessID.h:79
 TProcessID.h:80
 TProcessID.h:81
 TProcessID.h:82
 TProcessID.h:83
 TProcessID.h:84
 TProcessID.h:85
 TProcessID.h:86
 TProcessID.h:87
 TProcessID.h:88
 TProcessID.h:89
 TProcessID.h:90
 TProcessID.h:91
 TProcessID.h:92
 TProcessID.h:93
 TProcessID.h:94
 TProcessID.h:95
 TProcessID.h:96
 TProcessID.h:97
 TProcessID.h:98
 TProcessID.h:99
 TProcessID.h:100
 TProcessID.h:101
 TProcessID.h:102
 TProcessID.h:103
 TProcessID.h:104
 TProcessID.h:105
 TProcessID.h:106
 TProcessID.h:107
 TProcessID.h:108
 TProcessID.h:109
 TProcessID.h:110
 TProcessID.h:111
 TProcessID.h:112
 TProcessID.h:113
 TProcessID.h:114
 TProcessID.h:115
 TProcessID.h:116
 TProcessID.h:117
 TProcessID.h:118
 TProcessID.h:119