/*****************************************************************************
 * Project: RooFit                                                           *
 * Package: RooFitCore                                                       *
 *    File: $Id$
 * Authors:                                                                  *
 *   WV, Wouter Verkerke, UC Santa Barbara, verkerke@slac.stanford.edu       *
 *   DK, David Kirkby,    UC Irvine,         dkirkby@uci.edu                 *
 *                                                                           *
 * Copyright (c) 2000-2005, Regents of the University of California          *
 *                          and Stanford University. All rights reserved.    *
 *                                                                           *
 * Redistribution and use in source and binary forms,                        *
 * with or without modification, are permitted according to the terms        *
 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)             *
 *****************************************************************************/
#ifndef ROO_CACHE_MANAGER
#define ROO_CACHE_MANAGER

#include "Rtypes.h"

#include "RooMsgService.h"
#include "RooNormSetCache.h"
#include "RooAbsReal.h"
#include "RooArgSet.h"
#include "RooArgList.h"
#include "RooAbsCache.h"
#include "RooAbsCacheElement.h"
#include "RooNameReg.h"
#include <vector>

class RooNameSet ;


template<class T>
class RooCacheManager : public RooAbsCache {

public:

  RooCacheManager(Int_t maxSize=2) ;
  RooCacheManager(RooAbsArg* owner, Int_t maxSize=2) ;
  RooCacheManager(const RooCacheManager& other, RooAbsArg* owner=0) ;
  virtual ~RooCacheManager() ;
  
  T* getObj(const RooArgSet* nset, Int_t* sterileIndex=0, const TNamed* isetRangeName=0) {
    // Getter function without integration set 
    return getObj(nset,0,sterileIndex,isetRangeName) ;
  }

  Int_t setObj(const RooArgSet* nset, T* obj, const TNamed* isetRangeName=0) {
    // Setter function without integration set 
    return setObj(nset,0,obj,isetRangeName) ;
  }

  inline T* getObj(const RooArgSet* nset, const RooArgSet* iset, Int_t* sterileIdx, const char* isetRangeName)  {
    if (_wired) return _object[0] ;
    return getObj(nset,iset,sterileIdx,RooNameReg::ptr(isetRangeName)) ;
  }

  T* getObj(const RooArgSet* nset, const RooArgSet* iset, Int_t* sterileIndex=0, const TNamed* isetRangeName=0) ;
  Int_t setObj(const RooArgSet* nset, const RooArgSet* iset, T* obj, const TNamed* isetRangeName=0) ;  

  void reset() ;
  virtual void sterilize() ;

  Int_t lastIndex() const { 
    // Return index of slot used in last get or set operation
    return _lastIndex ; 
  }
  Int_t cacheSize() const { 
    // Return size of cache
    return _size ; 
  }

  virtual Bool_t redirectServersHook(const RooAbsCollection& /*newServerList*/, Bool_t /*mustReplaceAll*/, 
				     Bool_t /*nameChange*/, Bool_t /*isRecursive*/) { 
    // Interface function to intercept server redirects
    return kFALSE ; 
  }
  virtual void operModeHook() {
    // Interface function to intercept cache operation mode changes
  }
  virtual void printCompactTreeHook(std::ostream&, const char *) {
    // Interface function to cache add contents to output in tree printing mode
  } 

  T* getObjByIndex(Int_t index) const ;
  const RooNameSet* nameSet1ByIndex(Int_t index) const ;
  const RooNameSet* nameSet2ByIndex(Int_t index) const ;

  virtual void insertObjectHook(T&) {
    // Interface function to perform post-insert operations on cached object
  } 

  void wireCache() {
    if (_size==0) {
      oocoutI(_owner,Optimization) << "RooCacheManager::wireCache(" << _owner->GetName() << ") no cached elements!" << std::endl ;
    } else if (_size==1) {
      oocoutI(_owner,Optimization) << "RooCacheManager::wireCache(" << _owner->GetName() << ") now wiring cache" << std::endl ;
      _wired=kTRUE ;
    } else if (_size>1) {
      oocoutI(_owner,Optimization) << "RooCacheManager::wireCache(" << _owner->GetName() << ") cache cannot be wired because it contains more than one element" << std::endl ; 
    }
  }
 
protected:

