/*!***************************************************************************

  module      : RTESync_SpinlockRegister.hpp

  -------------------------------------------------------------------------

  responsible : JoergM

  special area: RTE
  description : Allocator registration 
  
                This class implements a singleton, that allows to register spinlocks.
                This allows to collect the statistic information for all registered
                spinlocks.

  last changed: 2001-01-10  11:04
  see also    : <class>RTE_ItemRegister</class>
  first created:2000-03-09  18:21

  -------------------------------------------------------------------------



    ========== licence begin  GPL
    Copyright (c) 2001-2005 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end




*****************************************************************************/

#ifndef RTEMEM_SPINLOCKREGISTER_HPP
#define RTEMEM_SPINLOCKREGISTER_HPP

/*===========================================================================*
 *  INCLUDES                                                                 *
 *===========================================================================*/

class RTESync_NamedSpinlock;
#include "RunTime/RTE_ItemRegister.hpp"

/*===========================================================================*
 *  CLASSES, STRUCTURES, TYPES, UNIONS ...                                   *
 *===========================================================================*/

/*! 
  Class: RTESync_SpinlockRegister

  Description: The spinlock register singleton
  
  The spinlock register allows individual spinlocks to Register()/Deregister()
  themselfs. The RTESync_NamedSpinlock is able to register itself during construction
  using a Register() call in their ctor and a Deregister() call in their dtor. 
  The registration takes place automatically during construction, no extra call is needed.

  To obtain a list of all static records of all currently registered spinlocks, a single
  call to GetStatisticInfo() is used. This call will lock the register during collecting
  information, providing a consistent snapshot. After the information is no longer needed
  it must be freed with a call to FreeStatisticInfo().

  The Register() and Deregister() functions use the same internal Spinlock as the GetStatisticInfo().
  
  Since the Deregister() function is called in the dtor only, the spinlock instances will never
  be detructed while the lock in the RTESync_SpinlockRegister is hold.

  Example:

  \#include "Runtime/Synchronisation/RTESync_SpinlockRegister.hpp"

  void SaveSpinlockInfo()
  {
      RTESync_SpinlockRegister & register = RTESync_SpinlockRegister::Instance() ;

      RTESync_SpinlockRegister::StatisticInfo * pInfo ;
      SAPDB_Int4 itemCount;

      if ( register.GetStatisticInfo(pInfo, itemCount) )
      {
          for ( SAPDB_Int4 iFirst; iFirst < itemCount; ++iFirst )
          {
              InsertIntoAllocatorSystemTable( pInfo[iItem].Name,
                                              usedCount,
                                              allocCount,
                                              info->GetBaseIdentifier() );
          }
      }

      register.Unlock();
  }

 */
class RTESync_SpinlockRegister : public RTE_ItemRegister<RTESync_NamedSpinlock>
{
public:
    static const SAPDB_Int4 m_MaxIdentfierLength;

    struct StatisticInfo
    {
        RTE_SpinlockStatistic StatisticRecord;
        SAPDB_UTF8            SpinlockName[40+4];
    };

    /*!
        Function: Instance

        description: Return reference to single instance of RTESync_SpinlockRegister

        The InitializeInstance function must have been called before.

        Return value: Reference to singleton instance
     */
    static RTESync_SpinlockRegister & Instance( );

    /*!
       Function: GetStatisticInfo
       Description: Get a snapshot of all statistic informations
       Arguments: pInfoArray[out] Pointer to array of StatisticInfo

       Return value: True if info array fill, false if not not enough memory
     */
    SAPDB_Bool GetStatisticInfo(StatisticInfo * &pInfoArray, SAPDB_Int4 &itemCount);

    /*!
       Function: FreeStatisticInfo
       Description: Free the snapshot of all statistic informations collected by GetStatisticInfo

       Arguments: pInfoArray[in] Pointer to array of StatisticInfo
     */
    void FreeStatisticInfo(StatisticInfo *pInfoArray);

private:
    RTESync_SpinlockRegister(SAPDB_Bool makeBackupCopy):RTE_ItemRegister<RTESync_NamedSpinlock>(makeBackupCopy) {}

    /*!
       Function: FillStatisticInfo
       Description: Fill the statistic informations
       
       Called by GetStatisticInfo, to call at least memory allocation outside of locked registration code

       Arguments: pInfoArray[in] Pointer to array of StatisticInfo
     */
    SAPDB_Bool FillStatisticInfo(StatisticInfo * &pInfoArray, SAPDB_Int4 maxCount, SAPDB_Int4 &itemCount);

    static RTESync_SpinlockRegister *m_Instance;
};

typedef RTE_ItemRegister<RTESync_NamedSpinlock>::Info RTESync_SpinlockInfo;

/*!
  EndClass: RTESync_SpinlockRegister
 */
#endif  /* RTEMEM_SPINLOCKREGISTER_HPP */
