WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
/*
|
2019-09-18 00:36:19 +00:00
|
|
|
* Copyright (C) 2016-2019 Apple Inc. All rights reserved.
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2018-10-15 14:24:49 +00:00
|
|
|
#pragma once
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
|
|
|
|
#include <wtf/ClockType.h>
|
|
|
|
#include <wtf/Seconds.h>
|
|
|
|
|
|
|
|
namespace WTF {
|
|
|
|
|
|
|
|
class MonotonicTime;
|
|
|
|
class PrintStream;
|
|
|
|
|
|
|
|
// The current time according to a wall clock (aka real time clock). This uses floating point
|
|
|
|
// internally so that you can reason about infinity and other things that arise in math. It's
|
|
|
|
// acceptable to use this to wrap NaN times, negative times, and infinite times, so long as they
|
2018-02-23 04:18:17 +00:00
|
|
|
// are relative to the same clock. Use this only if wall clock time is needed. For elapsed time
|
|
|
|
// measurement use MonotonicTime instead.
|
2019-08-12 20:57:15 +00:00
|
|
|
class WallTime final {
|
|
|
|
WTF_MAKE_FAST_ALLOCATED;
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
public:
|
2019-09-18 00:36:19 +00:00
|
|
|
static constexpr ClockType clockType = ClockType::Wall;
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
|
|
|
|
// This is the epoch. So, x.secondsSinceEpoch() should be the same as x - WallTime().
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr WallTime() { }
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
|
|
|
|
// Call this if you know for sure that the double represents time according to
|
|
|
|
// WTF::currentTime(). It must be in seconds and it must be from the same time source.
|
2017-12-29 01:41:45 +00:00
|
|
|
static constexpr WallTime fromRawSeconds(double value)
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
2017-12-29 01:41:45 +00:00
|
|
|
return WallTime(value);
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
WTF_EXPORT_PRIVATE static WallTime now();
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
static constexpr WallTime infinity() { return fromRawSeconds(std::numeric_limits<double>::infinity()); }
|
[WTF] Add Markable<T, Traits>
https://bugs.webkit.org/show_bug.cgi?id=189231
Reviewed by Sam Weinig.
Source/WebCore:
Use Markable<Seconds> and Markable<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 Markable because it uses
these nan values as an empty values (they are configured by Seconds::MarkableTraits and WallTime::MarkableTraits).
This reduces the size of ResourceResponseBase from 448 to 416.
* platform/network/ResourceResponseBase.h:
Source/WTF:
We can represent a value with nullopt by using std::optional<T>. However, std::optional<T> has storage efficiency
problem. It always has a bool indicating that the value is nullopt or not. If we have a following class,
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::Markable<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::Markable<T>) == sizeof(T)`.
This idea is inspired from https://github.com/akrzemi1/markable. But we would like to have WTF::Markable<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.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/Markable.h: Added.
(WTF::std::underlying_type<EnumType>::type>::max): EnumMarkableTraits can be used as an MarkableTraits for enum
values. We can specify a constant value as an empty value.
(WTF::IntegralMarkableTraits::isEmptyValue):
(WTF::IntegralMarkableTraits::emptyValue): IntegralMarkableTraits can be used as an MarkableTraits for integral
types including int etc.
(WTF::Markable::Markable):
(WTF::Markable::operator bool const):
(WTF::Markable::reset):
(WTF::Markable::value const):
(WTF::Markable::value):
(WTF::Markable::operator-> const):
(WTF::Markable::operator->):
(WTF::Markable::operator* const):
(WTF::Markable::operator*):
(WTF::Markable::operator std::optional<T>):
(WTF::Markable::operator std::optional<T> const): This operator allows us to cast Markable<T> to
std::optional<T>.
* wtf/MonotonicTime.h:
(WTF::MonotonicTime::MarkableTraits::isEmptyValue):
(WTF::MonotonicTime::MarkableTraits::emptyValue): MarkableTraits for MonotonicTime. MonotonicTime::nan() is used
as an empty value.
* wtf/Seconds.h:
(WTF::Seconds::MarkableTraits::isEmptyValue):
(WTF::Seconds::MarkableTraits::emptyValue): MarkableTraits for Seconds. Seconds::nan() is used as an empty value.
* wtf/WallTime.h:
(WTF::WallTime::nan):
(WTF::WallTime::MarkableTraits::isEmptyValue):
(WTF::WallTime::MarkableTraits::emptyValue): MarkableTraits for WallTime. WallTime::nan() is used as an empty value.
Tools:
Add tests for Markable.
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Markable.cpp: Added.
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/204438@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235852 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-10 18:19:09 +00:00
|
|
|
static constexpr WallTime nan() { return fromRawSeconds(std::numeric_limits<double>::quiet_NaN()); }
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr Seconds secondsSinceEpoch() const { return Seconds(m_value); }
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
|
|
|
|
WallTime approximateWallTime() const { return *this; }
|
|
|
|
WTF_EXPORT_PRIVATE MonotonicTime approximateMonotonicTime() const;
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
explicit constexpr operator bool() const { return !!m_value; }
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr WallTime operator+(Seconds other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return fromRawSeconds(m_value + other.value());
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr WallTime operator-(Seconds other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return fromRawSeconds(m_value - other.value());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Time is a scalar and scalars can be negated as this could arise from algebraic
|
|
|
|
// transformations. So, we allow it.
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr WallTime operator-() const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return fromRawSeconds(-m_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
WallTime& operator+=(Seconds other)
|
|
|
|
{
|
|
|
|
return *this = *this + other;
|
|
|
|
}
|
|
|
|
|
|
|
|
WallTime& operator-=(Seconds other)
|
|
|
|
{
|
|
|
|
return *this = *this - other;
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr Seconds operator-(WallTime other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return Seconds(m_value - other.m_value);
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr bool operator==(WallTime other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return m_value == other.m_value;
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr bool operator!=(WallTime other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return m_value != other.m_value;
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr bool operator<(WallTime other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return m_value < other.m_value;
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr bool operator>(WallTime other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return m_value > other.m_value;
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr bool operator<=(WallTime other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return m_value <= other.m_value;
|
|
|
|
}
|
|
|
|
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr bool operator>=(WallTime other) const
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
{
|
|
|
|
return m_value >= other.m_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
WTF_EXPORT_PRIVATE void dump(PrintStream&) const;
|
|
|
|
|
2018-01-03 03:39:57 +00:00
|
|
|
WallTime isolatedCopy() const
|
|
|
|
{
|
|
|
|
return *this;
|
|
|
|
}
|
[WTF] Add Markable<T, Traits>
https://bugs.webkit.org/show_bug.cgi?id=189231
Reviewed by Sam Weinig.
Source/WebCore:
Use Markable<Seconds> and Markable<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 Markable because it uses
these nan values as an empty values (they are configured by Seconds::MarkableTraits and WallTime::MarkableTraits).
This reduces the size of ResourceResponseBase from 448 to 416.
* platform/network/ResourceResponseBase.h:
Source/WTF:
We can represent a value with nullopt by using std::optional<T>. However, std::optional<T> has storage efficiency
problem. It always has a bool indicating that the value is nullopt or not. If we have a following class,
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::Markable<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::Markable<T>) == sizeof(T)`.
This idea is inspired from https://github.com/akrzemi1/markable. But we would like to have WTF::Markable<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.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/Markable.h: Added.
(WTF::std::underlying_type<EnumType>::type>::max): EnumMarkableTraits can be used as an MarkableTraits for enum
values. We can specify a constant value as an empty value.
(WTF::IntegralMarkableTraits::isEmptyValue):
(WTF::IntegralMarkableTraits::emptyValue): IntegralMarkableTraits can be used as an MarkableTraits for integral
types including int etc.
(WTF::Markable::Markable):
(WTF::Markable::operator bool const):
(WTF::Markable::reset):
(WTF::Markable::value const):
(WTF::Markable::value):
(WTF::Markable::operator-> const):
(WTF::Markable::operator->):
(WTF::Markable::operator* const):
(WTF::Markable::operator*):
(WTF::Markable::operator std::optional<T>):
(WTF::Markable::operator std::optional<T> const): This operator allows us to cast Markable<T> to
std::optional<T>.
* wtf/MonotonicTime.h:
(WTF::MonotonicTime::MarkableTraits::isEmptyValue):
(WTF::MonotonicTime::MarkableTraits::emptyValue): MarkableTraits for MonotonicTime. MonotonicTime::nan() is used
as an empty value.
* wtf/Seconds.h:
(WTF::Seconds::MarkableTraits::isEmptyValue):
(WTF::Seconds::MarkableTraits::emptyValue): MarkableTraits for Seconds. Seconds::nan() is used as an empty value.
* wtf/WallTime.h:
(WTF::WallTime::nan):
(WTF::WallTime::MarkableTraits::isEmptyValue):
(WTF::WallTime::MarkableTraits::emptyValue): MarkableTraits for WallTime. WallTime::nan() is used as an empty value.
Tools:
Add tests for Markable.
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Markable.cpp: Added.
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/204438@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235852 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-10 18:19:09 +00:00
|
|
|
|
|
|
|
struct MarkableTraits;
|
|
|
|
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
private:
|
2017-12-29 01:41:45 +00:00
|
|
|
constexpr WallTime(double rawValue)
|
|
|
|
: m_value(rawValue)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
double m_value { 0 };
|
|
|
|
};
|
|
|
|
|
[WTF] Add Markable<T, Traits>
https://bugs.webkit.org/show_bug.cgi?id=189231
Reviewed by Sam Weinig.
Source/WebCore:
Use Markable<Seconds> and Markable<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 Markable because it uses
these nan values as an empty values (they are configured by Seconds::MarkableTraits and WallTime::MarkableTraits).
This reduces the size of ResourceResponseBase from 448 to 416.
* platform/network/ResourceResponseBase.h:
Source/WTF:
We can represent a value with nullopt by using std::optional<T>. However, std::optional<T> has storage efficiency
problem. It always has a bool indicating that the value is nullopt or not. If we have a following class,
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::Markable<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::Markable<T>) == sizeof(T)`.
This idea is inspired from https://github.com/akrzemi1/markable. But we would like to have WTF::Markable<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.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/Markable.h: Added.
(WTF::std::underlying_type<EnumType>::type>::max): EnumMarkableTraits can be used as an MarkableTraits for enum
values. We can specify a constant value as an empty value.
(WTF::IntegralMarkableTraits::isEmptyValue):
(WTF::IntegralMarkableTraits::emptyValue): IntegralMarkableTraits can be used as an MarkableTraits for integral
types including int etc.
(WTF::Markable::Markable):
(WTF::Markable::operator bool const):
(WTF::Markable::reset):
(WTF::Markable::value const):
(WTF::Markable::value):
(WTF::Markable::operator-> const):
(WTF::Markable::operator->):
(WTF::Markable::operator* const):
(WTF::Markable::operator*):
(WTF::Markable::operator std::optional<T>):
(WTF::Markable::operator std::optional<T> const): This operator allows us to cast Markable<T> to
std::optional<T>.
* wtf/MonotonicTime.h:
(WTF::MonotonicTime::MarkableTraits::isEmptyValue):
(WTF::MonotonicTime::MarkableTraits::emptyValue): MarkableTraits for MonotonicTime. MonotonicTime::nan() is used
as an empty value.
* wtf/Seconds.h:
(WTF::Seconds::MarkableTraits::isEmptyValue):
(WTF::Seconds::MarkableTraits::emptyValue): MarkableTraits for Seconds. Seconds::nan() is used as an empty value.
* wtf/WallTime.h:
(WTF::WallTime::nan):
(WTF::WallTime::MarkableTraits::isEmptyValue):
(WTF::WallTime::MarkableTraits::emptyValue): MarkableTraits for WallTime. WallTime::nan() is used as an empty value.
Tools:
Add tests for Markable.
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Markable.cpp: Added.
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/204438@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@235852 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2018-09-10 18:19:09 +00:00
|
|
|
struct WallTime::MarkableTraits {
|
|
|
|
static bool isEmptyValue(WallTime time)
|
|
|
|
{
|
|
|
|
return std::isnan(time.m_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
static constexpr WallTime emptyValue()
|
|
|
|
{
|
|
|
|
return WallTime::nan();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
WTF_EXPORT_PRIVATE void sleep(WallTime);
|
|
|
|
|
|
|
|
} // namespace WTF
|
|
|
|
|
2017-03-09 21:18:25 +00:00
|
|
|
namespace std {
|
|
|
|
|
|
|
|
inline bool isnan(WTF::WallTime time)
|
|
|
|
{
|
|
|
|
return std::isnan(time.secondsSinceEpoch().value());
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool isinf(WTF::WallTime time)
|
|
|
|
{
|
|
|
|
return std::isinf(time.secondsSinceEpoch().value());
|
|
|
|
}
|
|
|
|
|
|
|
|
inline bool isfinite(WTF::WallTime time)
|
|
|
|
{
|
|
|
|
return std::isfinite(time.secondsSinceEpoch().value());
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace std
|
|
|
|
|
WTF::ParkingLot should stop using std::chrono because std::chrono::duration casts are prone to overflows
https://bugs.webkit.org/show_bug.cgi?id=152045
Reviewed by Andy Estes.
Source/JavaScriptCore:
Probably the nicest example of why this patch is a good idea is the change in
AtomicsObject.cpp.
* jit/ICStats.cpp:
(JSC::ICStats::ICStats):
* runtime/AtomicsObject.cpp:
(JSC::atomicsFuncWait):
Source/WebCore:
No new layout tests because no new behavior. The new WTF time classes have some unit tests
in TestWebKitAPI.
* fileapi/ThreadableBlobRegistry.cpp:
(WebCore::ThreadableBlobRegistry::blobSize):
* platform/MainThreadSharedTimer.h:
* platform/SharedTimer.h:
* platform/ThreadTimers.cpp:
(WebCore::ThreadTimers::updateSharedTimer):
* platform/cf/MainThreadSharedTimerCF.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/efl/MainThreadSharedTimerEfl.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/glib/MainThreadSharedTimerGLib.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* platform/win/MainThreadSharedTimerWin.cpp:
(WebCore::MainThreadSharedTimer::setFireInterval):
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::runInMode):
Source/WebKit2:
* Platform/IPC/Connection.cpp:
(IPC::Connection::SyncMessageState::wait):
(IPC::Connection::sendMessage):
(IPC::Connection::timeoutRespectingIgnoreTimeoutsForTesting):
(IPC::Connection::waitForMessage):
(IPC::Connection::sendSyncMessage):
(IPC::Connection::waitForSyncReply):
* Platform/IPC/Connection.h:
(IPC::Connection::sendSync):
(IPC::Connection::waitForAndDispatchImmediately):
* Platform/IPC/MessageSender.h:
(IPC::MessageSender::sendSync):
* UIProcess/ChildProcessProxy.h:
(WebKit::ChildProcessProxy::sendSync):
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/Storage/StorageManager.cpp:
(WebKit::StorageManager::applicationWillTerminate):
* UIProcess/WebProcessProxy.cpp:
(WebKit::WebProcessProxy::sendProcessWillSuspendImminently):
* UIProcess/WebResourceLoadStatisticsStore.cpp:
(WebKit::WebResourceLoadStatisticsStore::applicationWillTerminate):
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.h:
* UIProcess/mac/RemoteLayerTreeDrawingAreaProxy.mm:
(-[WKOneShotDisplayLinkHandler displayLinkFired:]):
(WebKit::RemoteLayerTreeDrawingAreaProxy::commitLayerTree):
(WebKit::RemoteLayerTreeDrawingAreaProxy::didRefreshDisplay):
(WebKit::RemoteLayerTreeDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/TiledCoreAnimationDrawingAreaProxy.mm:
(WebKit::TiledCoreAnimationDrawingAreaProxy::waitForDidUpdateActivityState):
* UIProcess/mac/WKImmediateActionController.mm:
(-[WKImmediateActionController immediateActionRecognizerWillBeginAnimation:]):
* UIProcess/mac/WebPageProxyMac.mm:
(WebKit::WebPageProxy::stringSelectionForPasteboard):
(WebKit::WebPageProxy::dataSelectionForPasteboard):
(WebKit::WebPageProxy::readSelectionFromPasteboard):
(WebKit::WebPageProxy::shouldDelayWindowOrderingForEvent):
(WebKit::WebPageProxy::acceptsFirstMouse):
* WebProcess/WebCoreSupport/WebChromeClient.cpp:
(WebKit::WebChromeClient::runBeforeUnloadConfirmPanel):
(WebKit::WebChromeClient::runJavaScriptAlert):
(WebKit::WebChromeClient::runJavaScriptConfirm):
(WebKit::WebChromeClient::runJavaScriptPrompt):
(WebKit::WebChromeClient::print):
(WebKit::WebChromeClient::exceededDatabaseQuota):
(WebKit::WebChromeClient::reachedApplicationCacheOriginQuota):
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::postSynchronousMessageForTesting):
Source/WTF:
We used to use 'double' for all time measurements. Sometimes it was milliseconds,
sometimes it was seconds. Sometimes we measured a span of time, sometimes we spoke of time
since some epoch. When we spoke of time since epoch, we either used a monotonic clock or
a wall clock. The type - always 'double' - never told us what kind of time we had, even
though there were roughly six of them (sec interval, ms interval, sec since epoch on wall,
ms since epoch on wall, sec since epoch monotonic, ms since epoch monotonic).
At some point, we thought that it would be a good idea to replace these doubles with
std::chrono. But since replacing some things with std::chrono, we found it to be terribly
inconvenient:
- Outrageous API. I never want to say std::chrono::milliseconds(blah). I never want to say
std::chrono::steady_clock::timepoint. The syntax for duration_cast is ugly, and ideally
duration_cast would not even be a thing.
- No overflow protection. std::chrono uses integers by default and using anything else is
clumsy. But the integer math is done without regard for the rough edges of integer math,
so any cast between std::chrono types risks overflow. Any comparison risks overflow
because it may do conversions silently. We have even found bugs where some C++
implementations had more overflows than others, which ends up being a special kind of
hell. In many cases, the overflow also has nasal demons.
It's an error to represent time using integers. It would have been excusable back when
floating point math was not guaranteed to be supported on all platforms, but that would
have been a long time ago. Time is a continuous, infinite concept and it's a perfect fit
for floating point:
- Floating point preserves precision under multiplication in all but extreme cases, so
using floating point for time means that unit conversions are almost completely
lossless. This means that we don't have to think very hard about what units to use. In
this patch, we use seconds almost everywhere. We only convert at boundaries, like an API
boundary that wants something other than seconds.
- Floating point makes it easy to reason about infinity, which is something that time code
wants to do a lot. Example: when would you like to timeout? Infinity please! This is the
most elegant way of having an API support both a timeout variant and a no-timeout
variant.
- Floating point does well-understood things when math goes wrong, and these things are
pretty well optimized to match what a mathematician would do when computing with real
numbers represented using scientific notation with a finite number of significant
digits. This means that time math under floating point looks like normal math. On the
other hand, std::chrono time math looks like garbage because you have to always check
for multiple possible UB corners whenever you touch large integers. Integers that
represent time are very likely to be large and you don't have to do much to overflow
them. At this time, based on the number of bugs we have already seen due to chrono
overflows, I am not certain that we even understand what are all of the corner cases
that we should even check for.
This patch introduces a new set of timekeeping classes that are all based on double, and
all internally use seconds. These classes support algebraic typing. The classes are:
- Seconds: this is for measuring a duration.
- WallTime: time since epoch according to a wall clock (aka real time clock).
- MonotonicTime: time since epoch according to a monotonic clock.
- ClockType: enum that says either Wall or Monotonic.
- TimeWithDynamicClockType: a tuple of double and ClockType, which represents either a
wall time or a monotonic time.
All of these classes behave like C++ values and are cheap to copy around since they are
very nearly POD. This supports comprehensive conversions between the various time types.
Most of this is by way of algebra. Here are just some of the rules we recognize:
WallTime = WallTime + Seconds
Seconds = WallTime - WallTime
MonotonicTime = MonotonicTime + Seconds
etc...
We support negative, infinite, and NaN times because math.
We support conversions between MonotonicTime and WallTime, like:
WallTime wt = mt.approximateWallTime()
This is called this "approximate" because the only way to do it is to get the current time
on both clocks and convert relative to that.
Many of our APIs would be happy using whatever notion of time the user wanted to use. For
those APIs, which includes Condition and ParkingLot, we have TimeWithDynamicClockType. You
can automatically convert WallTime or MonotonicTime to TimeWithDynamicClockType. This
means that if you use a WallTime with Condition::waitUntil, then Condition's internal
logic for when it should wake up makes its decision based on the current WallTime - but if
you use MonotonicTime then waitUntil will make its decision based on current
MonotonicTime. This is a greater level of flexibility than chrono allowed, since chrono
did not have the concept of a dynamic clock type.
This patch does not include conversions between std::chrono and these new time classes,
because past experience shows that we're quite bad at getting conversions between
std::chrono and anything else right. Also, I didn't need such conversion code because this
patch only converts code that transitively touches ParkingLot and Condition. It was easy
to get all of that code onto the new time classes.
* WTF.xcodeproj/project.pbxproj:
* wtf/AutomaticThread.cpp:
(WTF::AutomaticThread::start):
* wtf/CMakeLists.txt:
* wtf/ClockType.cpp: Added.
(WTF::printInternal):
* wtf/ClockType.h: Added.
* wtf/Condition.h:
(WTF::ConditionBase::waitUntil):
(WTF::ConditionBase::waitFor):
(WTF::ConditionBase::wait):
(WTF::ConditionBase::waitUntilWallClockSeconds): Deleted.
(WTF::ConditionBase::waitUntilMonotonicClockSeconds): Deleted.
(WTF::ConditionBase::waitForSeconds): Deleted.
(WTF::ConditionBase::waitForSecondsImpl): Deleted.
(WTF::ConditionBase::waitForImpl): Deleted.
(WTF::ConditionBase::absoluteFromRelative): Deleted.
* wtf/CrossThreadQueue.h:
(WTF::CrossThreadQueue<DataType>::waitForMessage):
* wtf/CurrentTime.cpp:
(WTF::sleep):
* wtf/MessageQueue.h:
(WTF::MessageQueue::infiniteTime): Deleted.
* wtf/MonotonicTime.cpp: Added.
(WTF::MonotonicTime::now):
(WTF::MonotonicTime::approximateWallTime):
(WTF::MonotonicTime::dump):
(WTF::MonotonicTime::sleep):
* wtf/MonotonicTime.h: Added.
(WTF::MonotonicTime::MonotonicTime):
(WTF::MonotonicTime::fromRawDouble):
(WTF::MonotonicTime::infinity):
(WTF::MonotonicTime::secondsSinceEpoch):
(WTF::MonotonicTime::approximateMonotonicTime):
(WTF::MonotonicTime::operator bool):
(WTF::MonotonicTime::operator+):
(WTF::MonotonicTime::operator-):
(WTF::MonotonicTime::operator+=):
(WTF::MonotonicTime::operator-=):
(WTF::MonotonicTime::operator==):
(WTF::MonotonicTime::operator!=):
(WTF::MonotonicTime::operator<):
(WTF::MonotonicTime::operator>):
(WTF::MonotonicTime::operator<=):
(WTF::MonotonicTime::operator>=):
* wtf/ParkingLot.cpp:
(WTF::ParkingLot::parkConditionallyImpl):
(WTF::ParkingLot::unparkOne):
(WTF::ParkingLot::unparkOneImpl):
(WTF::ParkingLot::unparkCount):
* wtf/ParkingLot.h:
(WTF::ParkingLot::parkConditionally):
(WTF::ParkingLot::compareAndPark):
* wtf/Seconds.cpp: Added.
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::dump):
(WTF::Seconds::sleep):
* wtf/Seconds.h: Added.
(WTF::Seconds::Seconds):
(WTF::Seconds::value):
(WTF::Seconds::seconds):
(WTF::Seconds::milliseconds):
(WTF::Seconds::microseconds):
(WTF::Seconds::nanoseconds):
(WTF::Seconds::fromMilliseconds):
(WTF::Seconds::fromMicroseconds):
(WTF::Seconds::fromNanoseconds):
(WTF::Seconds::infinity):
(WTF::Seconds::operator bool):
(WTF::Seconds::operator+):
(WTF::Seconds::operator-):
(WTF::Seconds::operator*):
(WTF::Seconds::operator/):
(WTF::Seconds::operator+=):
(WTF::Seconds::operator-=):
(WTF::Seconds::operator*=):
(WTF::Seconds::operator/=):
(WTF::Seconds::operator==):
(WTF::Seconds::operator!=):
(WTF::Seconds::operator<):
(WTF::Seconds::operator>):
(WTF::Seconds::operator<=):
(WTF::Seconds::operator>=):
* wtf/TimeWithDynamicClockType.cpp: Added.
(WTF::TimeWithDynamicClockType::now):
(WTF::TimeWithDynamicClockType::nowWithSameClock):
(WTF::TimeWithDynamicClockType::wallTime):
(WTF::TimeWithDynamicClockType::monotonicTime):
(WTF::TimeWithDynamicClockType::approximateWallTime):
(WTF::TimeWithDynamicClockType::approximateMonotonicTime):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator<):
(WTF::TimeWithDynamicClockType::operator>):
(WTF::TimeWithDynamicClockType::operator<=):
(WTF::TimeWithDynamicClockType::operator>=):
(WTF::TimeWithDynamicClockType::dump):
(WTF::TimeWithDynamicClockType::sleep):
* wtf/TimeWithDynamicClockType.h: Added.
(WTF::TimeWithDynamicClockType::TimeWithDynamicClockType):
(WTF::TimeWithDynamicClockType::fromRawDouble):
(WTF::TimeWithDynamicClockType::secondsSinceEpoch):
(WTF::TimeWithDynamicClockType::clockType):
(WTF::TimeWithDynamicClockType::withSameClockAndRawDouble):
(WTF::TimeWithDynamicClockType::operator bool):
(WTF::TimeWithDynamicClockType::operator+):
(WTF::TimeWithDynamicClockType::operator-):
(WTF::TimeWithDynamicClockType::operator+=):
(WTF::TimeWithDynamicClockType::operator-=):
(WTF::TimeWithDynamicClockType::operator==):
(WTF::TimeWithDynamicClockType::operator!=):
* wtf/WallTime.cpp: Added.
(WTF::WallTime::now):
(WTF::WallTime::approximateMonotonicTime):
(WTF::WallTime::dump):
(WTF::WallTime::sleep):
* wtf/WallTime.h: Added.
(WTF::WallTime::WallTime):
(WTF::WallTime::fromRawDouble):
(WTF::WallTime::infinity):
(WTF::WallTime::secondsSinceEpoch):
(WTF::WallTime::approximateWallTime):
(WTF::WallTime::operator bool):
(WTF::WallTime::operator+):
(WTF::WallTime::operator-):
(WTF::WallTime::operator+=):
(WTF::WallTime::operator-=):
(WTF::WallTime::operator==):
(WTF::WallTime::operator!=):
(WTF::WallTime::operator<):
(WTF::WallTime::operator>):
(WTF::WallTime::operator<=):
(WTF::WallTime::operator>=):
* wtf/threads/BinarySemaphore.cpp:
(WTF::BinarySemaphore::wait):
* wtf/threads/BinarySemaphore.h:
Tools:
* TestWebKitAPI/CMakeLists.txt:
* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WTF/Condition.cpp:
(TestWebKitAPI::TEST):
* TestWebKitAPI/Tests/WTF/SynchronizedFixedQueue.cpp:
(TestWebKitAPI::ToUpperConverter::stopProducing):
(TestWebKitAPI::ToUpperConverter::stopConsuming):
* TestWebKitAPI/Tests/WTF/Time.cpp: Added.
(WTF::operator<<):
(TestWebKitAPI::TEST):
Canonical link: https://commits.webkit.org/182152@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@208415 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2016-11-05 03:02:39 +00:00
|
|
|
using WTF::WallTime;
|