  Int_t _maxSize ;    //! Maximum size
  Int_t _size ;       //! Actual use
  Int_t _lastIndex ;  //! Last slot accessed

  std::vector<RooNormSetCache> _nsetCache ; //! Normalization/Integration set manager
  std::vector<T*> _object ;                 //! Payload
  Bool_t _wired ;               //! In wired mode, there is a single payload which is returned always

  ClassDef(RooCacheManager,2) // Cache Manager class generic objects
} ;


template<class T>
RooCacheManager<T>::RooCacheManager(Int_t maxSize) : RooAbsCache(0)
{
  // Constructor for simple caches without RooAbsArg payload. A cache
  // made with this constructor is not registered with its owner
  // and will not receive information on server redirects and
  // cache operation mode changes

  _maxSize = maxSize ;
  _nsetCache.resize(_maxSize) ; // = new RooNormSetCache[maxSize] ;
  _object.resize(_maxSize,0) ; // = new T*[maxSize] ;
  _wired = kFALSE ;
}

template<class T>
RooCacheManager<T>::RooCacheManager(RooAbsArg* owner, Int_t maxSize) : RooAbsCache(owner)
{
  // Constructor for simple caches with RooAbsArg derived payload. A cache
  // made with this constructor is registered with its owner
  // and will receive information on server redirects and
  // cache operation mode changes
  
  _maxSize = maxSize ;
  _size = 0 ;

  _nsetCache.resize(_maxSize) ; // = new RooNormSetCache[maxSize] ;
  _object.resize(_maxSize,0) ; // = new T*[maxSize] ;
  _wired = kFALSE ;
  _lastIndex = -1 ;

  Int_t i ;
  for (i=0 ; i<_maxSize ; i++) {
    _object[i]=0 ;
  }

}


template<class T>
RooCacheManager<T>::RooCacheManager(const RooCacheManager& other, RooAbsArg* owner) : RooAbsCache(other,owner)
{
  // Copy constructor

  _maxSize = other._maxSize ;
  _size = other._size ;
  
  _nsetCache.resize(_maxSize) ; // = new RooNormSetCache[_maxSize] ;
  _object.resize(_maxSize,0) ; // = new T*[_maxSize] ;
  _wired = kFALSE ;
  _lastIndex = -1 ;

  //std::cout << "RooCacheManager:cctor(" << this << ") other = " << &other << " _size=" << _size << " _maxSize = " << _maxSize << std::endl ;

  Int_t i ;
  for (i=0 ; i<other._size ; i++) {    
    _nsetCache[i].initialize(other._nsetCache[i]) ;
    _object[i] = 0 ;
  }

  for (i=other._size ; i<_maxSize ; i++) {    
    _object[i] = 0 ;
  }
}


template<class T>
RooCacheManager<T>::~RooCacheManager()
{
  // Destructor

  //delete[] _nsetCache ;  
  Int_t i ;
  for (i=0 ; i<_size ; i++) {
    delete _object[i] ;
  }
  //delete[] _object ;
}


template<class T>
void RooCacheManager<T>::reset() 
{
  // Clear the cache

  Int_t i ;
  for (i=0 ; i<_maxSize ; i++) {
    delete _object[i] ;
    _object[i]=0 ;
    _nsetCache[i].clear() ;
  }  
  _lastIndex = -1 ;
  _size = 0 ;
}
  


template<class T>
void RooCacheManager<T>::sterilize() 
{
  // Clear the cache payload but retain slot mapping w.r.t to
  // normalization and integration sets.

  Int_t i ;
  for (i=0 ; i<_maxSize ; i++) {
    delete _object[i] ;
    _object[i]=0 ;
  }  
}
  


