The Gaudi Framework
master (2e57474e)
Toggle main menu visibility
Loading...
Searching...
No Matches
SynchronizedValue.h
Go to the documentation of this file.
1
/***********************************************************************************\
2
* (c) Copyright 1998-2026 CERN for the benefit of the LHCb and ATLAS collaborations *
3
* *
4
* This software is distributed under the terms of the Apache version 2 licence, *
5
* copied verbatim in the file "LICENSE". *
6
* *
7
* In applying this licence, CERN does not waive the privileges and immunities *
8
* granted to it by virtue of its status as an Intergovernmental Organization *
9
* or submit itself to any jurisdiction. *
10
\***********************************************************************************/
11
#pragma once
12
#include <algorithm>
13
#include <concepts>
14
#include <functional>
15
#include <mutex>
16
#include <shared_mutex>
17
#include <tuple>
18
#include <type_traits>
19
#include <utility>
20
21
namespace
Gaudi::cxx
{
22
23
// C++23: replace with http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0290r2.html
24
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4033.html
25
26
template
<
typename
Value,
typename
Mutex = std::mutex,
27
typename
ReadLock = std::conditional_t<std::is_same_v<std::shared_mutex, Mutex>, std::shared_lock<Mutex>,
28
std::lock_guard<Mutex>>,
29
typename
WriteLock = std::lock_guard<Mutex>>
30
requires
( !std::is_reference_v<Value> )
// Value must not be a reference
31
class
SynchronizedValue
{
32
Value
m_obj
;
33
mutable
Mutex
m_mtx
;
34
35
public
:
36
template
<
typename
... Args>
37
requires
std::constructible_from<Value, Args...> &&
38
(
sizeof
...( Args ) != 1 || !( std::same_as<SynchronizedValue, std::remove_cvref_t<Args>> || ... ) )
39
explicit
(
sizeof
...( Args ) == 1 )
SynchronizedValue
( Args&&... args ) :
m_obj
(
std
::forward<Args>( args )... ) {}
40
41
SynchronizedValue
(
SynchronizedValue
const
& rhs )
42
requires
std::constructible_from<Value, Value const&>
43
:
m_obj
( [&] {
44
auto
_ = ReadLock{ rhs.m_mtx };
45
return
Value( rhs.m_obj );
46
}() ) {}
47
48
SynchronizedValue
&
operator=
(
const
SynchronizedValue
& rhs )
49
requires
std::assignable_from<Value&, Value const&>
50
{
51
if
(
this
!= &rhs ) {
52
auto
_ = std::scoped_lock{ rhs.m_mtx,
m_mtx
};
53
m_obj
= rhs.m_obj;
54
}
55
return
*
this
;
56
}
57
58
SynchronizedValue
(
SynchronizedValue
&& rhs )
59
requires
std::constructible_from<Value, Value&&>
60
:
m_obj
( [&] {
61
auto
_ = WriteLock{ rhs.m_mtx };
62
return
Value( std::move( rhs.m_obj ) );
63
}() ) {}
64
65
SynchronizedValue
&
operator=
(
SynchronizedValue
&& rhs )
66
requires
std::assignable_from<Value&, Value&&>
67
{
68
if
(
this
!= &rhs ) {
69
auto
_ = std::scoped_lock{ rhs.m_mtx,
m_mtx
};
70
m_obj
= std::move( rhs.m_obj );
71
}
72
return
*
this
;
73
}
74
75
template
<
typename
... Args, std::invocable<Value&, Args...> F>
76
requires
( !std::is_invocable_v<F,
const
Value&, Args...> )
77
decltype
(
auto
)
with_lock
( F&& f, Args&&... args ) {
78
auto
_ = WriteLock{
m_mtx
};
79
return
std::invoke( std::forward<F>( f ),
m_obj
, std::forward<Args>( args )... );
80
}
81
82
template
<
typename
... Args, std::invocable<
const
Value&, Args...> F>
83
decltype
( auto )
with_lock
( F&& f, Args&&... args )
const
{
84
auto
_ = ReadLock{
m_mtx
};
85
return
std::invoke( std::forward<F>( f ),
m_obj
, std::forward<Args>( args )... );
86
}
87
};
88
89
// transform an f(T,...) into an f(SynchronizedValue<T>,...)
90
template
<
typename
Fun>
91
auto
with_lock
( Fun&& f ) {
92
return
[f = std::forward<Fun>( f )](
auto
& p,
auto
&&... args ) ->
decltype
(
auto
) {
93
return
p.with_lock( f, std::forward<
decltype
( args )>( args )... );
94
};
95
}
96
// call f(T) for each element in a container of Synced<T>
97
template
<
typename
ContainerOfSynced,
typename
Fun>
98
void
for_each
( ContainerOfSynced& c, Fun&& f ) {
99
std::for_each( begin( c ), end( c ),
with_lock
( std::forward<Fun>( f ) ) );
100
}
101
102
}
// namespace Gaudi::cxx
Gaudi::cxx::SynchronizedValue::with_lock
decltype(auto) with_lock(F &&f, Args &&... args) const
Definition
SynchronizedValue.h:83
Gaudi::cxx::SynchronizedValue::operator=
SynchronizedValue & operator=(const SynchronizedValue &rhs)
Definition
SynchronizedValue.h:48
Gaudi::cxx::SynchronizedValue::SynchronizedValue
SynchronizedValue(SynchronizedValue const &rhs)
Definition
SynchronizedValue.h:41
Gaudi::cxx::SynchronizedValue::SynchronizedValue
SynchronizedValue(SynchronizedValue &&rhs)
Definition
SynchronizedValue.h:58
Gaudi::cxx::SynchronizedValue::m_mtx
Mutex m_mtx
Definition
SynchronizedValue.h:33
Gaudi::cxx::SynchronizedValue::m_obj
Value m_obj
Definition
SynchronizedValue.h:32
Gaudi::cxx::SynchronizedValue::with_lock
decltype(auto) with_lock(F &&f, Args &&... args)
Definition
SynchronizedValue.h:77
Gaudi::cxx::SynchronizedValue::operator=
SynchronizedValue & operator=(SynchronizedValue &&rhs)
Definition
SynchronizedValue.h:65
Gaudi::cxx
Definition
SynchronizedValue.h:21
Gaudi::cxx::for_each
void for_each(ContainerOfSynced &c, Fun &&f)
Definition
SynchronizedValue.h:98
Gaudi::cxx::with_lock
auto with_lock(Fun &&f)
Definition
SynchronizedValue.h:91
std
STL namespace.
GaudiKernel
include
Gaudi
cxx
SynchronizedValue.h
Generated on
for The Gaudi Framework by
1.17.0