Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
Public Member Functions | Private Member Functions | Private Attributes | List of all members
CaloRecGPU::Helpers::separate_thread_holder< T > Class Template Reference

Manages objects of type T in a thread-safe way, ensuring that there's an object available for each separate thread while minimizing the number of allocations. More...

#include <Helpers.h>

Collaboration diagram for CaloRecGPU::Helpers::separate_thread_holder< T >:

Public Member Functions

T & get_one ()
 
T & get_for_thread () const
 
void release_one ()
 
void resize (const size_t new_size)
 
template<class F , class ... Args>
void operate_on_all (F &&f, Args &&... args)
 
size_t held_size () const
 
size_t available_size () const
 
size_t filled_size () const
 

Private Member Functions

T & add_one_and_return ()
 

Private Attributes

std::vector< std::unique_ptr< T > > m_held
 
std::vector< typename std::thread::idm_thread_equivs
 
std::shared_mutex m_mutex
 

Detailed Description

template<class T>
class CaloRecGPU::Helpers::separate_thread_holder< T >

Manages objects of type T in a thread-safe way, ensuring that there's an object available for each separate thread while minimizing the number of allocations.

Internally uses a std::vector of std::thread::id to manage the different threads, thus it is especially efficient for relatively small numbers of concurrent threads (which matches the use case, e. g. 64 threads )

Definition at line 1472 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

Member Function Documentation

◆ add_one_and_return()

template<class T >
T& CaloRecGPU::Helpers::separate_thread_holder< T >::add_one_and_return ( )
inlineprivate

Definition at line 1490 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1491  {
1492  std::unique_lock<std::shared_mutex> lock(m_mutex);
1493  m_held.emplace_back(std::make_unique<T>());
1494  m_thread_equivs.emplace_back(std::this_thread::get_id());
1495  return *(m_held.back());
1496  }

◆ available_size()

template<class T >
size_t CaloRecGPU::Helpers::separate_thread_holder< T >::available_size ( ) const
inline

Definition at line 1584 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1585  {
1586  std::shared_lock<std::shared_mutex> lock(m_mutex);
1587  size_t count = 0;
1588  const std::thread::id invalid_id{};
1589  for (const auto & id : m_thread_equivs)
1590  {
1591  if (id == invalid_id)
1592  {
1593  ++count;
1594  }
1595  }
1596  return count;
1597  }

◆ filled_size()

template<class T >
size_t CaloRecGPU::Helpers::separate_thread_holder< T >::filled_size ( ) const
inline

Definition at line 1599 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1600  {
1601  std::shared_lock<std::shared_mutex> lock(m_mutex);
1602  size_t count = 0;
1603  const std::thread::id invalid_id{};
1604  for (const auto & id : m_thread_equivs)
1605  {
1606  if (id == invalid_id)
1607  {
1608  ++count;
1609  }
1610  }
1611  return m_held.size() - count;
1612  }

◆ get_for_thread()

template<class T >
T& CaloRecGPU::Helpers::separate_thread_holder< T >::get_for_thread ( ) const
inline
Precondition
Assumes the thread already has an allocated object (through get_one).

Definition at line 1518 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1519  {
1520  std::shared_lock<std::shared_mutex> lock(m_mutex);
1521  std::thread::id this_id = std::this_thread::get_id();
1522  for (size_t i = 0; i < m_thread_equivs.size(); ++i)
1523  {
1524  if (m_thread_equivs[i] == this_id)
1525  {
1526  return *(m_held[i]);
1527  }
1528  }
1529  //Here would be a good place for an unreachable.
1530  //C++23?
1531  return *(m_held.back());
1532  }

◆ get_one()

template<class T >
T& CaloRecGPU::Helpers::separate_thread_holder< T >::get_one ( )
inline

Definition at line 1499 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1500  {
1501  {
1502  std::shared_lock<std::shared_mutex> lock(m_mutex);
1503  std::thread::id this_id = std::this_thread::get_id();
1504  const std::thread::id invalid_id{};
1505  for (size_t i = 0; i < m_thread_equivs.size(); ++i)
1506  {
1507  if (m_thread_equivs[i] == invalid_id)
1508  {
1509  m_thread_equivs[i] = this_id;
1510  return *(m_held[i]);
1511  }
1512  }
1513  }
1514  return add_one_and_return();
1515  }

