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/WTFString.h>
33
34namespace WTF {
35
36class ObjectIdentifierBase {
37protected:
38 WTF_EXPORT_PRIVATE static uint64_t generateIdentifierInternal();
39 WTF_EXPORT_PRIVATE static uint64_t generateThreadSafeIdentifierInternal();
40};
41
42template<typename T> class ObjectIdentifier : private ObjectIdentifierBase {
43public:
44 static ObjectIdentifier generate()
45 {
46 return ObjectIdentifier { generateIdentifierInternal() };
47 }
48
49 static ObjectIdentifier generateThreadSafe()
50 {
51 return ObjectIdentifier { generateThreadSafeIdentifierInternal() };
52 }
53
54 ObjectIdentifier() = default;
55
56 ObjectIdentifier(HashTableDeletedValueType) : m_identifier(hashTableDeletedValue()) { }
57 bool isHashTableDeletedValue() const { return m_identifier == hashTableDeletedValue(); }
58
59 template<typename Encoder> void encode(Encoder& encoder) const
60 {
61 ASSERT(isValidIdentifier(m_identifier));
62 encoder << m_identifier;
63 }
64 template<typename Decoder> static Optional<ObjectIdentifier> decode(Decoder& decoder)
65 {
66 Optional<uint64_t> identifier;
67 decoder >> identifier;
68 if (!identifier)
69 return WTF::nullopt;
70 ASSERT(isValidIdentifier(*identifier));
71 return ObjectIdentifier { *identifier };
72 }
73
74 bool operator==(const ObjectIdentifier& other) const
75 {
76 return m_identifier == other.m_identifier;
77 }
78
79 bool operator!=(const ObjectIdentifier& other) const
80 {
81 return m_identifier != other.m_identifier;
82 }
83
84 uint64_t toUInt64() const { return m_identifier; }
85 explicit operator bool() const { return m_identifier; }
86
87 String loggingString() const
88 {
89 return String::number(m_identifier);
90 }
91
92private:
93 template<typename U> friend ObjectIdentifier<U> makeObjectIdentifier(uint64_t);
94 friend struct HashTraits<ObjectIdentifier>;
95 template<typename U> friend struct ObjectIdentifierHash;
96
97 static uint64_t hashTableDeletedValue() { return std::numeric_limits<uint64_t>::max(); }
98 static bool isValidIdentifier(uint64_t identifier) { return identifier && identifier != hashTableDeletedValue(); }
99
100 explicit ObjectIdentifier(uint64_t identifier)
101 : m_identifier(identifier)
102 {
103 }
104
105 uint64_t m_identifier { 0 };
106};
107
108template<typename T> inline ObjectIdentifier<T> makeObjectIdentifier(uint64_t identifier)
109{
110 return ObjectIdentifier<T> { identifier };
111}
112
113template<typename T> struct ObjectIdentifierHash {
114 static unsigned hash(const ObjectIdentifier<T>& identifier) { return intHash(identifier.m_identifier); }
115 static bool equal(const ObjectIdentifier<T>& a, const ObjectIdentifier<T>& b) { return a == b; }
116 static const bool safeToCompareToEmptyOrDeleted = true;
117};
118
119template<typename T> struct HashTraits<ObjectIdentifier<T>> : SimpleClassHashTraits<ObjectIdentifier<T>> { };
120
121template<typename T> struct DefaultHash<ObjectIdentifier<T>> {
122 typedef ObjectIdentifierHash<T> Hash;
123};
124
125} // namespace WTF
126
127using WTF::ObjectIdentifier;
128using WTF::makeObjectIdentifier;
129