Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
HiveNumbers.h 3.58 KiB
/***********************************************************************************\
* (c) Copyright 1998-2019 CERN for the benefit of the LHCb and ATLAS collaborations *
*                                                                                   *
* This software is distributed under the terms of the Apache version 2 licence,     *
* copied verbatim in the file "LICENSE".                                            *
*                                                                                   *
* In applying this licence, CERN does not waive the privileges and immunities       *
* granted to it by virtue of its status as an Intergovernmental Organization        *
* or submit itself to any jurisdiction.                                             *
\***********************************************************************************/
#ifndef GAUDIHIVE_HIVENUMBERS_H
#define GAUDIHIVE_HIVENUMBERS_H

// Framework include files
#include "GaudiKernel/IRndmGen.h"
#include "GaudiKernel/SmartIF.h"

// STL includes
#include <memory>
#include <vector>

#include "tbb/spin_rw_mutex.h"

// Forward declarations
class IRndmGen;
class IRndmGenSvc;

/*
 * This is a first solution to the problem of the thread safe random generation.
 * It is locking, but the locking is "diluted" by a caching mechanism of the
 * random numbers.
 */

namespace HiveRndm {

  typedef tbb::spin_rw_mutex HiveNumbersMutex;

  class GAUDI_API HiveNumbers {
  private:
    unsigned int            m_buffer_index;
    const unsigned int      m_buffer_size;
    std::vector<double>     m_buffer;
    static HiveNumbersMutex m_genMutex;

  protected:
    /// Pointer to random number generator
    IRndmGen* m_generator;

  public:
    /// Standard constructor
    HiveNumbers();
    /// Copy constructor
    HiveNumbers( const HiveNumbers& copy );
    /// Initializing constructor
    HiveNumbers( const SmartIF<IRndmGenSvc>& svc, const IRndmGen::Param& par );
    /// Standard destructor
    virtual ~HiveNumbers();
    /// Initialization
    virtual StatusCode initialize( const SmartIF<IRndmGenSvc>& svc, const IRndmGen::Param& par );
#if !defined( GAUDI_V22_API ) || defined( G22_NEW_SVCLOCATOR )
    /// Initializing constructor
    HiveNumbers( IRndmGenSvc* svc, const IRndmGen::Param& par );
    /// Initialization
    virtual StatusCode initialize( IRndmGenSvc* svc, const IRndmGen::Param& par );
#endif
    /// Finalization
    virtual StatusCode finalize();
    /// Check if the number supply is possible
    operator bool() const { return m_generator != 0; }
    /// Operator () for the use within STL
    double operator()() { return this->shoot(); }
    /// Pop a new number from the buffer
    double pop() { return this->shoot(); }
    /// Pop a new number from the buffer
    double shoot() {
      if ( 0 != m_generator ) {
        if ( m_buffer_index == 0 ) { // we are out of numbers
          this->shootArray( m_buffer, m_buffer_size ).ignore( /* AUTOMATICALLY ADDED FOR gaudi/Gaudi!763 */ );
          m_buffer_index = m_buffer_size - 1;
        }
        const double number = m_buffer[m_buffer_index];
        m_buffer_index--;
        return number;
      }
      return -1;
    }
    /// Pop a new number from the buffer
    StatusCode shootArray( std::vector<double>& array, long num, long start = 0 ) {
      if ( 0 != m_generator ) {
        StatusCode status;
        {
          HiveNumbersMutex::scoped_lock lock( m_genMutex );
          status = m_generator->shootArray( array, num, start );
        }
        return status;
      }
      return StatusCode::FAILURE;
    }
  };

} // namespace HiveRndm

#endif // GAUDIHIVE_HIVENumbers_H