WebKit Bugzilla
Attachment 348749 Details for
Bug 189231
: [WTF] Add Markable<T, Traits>
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-189231-20180903044907.patch (text/plain), 24.65 KB, created by
Yusuke Suzuki
on 2018-09-02 12:49:09 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Yusuke Suzuki
Created:
2018-09-02 12:49:09 PDT
Size:
24.65 KB
patch
obsolete
>Subversion Revision: 235589 >diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog >index 37942bc85786d383e5fea2cacfa9490a2102e4bc..c26912df49a0b876214557f8cba7eedf60fbee0b 100644 >--- a/Source/WTF/ChangeLog >+++ b/Source/WTF/ChangeLog >@@ -1,3 +1,65 @@ >+2018-09-02 Yusuke Suzuki <yusukesuzuki@slowstart.org> >+ >+ [WTF] Add CompactOptional<T, Traits> >+ https://bugs.webkit.org/show_bug.cgi?id=189231 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ We can represent a value with nullopt by using std::optional<T>. However, as you know, std::optional<T> has >+ storage efficiency problem. It always has a bool indicating that the value is nullopt or not. If you have a >+ class like, >+ >+ class A { >+ std::optional<WallTime> m_timeA; >+ std::optional<WallTime> m_timeB; >+ std::optional<WallTime> m_timeC; >+ }; >+ >+ This class has significant amount of padding between m_timeA / m_timeB, m_timeB / m_timeC due to the above bool. >+ >+ If we know that WallTime has a value that represents invalid, we can use it instead and save the storage. >+ This is very similar problem to our HashTable implementation. In our HashTable implementation, we need Deleted >+ and Empty value, which can represent Deleted and Empty values without sacrificing storage efficiency. >+ >+ We should have similar mechanism here. In this patch, we have WTF::CompactOptional<T, Traits>. Traits offers >+ `Traits::isEmptyValue(value)` and `Traits::emptyValue()`. Then, we use this empty value instead of having bool >+ flag. This way, we can make `sizeof(WTF::CompactOptional<T>) == sizeof(T)`. >+ >+ This idea is inspired from https://github.com/akrzemi1/markable. But we would like to have WTF::CompactOptional<T> >+ here instead of importing it since we would like to have (1) integrated interfaces with std::optional<T> and (2) >+ aligned function names to HashTraits' `isEmptyValue` and `emptyValue`. >+ >+ * wtf/CMakeLists.txt: >+ * wtf/CompactOptional.h: Added. >+ (WTF::std::underlying_type<EnumType>::type>::max): EnumOptionalTraits can be used as an OptionalTraits for enum >+ values. We can specify a constant value as an empty value. >+ (WTF::IntegralOptionalTraits::isEmptyValue): >+ (WTF::IntegralOptionalTraits::emptyValue): IntegralOptionalTraits can be used as an OptionalTraits for integral >+ types including int etc. >+ (WTF::CompactOptional::CompactOptional): >+ (WTF::CompactOptional::operator bool const): >+ (WTF::CompactOptional::reset): >+ (WTF::CompactOptional::value const): >+ (WTF::CompactOptional::value): >+ (WTF::CompactOptional::operator-> const): >+ (WTF::CompactOptional::operator->): >+ (WTF::CompactOptional::operator* const): >+ (WTF::CompactOptional::operator*): >+ (WTF::CompactOptional::operator std::optional<T>): >+ (WTF::CompactOptional::operator std::optional<T> const): This operator allows us to cast CompactOptional<T> to >+ std::optional<T>. >+ * wtf/MonotonicTime.h: >+ (WTF::MonotonicTime::OptionalTraits::isEmptyValue): >+ (WTF::MonotonicTime::OptionalTraits::emptyValue): OptionalTraits for MonotonicTime. MonotonicTime::nan() is used >+ as an empty value. >+ * wtf/Seconds.h: >+ (WTF::Seconds::OptionalTraits::isEmptyValue): >+ (WTF::Seconds::OptionalTraits::emptyValue): OptionalTraits for Seconds. Seconds::nan() is used as an empty value. >+ * wtf/WallTime.h: >+ (WTF::WallTime::nan): >+ (WTF::WallTime::OptionalTraits::isEmptyValue): >+ (WTF::WallTime::OptionalTraits::emptyValue): OptionalTraits for WallTime. WallTime::nan() is used as an empty value. >+ > 2018-08-31 Antti Koivisto <antti@apple.com> > > Replace OptionSet |= and -= operators with add() and remove() functions >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index fff37193dfdfd65651632ba6602b7546c4bb2018..7f9c224074392fe039adf731ea94be7477855a96 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,18 @@ >+2018-09-02 Yusuke Suzuki <yusukesuzuki@slowstart.org> >+ >+ [WTF] Add CompactOptional<T, Traits> >+ https://bugs.webkit.org/show_bug.cgi?id=189231 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Use CompactOptional<Seconds> and CompactOptional<WallTime> in ResourceResponseBase. >+ Since these fields are parsed results from http header fields, Seconds::nan() and WallTime::nan() >+ can be used as an empty value for these fields. Thus we can use CompactOptional because it uses >+ these nan values as an empty values (they are configured by Seconds::OptionalTraits and WallTime::OptionalTraits). >+ This reduces the size of ResourceResponseBase from 448 to 416. >+ >+ * platform/network/ResourceResponseBase.h: >+ > 2018-09-01 Simon Fraser <simon.fraser@apple.com> > > Rename FilterEffectRenderer to CSSFilter >diff --git a/Source/WTF/wtf/CMakeLists.txt b/Source/WTF/wtf/CMakeLists.txt >index 50e62a311d201213756aff521aa4962c0592a878..5ce1faa4c21ba9a7bdc4e8b82bc0db2b74ff20d8 100644 >--- a/Source/WTF/wtf/CMakeLists.txt >+++ b/Source/WTF/wtf/CMakeLists.txt >@@ -27,6 +27,7 @@ set(WTF_PUBLIC_HEADERS > CheckedBoolean.h > ClockType.h > CommaPrinter.h >+ CompactOptional.h > CompactPointerTuple.h > CompilationThread.h > Compiler.h >diff --git a/Source/WTF/wtf/CompactOptional.h b/Source/WTF/wtf/CompactOptional.h >new file mode 100644 >index 0000000000000000000000000000000000000000..3b079d20bffb41f90bd52f65dc16c559a0b63885 >--- /dev/null >+++ b/Source/WTF/wtf/CompactOptional.h >@@ -0,0 +1,152 @@ >+/* >+ * Copyright (C) 2018 Yusuke Suzuki <yusukesuzuki@slowstart.org>. >+ * Copyright (C) 2016-2017 Apple Inc. All rights reserved. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY >+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR >+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, >+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, >+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR >+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY >+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT >+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE >+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+// The idea of CompactOptional<T> is derived from markable<T> at >+// https://github.com/akrzemi1/markable. >+// >+// Copyright (C) 2015-2018 Andrzej Krzemienski. >+// >+// Use, modification, and distribution is subject to the Boost Software >+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at >+// http://www.boost.org/LICENSE_1_0.txt) >+ >+#pragma once >+ >+#include <type_traits> >+#include <wtf/Optional.h> >+#include <wtf/StdLibExtras.h> >+ >+namespace WTF { >+ >+// Example: >+// enum class Type { Value1, Value2, Value3 }; >+// CompactOptional<Type, EnumOptionalTraits<Type, 42>> optional; >+template< >+ typename EnumType, >+ typename std::underlying_type<EnumType>::type constant = std::numeric_limits<typename std::underlying_type<EnumType>::type>::max()> >+struct EnumOptionalTraits { >+ static_assert(std::is_enum<EnumType>::value, ""); >+ using UnderlyingType = typename std::underlying_type<EnumType>::type; >+ >+ constexpr static bool isEmptyValue(EnumType value) >+ { >+ return static_cast<UnderlyingType>(value) == constant; >+ } >+ >+ constexpr static EnumType emptyValue() >+ { >+ return static_cast<EnumType>(constant); >+ } >+}; >+ >+template<typename IntegralType, IntegralType constant = 0> >+struct IntegralOptionalTraits { >+ static_assert(std::is_integral<IntegralType>::value, ""); >+ constexpr static bool isEmptyValue(IntegralType value) >+ { >+ return value == constant; >+ } >+ >+ constexpr static IntegralType emptyValue() >+ { >+ return constant; >+ } >+}; >+ >+// The goal of CompactOptional is offering std::optional without sacrificing storage efficiency. >+// CompactOptional takes Traits, which should have isEmptyValue and emptyValue functions. By using >+// one value of T as an empty value, we can remove bool flag in std::optional. This strategy is >+// similar to WTF::HashTable, which uses two values of T as an empty value and a deleted value. >+// This class is intended to be used as a member of a class to compact the size of the class. >+// Otherwise, you should use std::optional. >+template<typename T, typename Traits> >+class CompactOptional { >+public: >+ constexpr CompactOptional() >+ : m_value(Traits::emptyValue()) >+ { } >+ >+ constexpr CompactOptional(std::nullopt_t) >+ : CompactOptional() >+ { } >+ >+ constexpr CompactOptional(T&& value) >+ : m_value(WTFMove(value)) >+ { } >+ >+ constexpr CompactOptional(const T& value) >+ : m_value(value) >+ { } >+ >+ template<typename... Args> >+ constexpr explicit CompactOptional(std::in_place_t, Args&&... args) >+ : m_value(std::forward<Args>(args)...) >+ { } >+ >+ constexpr CompactOptional(const std::optional<T>& value) >+ : m_value(bool(value) ? *value : Traits::emptyValue()) >+ { } >+ >+ constexpr CompactOptional(std::optional<T>&& value) >+ : m_value(bool(value) ? WTFMove(*value) : Traits::emptyValue()) >+ { } >+ >+ constexpr explicit operator bool() const { return !Traits::isEmptyValue(m_value); } >+ >+ void reset() { m_value = Traits::emptyValue(); } >+ >+ constexpr const T& value() const& { return m_value; } >+ constexpr T& value() & { return m_value; } >+ constexpr T&& value() && { return WTFMove(m_value); } >+ >+ constexpr const T* operator->() const { return std::addressof(m_value); } >+ constexpr T* operator->() { return std::addressof(m_value); } >+ >+ constexpr const T& operator*() const& { return m_value; } >+ constexpr T& operator*() & { return m_value; } >+ >+ operator std::optional<T>() && >+ { >+ if (bool(*this)) >+ return WTFMove(m_value); >+ return std::nullopt; >+ } >+ >+ operator std::optional<T>() const& >+ { >+ if (bool(*this)) >+ return m_value; >+ return std::nullopt; >+ } >+ >+private: >+ T m_value; >+}; >+ >+} // namespace WTF >+ >+using WTF::CompactOptional; >+using WTF::IntegralOptionalTraits; >+using WTF::EnumOptionalTraits; >diff --git a/Source/WTF/wtf/MonotonicTime.h b/Source/WTF/wtf/MonotonicTime.h >index 0bbee823d8291f93bec757652121b9f04cd6c2e3..fd833814b06f4e480f699caaaa1b29963466320e 100644 >--- a/Source/WTF/wtf/MonotonicTime.h >+++ b/Source/WTF/wtf/MonotonicTime.h >@@ -165,6 +165,8 @@ class MonotonicTime { > return true; > } > >+ struct OptionalTraits; >+ > private: > constexpr MonotonicTime(double rawValue) > : m_value(rawValue) >@@ -174,6 +176,18 @@ class MonotonicTime { > double m_value { 0 }; > }; > >+struct MonotonicTime::OptionalTraits { >+ static constexpr bool isEmptyValue(MonotonicTime time) >+ { >+ return std::isnan(time.m_value); >+ } >+ >+ static constexpr MonotonicTime emptyValue() >+ { >+ return MonotonicTime::nan(); >+ } >+}; >+ > } // namespace WTF > > namespace std { >diff --git a/Source/WTF/wtf/Seconds.h b/Source/WTF/wtf/Seconds.h >index 61086f3e46337ed739488fcb5f4d53e8b64c2810..68c3c8df8db45862f3c8b87cb83d845196791046 100644 >--- a/Source/WTF/wtf/Seconds.h >+++ b/Source/WTF/wtf/Seconds.h >@@ -247,12 +247,26 @@ class Seconds { > return true; > } > >+ struct OptionalTraits; >+ > private: > double m_value { 0 }; > }; > > WTF_EXPORT_PRIVATE void sleep(Seconds); > >+struct Seconds::OptionalTraits { >+ static constexpr bool isEmptyValue(Seconds seconds) >+ { >+ return std::isnan(seconds.value()); >+ } >+ >+ static constexpr Seconds emptyValue() >+ { >+ return Seconds::nan(); >+ } >+}; >+ > inline namespace seconds_literals { > > constexpr Seconds operator"" _min(long double minutes) >diff --git a/Source/WTF/wtf/WallTime.h b/Source/WTF/wtf/WallTime.h >index bf66201090f331fffeb6a7652f413f35a9e29df2..09e8d13b8e9bd2554473d2131b77e0c89039b4b4 100644 >--- a/Source/WTF/wtf/WallTime.h >+++ b/Source/WTF/wtf/WallTime.h >@@ -56,6 +56,7 @@ class WallTime { > WTF_EXPORT_PRIVATE static WallTime now(); > > static constexpr WallTime infinity() { return fromRawSeconds(std::numeric_limits<double>::infinity()); } >+ static constexpr WallTime nan() { return fromRawSeconds(std::numeric_limits<double>::quiet_NaN()); } > > constexpr Seconds secondsSinceEpoch() const { return Seconds(m_value); } > >@@ -132,6 +133,9 @@ class WallTime { > { > return *this; > } >+ >+ struct OptionalTraits; >+ > private: > constexpr WallTime(double rawValue) > : m_value(rawValue) >@@ -141,6 +145,18 @@ class WallTime { > double m_value { 0 }; > }; > >+struct WallTime::OptionalTraits { >+ static constexpr bool isEmptyValue(WallTime time) >+ { >+ return std::isnan(time.m_value); >+ } >+ >+ static constexpr WallTime emptyValue() >+ { >+ return WallTime::nan(); >+ } >+}; >+ > WTF_EXPORT_PRIVATE void sleep(WallTime); > > } // namespace WTF >diff --git a/Source/WebCore/platform/network/ResourceResponseBase.h b/Source/WebCore/platform/network/ResourceResponseBase.h >index 2a4e49efa95803d2b849102fa5ec465b64df8e63..21bdcc80839c50bde67cad39d6a7bb657926f8d0 100644 >--- a/Source/WebCore/platform/network/ResourceResponseBase.h >+++ b/Source/WebCore/platform/network/ResourceResponseBase.h >@@ -32,6 +32,7 @@ > #include "NetworkLoadMetrics.h" > #include "ParsedContentRange.h" > #include "URL.h" >+#include <wtf/CompactOptional.h> > #include <wtf/WallTime.h> > > namespace WebCore { >@@ -214,10 +215,10 @@ class ResourceResponseBase { > mutable std::optional<CertificateInfo> m_certificateInfo; > > private: >- mutable std::optional<Seconds> m_age; >- mutable std::optional<WallTime> m_date; >- mutable std::optional<WallTime> m_expires; >- mutable std::optional<WallTime> m_lastModified; >+ mutable CompactOptional<Seconds, Seconds::OptionalTraits> m_age; >+ mutable CompactOptional<WallTime, WallTime::OptionalTraits> m_date; >+ mutable CompactOptional<WallTime, WallTime::OptionalTraits> m_expires; >+ mutable CompactOptional<WallTime, WallTime::OptionalTraits> m_lastModified; > mutable ParsedContentRange m_contentRange; > mutable CacheControlDirectives m_cacheControlDirectives; > >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 5a433aeef506b6f46556013bfbb4361bf219ac1a..022f0a49c3cec2eddf24a204bbaec2445d802ed5 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,16 @@ >+2018-09-02 Yusuke Suzuki <yusukesuzuki@slowstart.org> >+ >+ [WTF] Add CompactOptional<T, Traits> >+ https://bugs.webkit.org/show_bug.cgi?id=189231 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add tests for CompactOptional. >+ >+ * TestWebKitAPI/CMakeLists.txt: >+ * TestWebKitAPI/Tests/WTF/CompactOptional.cpp: Added. >+ (TestWebKitAPI::TEST): >+ > 2018-09-01 Michael Catanzaro <mcatanzaro@igalia.com> > > [WPE] 2.21.91 fails to build with ENABLE_MINIBROWSER >diff --git a/Tools/TestWebKitAPI/CMakeLists.txt b/Tools/TestWebKitAPI/CMakeLists.txt >index 968af7649923a5e3f4961da45ed6dcc16c818c7d..fb0188f6d762d2e33a976a12d7e00148fd16aeb2 100644 >--- a/Tools/TestWebKitAPI/CMakeLists.txt >+++ b/Tools/TestWebKitAPI/CMakeLists.txt >@@ -92,6 +92,7 @@ set(TestWTF_SOURCES > ${TESTWEBKITAPI_DIR}/Tests/WTF/BloomFilter.cpp > ${TESTWEBKITAPI_DIR}/Tests/WTF/CString.cpp > ${TESTWEBKITAPI_DIR}/Tests/WTF/CheckedArithmeticOperations.cpp >+ ${TESTWEBKITAPI_DIR}/Tests/WTF/CompactOptional.cpp > ${TESTWEBKITAPI_DIR}/Tests/WTF/ConcurrentPtrHashSet.cpp > ${TESTWEBKITAPI_DIR}/Tests/WTF/Condition.cpp > ${TESTWEBKITAPI_DIR}/Tests/WTF/CrossThreadTask.cpp >diff --git a/Tools/TestWebKitAPI/Tests/WTF/CompactOptional.cpp b/Tools/TestWebKitAPI/Tests/WTF/CompactOptional.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..7e5185ac28177d0487bc7390bdd5eaa63063f132 >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WTF/CompactOptional.cpp >@@ -0,0 +1,262 @@ >+/* >+ * Copyright (C) 2014 Apple Inc. All rights reserved. >+ * Copyright (C) 2018 Yusuke Suzuki <yusukesuzuki@slowstart.org>. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+ >+#include <wtf/CompactOptional.h> >+ >+namespace TestWebKitAPI { >+ >+TEST(WTF_CompactOptional, Disengaged) >+{ >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional; >+ >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+ >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { std::nullopt }; >+ >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+} >+ >+TEST(WTF_CompactOptional, Engaged) >+{ >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { 10 }; >+ >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ EXPECT_EQ(10, optional.value()); >+ >+ optional = 41; >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ EXPECT_EQ(41, optional.value()); >+ >+ optional = std::nullopt; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ >+ optional = 42; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { 42 }; >+ >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ >+ optional = 41; >+ >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ EXPECT_EQ(41, optional.value()); >+ } >+} >+ >+TEST(WTF_CompactOptional, Destructor) >+{ >+ static bool didCallDestructor = false; >+ struct A { >+ explicit A(int value) >+ : m_value(value) >+ { } >+ >+ ~A() >+ { >+ EXPECT_FALSE(didCallDestructor); >+ didCallDestructor = true; >+ } >+ >+ int m_value { 42 }; >+ }; >+ >+ struct ATraits { >+ static bool isEmptyValue(const A& value) >+ { >+ return value.m_value == 42; >+ } >+ static A emptyValue() >+ { >+ return A(42); >+ } >+ }; >+ >+ didCallDestructor = false; >+ { >+ CompactOptional<A, ATraits> optional { std::in_place, 20 }; >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ } >+ EXPECT_TRUE(didCallDestructor); >+ >+ didCallDestructor = false; >+ { >+ CompactOptional<A, ATraits> optional { std::in_place, 42 }; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+ EXPECT_TRUE(didCallDestructor); >+} >+ >+TEST(WTF_CompactOptional, FromOptional) >+{ >+ { >+ std::optional<int> from; >+ EXPECT_FALSE(static_cast<bool>(from)); >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional = from; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+ { >+ std::optional<int> from { 42 }; >+ EXPECT_TRUE(static_cast<bool>(from)); >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional = from; >+ // We convert this to nullopt. >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+ { >+ std::optional<int> from { 43 }; >+ EXPECT_TRUE(static_cast<bool>(from)); >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional = from; >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ EXPECT_EQ(optional.value(), 43); >+ } >+ { >+ std::optional<int> from; >+ EXPECT_FALSE(static_cast<bool>(from)); >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { WTFMove(from) }; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+ { >+ std::optional<int> from { 42 }; >+ EXPECT_TRUE(static_cast<bool>(from)); >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { WTFMove(from) }; >+ // We convert this to nullopt. >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ } >+ { >+ std::optional<int> from { 43 }; >+ EXPECT_TRUE(static_cast<bool>(from)); >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { WTFMove(from) }; >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ EXPECT_EQ(optional.value(), 43); >+ } >+} >+ >+TEST(WTF_CompactOptional, ToOptional) >+{ >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ std::optional<int> to = optional; >+ EXPECT_FALSE(static_cast<bool>(to)); >+ } >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { 42 }; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ // We convert this to nullopt. >+ std::optional<int> to = optional; >+ EXPECT_FALSE(static_cast<bool>(to)); >+ } >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { 43 }; >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ std::optional<int> to = optional; >+ EXPECT_TRUE(static_cast<bool>(to)); >+ EXPECT_EQ(to.value(), 43); >+ } >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ std::optional<int> to { WTFMove(optional) }; >+ EXPECT_FALSE(static_cast<bool>(to)); >+ } >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { 42 }; >+ EXPECT_FALSE(static_cast<bool>(optional)); >+ // We convert this to nullopt. >+ std::optional<int> to { WTFMove(optional) }; >+ EXPECT_FALSE(static_cast<bool>(to)); >+ } >+ { >+ CompactOptional<int, IntegralOptionalTraits<int, 42>> optional { 43 }; >+ EXPECT_TRUE(static_cast<bool>(optional)); >+ std::optional<int> to { WTFMove(optional) }; >+ EXPECT_TRUE(static_cast<bool>(to)); >+ EXPECT_EQ(to.value(), 43); >+ } >+} >+ >+TEST(WTF_CompactOptional, MoveOptional) >+{ >+ class OnlyMovable { >+ public: >+ constexpr explicit OnlyMovable(int value) >+ : m_value(value) >+ { >+ } >+ >+ int value() { return m_value; } >+ >+ OnlyMovable& operator=(OnlyMovable&& other) >+ { >+ m_value = other.m_value; >+ other.m_value = 42; >+ return *this; >+ } >+ >+ OnlyMovable(OnlyMovable&& other) >+ : m_value(other.m_value) >+ { >+ other.m_value = 42; >+ } >+ >+ static constexpr OnlyMovable emptyValue() >+ { >+ return OnlyMovable(42); >+ } >+ >+ static constexpr bool isEmptyValue(const OnlyMovable& value) >+ { >+ return value.m_value == 42; >+ } >+ >+ private: >+ OnlyMovable(const OnlyMovable&) = delete; >+ OnlyMovable& operator=(const OnlyMovable&) = delete; >+ >+ int m_value; >+ }; >+ { >+ std::optional<OnlyMovable> from { std::in_place, 20 }; >+ EXPECT_TRUE(static_cast<bool>(from)); >+ EXPECT_EQ(from.value().value(), 20); >+ CompactOptional<OnlyMovable, OnlyMovable> compact = WTFMove(from); >+ EXPECT_TRUE(static_cast<bool>(compact)); >+ EXPECT_EQ(compact.value().value(), 20); >+ std::optional<OnlyMovable> to = WTFMove(compact); >+ EXPECT_TRUE(static_cast<bool>(to)); >+ EXPECT_EQ(to.value().value(), 20); >+ } >+} >+ >+} // namespace TestWebKitAPI
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 189231
:
348749
|
348750
|
348751
|
348761
|
349286