1/*
2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#include <atomic>
29#include <mutex>
30#include <wtf/HashTraits.h>
31#include <wtf/NeverDestroyed.h>
32#include <wtf/text/TextStream.h>
33#include <wtf/text/WTFString.h>
34
35namespace WTF {
36
37class ObjectIdentifierBase {
38protected:
39 WTF_EXPORT_PRIVATE static uint64_t generateIdentifierInternal();
40 WTF_EXPORT_PRIVATE static uint64_t generateThreadSafeIdentifierInternal();
41};
42
43template<typename T> class ObjectIdentifier : private ObjectIdentifierBase {
44public:
45 static ObjectIdentifier generate()
46 {
47 return ObjectIdentifier { generateIdentifierInternal() };
48 }
49
50 static ObjectIdentifier generateThreadSafe()
51 {
52 return ObjectIdentifier { generateThreadSafeIdentifierInternal() };
53 }
54
55 ObjectIdentifier() = default;
56
57 ObjectIdentifier(HashTableDeletedValueType) : m_identifier(hashTableDeletedValue()) { }
58 bool isHashTableDeletedValue() const { return m_identifier == hashTableDeletedValue(); }
59
60 template<typename Encoder> void encode(Encoder& encoder) const
61 {
62 ASSERT(isValidIdentifier(m_identifier));
63 encoder << m_identifier;
64 }
65 template<typename Decoder> static Optional<ObjectIdentifier> decode(Decoder& decoder)
66 {
67 Optional<uint64_t> identifier;
68 decoder >> identifier;
69 if (!identifier)
70 return WTF::nullopt;
71 ASSERT(isValidIdentifier(*identifier));
72 return ObjectIdentifier { *identifier };
73 }
74
75 bool operator==(const ObjectIdentifier& other) const
76 {
77 return m_identifier == other.m_identifier;
78 }
79
80 bool operator!=(const ObjectIdentifier& other) const
81 {
82 return m_identifier != other.m_identifier;
83 }
84
85 uint64_t toUInt64() const { return m_identifier; }
86 explicit operator bool() const { return m_identifier; }
87
88 String loggingString() const
89 {
90 return String::number(m_identifier);
91 }
92
93private:
94 template<typename U> friend ObjectIdentifier<U> makeObjectIdentifier(uint64_t);
95 friend struct HashTraits<ObjectIdentifier>;
96 template<typename U> friend struct ObjectIdentifierHash;
97
98 static uint64_t hashTableDeletedValue() { return std::numeric_limits<uint64_t>::max(); }
99 static bool isValidIdentifier(uint64_t identifier) { return identifier && identifier != hashTableDeletedValue(); }
100
101 explicit ObjectIdentifier(uint64_t identifier)
102 : m_identifier(identifier)
103 {
104 }
105
106 uint64_t m_identifier { 0 };
107};
108
109template<typename T> inline ObjectIdentifier<T> makeObjectIdentifier(uint64_t identifier)
110{
111 return ObjectIdentifier<T> { identifier };
112}
113
114template<typename T> struct ObjectIdentifierHash {
115 static unsigned hash(const ObjectIdentifier<T>& identifier) { return intHash(identifier.m_identifier); }
116 static bool equal(const ObjectIdentifier<T>& a, const ObjectIdentifier<T>& b) { return a == b; }
117 static const bool safeToCompareToEmptyOrDeleted = true;
118};
119
120template<typename T> struct HashTraits<ObjectIdentifier<T>> : SimpleClassHashTraits<ObjectIdentifier<T>> { };
121
122template<typename T> struct DefaultHash<ObjectIdentifier<T>> {
123 typedef ObjectIdentifierHash<T> Hash;
124};
125
126template<typename T>
127TextStream& operator<<(TextStream& ts, const ObjectIdentifier<T>& identifier)
128{
129 ts << identifier.toUInt64();
130 return ts;
131}
132
133} // namespace WTF
134
135using WTF::ObjectIdentifier;
136using WTF::makeObjectIdentifier;
137