template<class T>
Int_t RooCacheManager<T>::setObj(const RooArgSet* nset, const RooArgSet* iset, T* obj, const TNamed* isetRangeName) 
{
  // Insert payload object 'obj' in cache indexed on nset,iset and isetRangeName

  // Check if object is already registered
  Int_t sterileIdx(-1) ;
  if (getObj(nset,iset,&sterileIdx,isetRangeName)) {
    return lastIndex() ;
  } 


  if (sterileIdx>=0) {
    // Found sterile slot that can should be recycled [ sterileIndex only set if isetRangeName matches ]

    if (sterileIdx>=_maxSize) {
      //cout << "RooCacheManager<T>::setObj()/SI increasing object cache size from " << _maxSize << " to " << sterileIdx+4 << endl ;
      _maxSize = sterileIdx+4;
      _object.resize(_maxSize,0) ;
      _nsetCache.resize(_maxSize) ;
    }


    _object[sterileIdx] = obj ;

    // Allow optional post-processing of object inserted in cache
    insertObjectHook(*obj) ;

    return lastIndex() ;
  }

  if (_size>=_maxSize-1) {
    //cout << "RooCacheManager<T>::setObj() increasing object cache size from " << _maxSize << " to " << _maxSize*2 << endl ;
    _maxSize *=2 ;
    _object.resize(_maxSize,0) ;
    _nsetCache.resize(_maxSize) ;
  }

  //cout << "RooCacheManager::setObj<T>(" << this << ") _size = " << _size << " _maxSize = " << _maxSize << endl ;
  _nsetCache[_size].autoCache(_owner,nset,iset,isetRangeName,kTRUE) ;
  if (_object[_size]) {
    delete _object[_size] ;
  }

  _object[_size] = obj ;
  _size++ ;

  // Allow optional post-processing of object inserted in cache
  insertObjectHook(*obj) ;

  // Unwire cache in case it was wired
  _wired = kFALSE ;

  return _size-1 ;
}



template<class T>
T* RooCacheManager<T>::getObj(const RooArgSet* nset, const RooArgSet* iset, Int_t* sterileIdx, const TNamed* isetRangeName) 
{
  // Retrieve payload object indexed on nset,uset amd isetRangeName
  // If sterileIdx is not null, it is set to the index of the sterile
  // slot in cacse such a slot is recycled

  // Fast-track for wired mode
  if (_wired) {
    if(_object[0]==0 && sterileIdx) *sterileIdx=0 ;
    return _object[0] ;
  }
  
  Int_t i ;
  for (i=0 ; i<_size ; i++) {
    if (_nsetCache[i].contains(nset,iset,isetRangeName)==kTRUE) {      
      _lastIndex = i ;
      if(_object[i]==0 && sterileIdx) *sterileIdx=i ;
      return _object[i] ;
    }
  }

  for (i=0 ; i<_size ; i++) {
    if (_nsetCache[i].autoCache(_owner,nset,iset,isetRangeName,kFALSE)==kFALSE) {
      _lastIndex = i ;
      if(_object[i]==0 && sterileIdx) *sterileIdx=i ;
      return _object[i] ;
    }
  }

  return 0 ;
}



template<class T>
T* RooCacheManager<T>::getObjByIndex(Int_t index) const 
{
  // Retrieve payload object by slot index

  if (index<0||index>=_size) {
    oocoutE(_owner,ObjectHandling) << "RooCacheManager::getNormListByIndex: ERROR index (" 
				   << index << ") out of range [0," << _size-1 << "]" << std::endl ;
    return 0 ;
  }
  return _object[index] ;
}

template<class T>
const RooNameSet* RooCacheManager<T>::nameSet1ByIndex(Int_t index) const
{
  // Retrieve RooNameSet associated with slot at given index

  if (index<0||index>=_size) {
    oocoutE(_owner,ObjectHandling) << "RooCacheManager::getNormListByIndex: ERROR index (" 
				   << index << ") out of range [0," << _size-1 << "]" << std::endl ;
    return 0 ;
  }
  return &_nsetCache[index].nameSet1() ;
}

