forked from root-project/root
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathRConcurrentHashColl.hxx
101 lines (82 loc) · 3.19 KB
/
RConcurrentHashColl.hxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// Author: Danilo Piparo May 2018
/*************************************************************************
* Copyright (C) 1995-2018, Rene Brun and Fons Rademakers. *
* All rights reserved. *
* *
* For the licensing terms see $ROOTSYS/LICENSE. *
* For the list of contributors see $ROOTSYS/README/CREDITS. *
*************************************************************************/
#ifndef ROOT_RConcurrentHashColl
#define ROOT_RConcurrentHashColl
#include <memory>
#include <vector>
#include <functional>
#include "Rtypes.h"
namespace ROOT {
class TRWSpinLock;
namespace Internal {
struct RHashMap;
using RUidColl = std::vector<Int_t>;
/// This class is a thread-safe associative collection connecting
/// a 256 bits digest/hash to a collection of uid (integer)
/// This is used in the handling of the StreamerInfo record in TFile.
class RConcurrentHashColl {
private:
mutable std::unique_ptr<RHashMap> fHashMap;
mutable std::unique_ptr<ROOT::TRWSpinLock> fRWLock;
public:
class HashValue {
friend std::ostream &operator<<(std::ostream &os, const RConcurrentHashColl::HashValue &h);
private:
ULong64_t fDigest[4] = {0, 0, 0, 0};
public:
HashValue() = default;
HashValue(const char *data, int len);
ULong64_t const *Get() const { return fDigest; }
/// Return the hash value for this object
size_t Hash() const noexcept {
std::hash<ULong64_t> hasher;
return hasher(fDigest[0]) ^ hasher(fDigest[1])
^ hasher(fDigest[2]) ^ hasher(fDigest[3]);
}
};
RConcurrentHashColl();
~RConcurrentHashColl();
/// Return the collection of UID corresponding to the hash if the hash has
/// already been seen or nullptr otherwise.
const RUidColl *Find(const HashValue &hash) const;
/// If the hash is there, return false. Otherwise, insert the hash and UID
/// collection and return true.
bool Insert(const HashValue &hash, RUidColl &&coll) const;
/// Return the hash object corresponding to the buffer.
static HashValue Hash(char *buf, int len);
};
inline bool operator==(const RConcurrentHashColl::HashValue &lhs, const RConcurrentHashColl::HashValue &rhs)
{
auto l = lhs.Get();
auto r = rhs.Get();
return l[0] == r[0] && l[1] == r[1] && l[2] == r[2] && l[3] == r[3];
}
} // End NS Internal
} // End NS ROOT
namespace std {
template <>
struct less<ROOT::Internal::RConcurrentHashColl::HashValue> {
bool operator()(const ROOT::Internal::RConcurrentHashColl::HashValue &lhs, const ROOT::Internal::RConcurrentHashColl::HashValue &rhs) const
{
/// Check piece by piece the 4 64 bits ints which make up the hash.
auto l = lhs.Get();
auto r = rhs.Get();
// clang-format off
return l[0] < r[0] ? true :
l[0] > r[0] ? false :
l[1] < r[1] ? true :
l[1] > r[1] ? false :
l[2] < r[2] ? true :
l[2] > r[2] ? false :
l[3] < r[3] ? true : false;
// clang-format on
}
};
} // End NS std
#endif