◆ held_size()

template<class T >
size_t CaloRecGPU::Helpers::separate_thread_holder< T >::held_size ( ) const
inline

Definition at line 1578 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1579  {
1580  std::shared_lock<std::shared_mutex> lock(m_mutex);
1581  return m_held.size();
1582  }

◆ operate_on_all()

template<class T >
template<class F , class ... Args>
void CaloRecGPU::Helpers::separate_thread_holder< T >::operate_on_all ( F &&  f,
Args &&...  args 
)
inline

Definition at line 1569 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1570  {
1571  std::unique_lock<std::shared_mutex> lock(m_mutex);
1572  for (std::unique_ptr<T> & obj : m_held)
1573  {
1574  f(*obj, std::forward<Args>(args)...);
1575  }
1576  }

◆ release_one()

template<class T >
void CaloRecGPU::Helpers::separate_thread_holder< T >::release_one ( )
inline

Definition at line 1534 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1535  {
1536  std::unique_lock<std::shared_mutex> lock(m_mutex);
1537  std::thread::id this_id = std::this_thread::get_id();
1538  const std::thread::id invalid_id{};
1539  for (size_t i = 0; i < m_thread_equivs.size(); ++i)
1540  {
1541  if (m_thread_equivs[i] == this_id)
1542  {
1543  m_thread_equivs[i] = invalid_id;
1544  }
1545  }
1546  }

◆ resize()

template<class T >
void CaloRecGPU::Helpers::separate_thread_holder< T >::resize ( const size_t  new_size)
inline

Definition at line 1548 of file Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h.

1549  {
1550  std::unique_lock<std::shared_mutex> lock(m_mutex);
1551  if (new_size < m_held.size())
1552  {
1553  m_held.resize(new_size);
1554  m_thread_equivs.resize(new_size);
1555  }
1556  else if (new_size > m_held.size())
1557  {
1558  const size_t to_add = new_size - m_held.size();
1559  const std::thread::id invalid_id{};
1560  for (size_t i = 0; i < to_add; ++i)
1561  {
1562  m_held.emplace_back(std::make_unique<T>());
1563  m_thread_equivs.emplace_back(invalid_id);
1564  }
1565  }
1566  }

Member Data Documentation

◆ m_held

template<class T >
std::vector< std::unique_ptr<T> > CaloRecGPU::Helpers::separate_thread_holder< T >::m_held
private

◆ m_mutex

template<class T >
std::shared_mutex CaloRecGPU::Helpers::separate_thread_holder< T >::m_mutex
mutableprivate

◆ m_thread_equivs

template<class T >
std::vector< typename std::thread::id > CaloRecGPU::Helpers::separate_thread_holder< T >::m_thread_equivs
private

The documentation for this class was generated from the following file:
python.CaloAddPedShiftConfig.args
args
Definition: CaloAddPedShiftConfig.py:47
CaloRecGPU::Helpers::separate_thread_holder::add_one_and_return
T & add_one_and_return()
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1490
CaloRecGPU::Helpers::separate_thread_holder::m_held
std::vector< std::unique_ptr< T > > m_held
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1475
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
CaloRecGPU::Helpers::separate_thread_holder::m_mutex
std::shared_mutex m_mutex
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1488
lumiFormat.i
int i
Definition: lumiFormat.py:85
CaloRecGPU::Helpers::separate_thread_holder::m_thread_equivs
std::vector< typename std::thread::id > m_thread_equivs
Definition: Calorimeter/CaloRecGPU/CaloRecGPU/Helpers.h:1476
hist_file_dump.f
f
Definition: hist_file_dump.py:141
id
SG::auxid_t id
Definition: Control/AthContainers/Root/debug.cxx:239
python.PyAthena.obj
obj
Definition: PyAthena.py:132