template<class T>
const RooNameSet* RooCacheManager<T>::nameSet2ByIndex(Int_t index) const 
{
  // Retrieve RooNameSet associated with slot at given index

  if (index<0||index>=_size) {
    oocoutE(_owner,ObjectHandling) << "RooCacheManager::getNormListByIndex: ERROR index (" 
				   << index << ") out of range [0," << _size-1 << "]" << std::endl ;
    return 0 ;
  }
  return &_nsetCache[index].nameSet2() ;
}


#endif 
 RooCacheManager.h:1
 RooCacheManager.h:2
 RooCacheManager.h:3
 RooCacheManager.h:4
 RooCacheManager.h:5
 RooCacheManager.h:6
 RooCacheManager.h:7
 RooCacheManager.h:8
 RooCacheManager.h:9
 RooCacheManager.h:10
 RooCacheManager.h:11
 RooCacheManager.h:12
 RooCacheManager.h:13
 RooCacheManager.h:14
 RooCacheManager.h:15
 RooCacheManager.h:16
 RooCacheManager.h:17
 RooCacheManager.h:18
 RooCacheManager.h:19
 RooCacheManager.h:20
 RooCacheManager.h:21
 RooCacheManager.h:22
 RooCacheManager.h:23
 RooCacheManager.h:24
 RooCacheManager.h:25
 RooCacheManager.h:26
 RooCacheManager.h:27
 RooCacheManager.h:28
 RooCacheManager.h:29
 RooCacheManager.h:30
 RooCacheManager.h:31
 RooCacheManager.h:32
 RooCacheManager.h:33
 RooCacheManager.h:34
 RooCacheManager.h:35
 RooCacheManager.h:36
 RooCacheManager.h:37
 RooCacheManager.h:38
 RooCacheManager.h:39
 RooCacheManager.h:40
 RooCacheManager.h:41
 RooCacheManager.h:42
 RooCacheManager.h:43
 RooCacheManager.h:44
 RooCacheManager.h:45
 RooCacheManager.h:46
 RooCacheManager.h:47
 RooCacheManager.h:48
 RooCacheManager.h:49
 RooCacheManager.h:50
 RooCacheManager.h:51
 RooCacheManager.h:52
 RooCacheManager.h:53
 RooCacheManager.h:54
 RooCacheManager.h:55
 RooCacheManager.h:56
 RooCacheManager.h:57
 RooCacheManager.h:58
 RooCacheManager.h:59
 RooCacheManager.h:60
 RooCacheManager.h:61
 RooCacheManager.h:62
 RooCacheManager.h:63
 RooCacheManager.h:64
 RooCacheManager.h:65
 RooCacheManager.h:66
 RooCacheManager.h:67
 RooCacheManager.h:68
 RooCacheManager.h:69
 RooCacheManager.h:70
 RooCacheManager.h:71
 RooCacheManager.h:72
 RooCacheManager.h:73
 RooCacheManager.h:74
 RooCacheManager.h:75
 RooCacheManager.h:76
 RooCacheManager.h:77
 RooCacheManager.h:78
 RooCacheManager.h:79
 RooCacheManager.h:80
 RooCacheManager.h:81
 RooCacheManager.h:82
 RooCacheManager.h:83
 RooCacheManager.h:84
 RooCacheManager.h:85
 RooCacheManager.h:86
 RooCacheManager.h:87
 RooCacheManager.h:88
 RooCacheManager.h:89
 RooCacheManager.h:90
 RooCacheManager.h:91
 RooCacheManager.h:92
 RooCacheManager.h:93
 RooCacheManager.h:94
 RooCacheManager.h:95
 RooCacheManager.h:96
 RooCacheManager.h:97
 RooCacheManager.h:98
 RooCacheManager.h:99
 RooCacheManager.h:100
 RooCacheManager.h:101
 RooCacheManager.h:102
 RooCacheManager.h:103
 RooCacheManager.h:104
 RooCacheManager.h:105
 RooCacheManager.h:106
 RooCacheManager.h:107
 RooCacheManager.h:108
 RooCacheManager.h:109
 RooCacheManager.h:110
 RooCacheManager.h:111
 RooCacheManager.h:112
 RooCacheManager.h:113
 RooCacheManager.h:114
 RooCacheManager.h:115
 RooCacheManager.h:116
 RooCacheManager.h:117
 RooCacheManager.h:118
 RooCacheManager.h:119
 RooCacheManager.h:120
 RooCacheManager.h:121
 RooCacheManager.h:122
 RooCacheManager.h:123
 RooCacheManager.h:124
 RooCacheManager.h:125
 RooCacheManager.h:126
 RooCacheManager.h:127
 RooCacheManager.h:128
 RooCacheManager.h:129
 RooCacheManager.h:130
 RooCacheManager.h:131
 RooCacheManager.h:132
 RooCacheManager.h:133
 RooCacheManager.h:134
 RooCacheManager.h:135
 RooCacheManager.h:136
 RooCacheManager.h:137
 RooCacheManager.h:138
 RooCacheManager.h:139
 RooCacheManager.h:140
 RooCacheManager.h:141
 RooCacheManager.h:142
 RooCacheManager.h:143
 RooCacheManager.h:144
 RooCacheManager.h:145
 RooCacheManager.h:146
 RooCacheManager.h:147
 RooCacheManager.h:148
 RooCacheManager.h:149
 RooCacheManager.h:150
 RooCacheManager.h:151
 RooCacheManager.h:152
 RooCacheManager.h:153
 RooCacheManager.h:154
 RooCacheManager.h:155
 RooCacheManager.h:156
 RooCacheManager.h:157
 RooCacheManager.h:158
 RooCacheManager.h:159
 RooCacheManager.h:160
 RooCacheManager.h:161
 RooCacheManager.h:162
 RooCacheManager.h:163
 RooCacheManager.h:164
 RooCacheManager.h:165
 RooCacheManager.h:166
 RooCacheManager.h:167
 RooCacheManager.h:168
 RooCacheManager.h:169
 RooCacheManager.h:170
 RooCacheManager.h:171
 RooCacheManager.h:172
 RooCacheManager.h:173
 RooCacheManager.h:174
 RooCacheManager.h:175
 RooCacheManager.h:176
 RooCacheManager.h:177
 RooCacheManager.h:178
 RooCacheManager.h:179
 RooCacheManager.h:180
 RooCacheManager.h:181
 RooCacheManager.h:182
 RooCacheManager.h:183
 RooCacheManager.h:184
 RooCacheManager.h:185
 RooCacheManager.h:186
 RooCacheManager.h:187
 RooCacheManager.h:188
 RooCacheManager.h:189
 RooCacheManager.h:190
 RooCacheManager.h:191
 RooCacheManager.h:192
 RooCacheManager.h:193
 RooCacheManager.h:194
 RooCacheManager.h:195
 RooCacheManager.h:196
 RooCacheManager.h:197
 RooCacheManager.h:198
 RooCacheManager.h:199
 RooCacheManager.h:200
 RooCacheManager.h:201
 RooCacheManager.h:202
 RooCacheManager.h:203
 RooCacheManager.h:204
 RooCacheManager.h:205
 RooCacheManager.h:206
 RooCacheManager.h:207
 RooCacheManager.h:208
 RooCacheManager.h:209
 RooCacheManager.h:210
 RooCacheManager.h:211
 RooCacheManager.h:212
 RooCacheManager.h:213
 RooCacheManager.h:214
 RooCacheManager.h:215
 RooCacheManager.h:216
 RooCacheManager.h:217
 RooCacheManager.h:218
 RooCacheManager.h:219
 RooCacheManager.h:220
 RooCacheManager.h:221
 RooCacheManager.h:222
 RooCacheManager.h:223
 RooCacheManager.h:224
 RooCacheManager.h:225
 RooCacheManager.h:226
 RooCacheManager.h:227
 RooCacheManager.h:228
 RooCacheManager.h:229
 RooCacheManager.h:230
 RooCacheManager.h:231
 RooCacheManager.h:232
 RooCacheManager.h:233
 RooCacheManager.h:234
 RooCacheManager.h:235
 RooCacheManager.h:236
 RooCacheManager.h:237
 RooCacheManager.h:238
 RooCacheManager.h:239
 RooCacheManager.h:240
 RooCacheManager.h:241
 RooCacheManager.h:242
 RooCacheManager.h:243
 RooCacheManager.h:244
 RooCacheManager.h:245
 RooCacheManager.h:246
 RooCacheManager.h:247
 RooCacheManager.h:248
 RooCacheManager.h:249
 RooCacheManager.h:250
 RooCacheManager.h:251
 RooCacheManager.h:252
 RooCacheManager.h:253
 RooCacheManager.h:254
 RooCacheManager.h:255
 RooCacheManager.h:256
 RooCacheManager.h:257
 RooCacheManager.h:258
 RooCacheManager.h:259
 RooCacheManager.h:260
 RooCacheManager.h:261
 RooCacheManager.h:262
 RooCacheManager.h:263
 RooCacheManager.h:264
 RooCacheManager.h:265
 RooCacheManager.h:266
 RooCacheManager.h:267
 RooCacheManager.h:268
 RooCacheManager.h:269
 RooCacheManager.h:270
 RooCacheManager.h:271
 RooCacheManager.h:272
 RooCacheManager.h:273
 RooCacheManager.h:274
 RooCacheManager.h:275
 RooCacheManager.h:276
 RooCacheManager.h:277
 RooCacheManager.h:278
 RooCacheManager.h:279
 RooCacheManager.h:280
 RooCacheManager.h:281
 RooCacheManager.h:282
 RooCacheManager.h:283
 RooCacheManager.h:284
 RooCacheManager.h:285
 RooCacheManager.h:286
 RooCacheManager.h:287
 RooCacheManager.h:288
 RooCacheManager.h:289
 RooCacheManager.h:290
 RooCacheManager.h:291
 RooCacheManager.h:292
 RooCacheManager.h:293
 RooCacheManager.h:294
 RooCacheManager.h:295
 RooCacheManager.h:296
 RooCacheManager.h:297
 RooCacheManager.h:298
 RooCacheManager.h:299
 RooCacheManager.h:300
 RooCacheManager.h:301
 RooCacheManager.h:302
 RooCacheManager.h:303
 RooCacheManager.h:304
 RooCacheManager.h:305
 RooCacheManager.h:306
 RooCacheManager.h:307
 RooCacheManager.h:308
 RooCacheManager.h:309
 RooCacheManager.h:310
 RooCacheManager.h:311
 RooCacheManager.h:312
 RooCacheManager.h:313
 RooCacheManager.h:314
 RooCacheManager.h:315
 RooCacheManager.h:316
 RooCacheManager.h:317
 RooCacheManager.h:318
 RooCacheManager.h:319
 RooCacheManager.h:320
 RooCacheManager.h:321
 RooCacheManager.h:322
 RooCacheManager.h:323
 RooCacheManager.h:324
 RooCacheManager.h:325
 RooCacheManager.h:326
 RooCacheManager.h:327
 RooCacheManager.h:328
 RooCacheManager.h:329
 RooCacheManager.h:330
 RooCacheManager.h:331
 RooCacheManager.h:332
 RooCacheManager.h:333
 RooCacheManager.h:334
 RooCacheManager.h:335
 RooCacheManager.h:336
 RooCacheManager.h:337
 RooCacheManager.h:338
 RooCacheManager.h:339
 RooCacheManager.h:340
 RooCacheManager.h:341
 RooCacheManager.h:342
 RooCacheManager.h:343
 RooCacheManager.h:344
 RooCacheManager.h:345
 RooCacheManager.h:346
 RooCacheManager.h:347
 RooCacheManager.h:348
 RooCacheManager.h:349
 RooCacheManager.h:350
 RooCacheManager.h:351
 RooCacheManager.h:352
 RooCacheManager.h:353
 RooCacheManager.h:354
 RooCacheManager.h:355
 RooCacheManager.h:356
 RooCacheManager.h:357
 RooCacheManager.h:358
 RooCacheManager.h:359
 RooCacheManager.h:360
 RooCacheManager.h:361
 RooCacheManager.h:362
 RooCacheManager.h:363