diff options
-rw-r--r-- | include/ftl/algorithm.h | 25 | ||||
-rw-r--r-- | libs/ftl/algorithm_test.cpp | 16 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/RefreshRateStats.h | 20 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 10 |
5 files changed, 65 insertions, 11 deletions
diff --git a/include/ftl/algorithm.h b/include/ftl/algorithm.h index c5ff03b80d..c0f67683ab 100644 --- a/include/ftl/algorithm.h +++ b/include/ftl/algorithm.h @@ -68,4 +68,29 @@ constexpr auto to_mapped_ref(const Pair& pair) -> std::reference_wrapper<const M return std::cref(pair.second); } +// Combinator for ftl::Optional<T>::or_else when T is std::reference_wrapper<const V>. Given a +// lambda argument that returns a `constexpr` value, ftl::static_ref<T> binds a reference to a +// static T initialized to that constant. +// +// const ftl::SmallMap map = ftl::init::map(13, "tiramisu"sv)(14, "upside-down cake"sv); +// assert("???"sv == +// map.get(20).or_else(ftl::static_ref<std::string_view>([] { return "???"sv; }))->get()); +// +// using Map = decltype(map); +// +// assert("snow cone"sv == +// ftl::find_if(map, [](const auto& pair) { return pair.second.front() == 's'; }) +// .transform(ftl::to_mapped_ref<Map>) +// .or_else(ftl::static_ref<std::string_view>([] { return "snow cone"sv; })) +// ->get()); +// +template <typename T, typename F> +constexpr auto static_ref(F&& f) { + return [f = std::forward<F>(f)] { + constexpr auto kInitializer = f(); + static const T kValue = kInitializer; + return Optional(std::cref(kValue)); + }; +} + } // namespace android::ftl diff --git a/libs/ftl/algorithm_test.cpp b/libs/ftl/algorithm_test.cpp index 8052caf642..487b1b8759 100644 --- a/libs/ftl/algorithm_test.cpp +++ b/libs/ftl/algorithm_test.cpp @@ -47,4 +47,20 @@ TEST(Algorithm, FindIf) { EXPECT_EQ(opt->get(), ftl::StaticVector("tiramisu"sv)); } +TEST(Algorithm, StaticRef) { + using namespace std::string_view_literals; + + const ftl::SmallMap map = ftl::init::map(13, "tiramisu"sv)(14, "upside-down cake"sv); + ASSERT_EQ("???"sv, + map.get(20).or_else(ftl::static_ref<std::string_view>([] { return "???"sv; }))->get()); + + using Map = decltype(map); + + ASSERT_EQ("snow cone"sv, + ftl::find_if(map, [](const auto& pair) { return pair.second.front() == 's'; }) + .transform(ftl::to_mapped_ref<Map>) + .or_else(ftl::static_ref<std::string_view>([] { return "snow cone"sv; })) + ->get()); +} + } // namespace android::test diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index ed65bc607d..67e1b9c2ea 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -22,6 +22,7 @@ #include <string> #include <android-base/stringprintf.h> +#include <ftl/algorithm.h> #include <ftl/small_map.h> #include <utils/Timers.h> @@ -82,12 +83,18 @@ public: flushTime(); TotalTimes totalTimes = ftl::init::map("ScreenOff", mScreenOffTime); - const auto zero = std::chrono::milliseconds::zero(); // Sum the times for modes that map to the same name, e.g. "60 Hz". for (const auto& [fps, time] : mFpsTotalTimes) { const auto string = to_string(fps); - const auto total = std::as_const(totalTimes).get(string).value_or(std::cref(zero)); + const auto total = std::as_const(totalTimes) + .get(string) + .or_else(ftl::static_ref<std::chrono::milliseconds>([] { + using namespace std::chrono_literals; + return 0ms; + })) + .value(); + totalTimes.emplace_or_replace(string, total.get() + time); } @@ -114,15 +121,18 @@ private: mPreviousRecordedTime = currentTime; const auto duration = std::chrono::milliseconds{ns2ms(timeElapsed)}; - const auto zero = std::chrono::milliseconds::zero(); - uint32_t fps = 0; if (mCurrentPowerMode == PowerMode::ON) { // Normal power mode is counted under different config modes. const auto total = std::as_const(mFpsTotalTimes) .get(mCurrentRefreshRate) - .value_or(std::cref(zero)); + .or_else(ftl::static_ref<std::chrono::milliseconds>([] { + using namespace std::chrono_literals; + return 0ms; + })) + .value(); + mFpsTotalTimes.emplace_or_replace(mCurrentRefreshRate, total.get() + duration); fps = static_cast<uint32_t>(mCurrentRefreshRate.getIntValue()); diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 720a1cbba2..4b2983b33d 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -32,6 +32,7 @@ #include <ui/GraphicTypes.h> #pragma clang diagnostic pop // ignored "-Wconversion -Wextra" +#include <ftl/algorithm.h> #include <ftl/fake_guard.h> #include <ftl/optional.h> #include <scheduler/Features.h> @@ -438,13 +439,13 @@ private: RefreshRateSelectorPtr pacesetterSelectorPtrLocked() const REQUIRES(mDisplayLock) { ftl::FakeGuard guard(kMainThreadContext); - const RefreshRateSelectorPtr noPacesetter; return mPacesetterDisplayId .and_then([this](PhysicalDisplayId pacesetterId) REQUIRES(mDisplayLock, kMainThreadContext) { return mRefreshRateSelectors.get(pacesetterId); }) - .value_or(std::cref(noPacesetter)); + .or_else(ftl::static_ref<RefreshRateSelectorPtr>([] { return nullptr; })) + .value(); } std::shared_ptr<const VsyncSchedule> getVsyncScheduleLocked( diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index eb9dc7494e..04fcfb9097 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -28,6 +28,7 @@ #include <android/gui/ISurfaceComposerClient.h> #include <cutils/atomic.h> #include <cutils/compiler.h> +#include <ftl/algorithm.h> #include <ftl/future.h> #include <ftl/non_null.h> #include <gui/BufferQueue.h> @@ -854,8 +855,9 @@ private: } sp<DisplayDevice> getDisplayDeviceLocked(const wp<IBinder>& displayToken) REQUIRES(mStateLock) { - const sp<DisplayDevice> nullDisplay; - return mDisplays.get(displayToken).value_or(std::cref(nullDisplay)); + return mDisplays.get(displayToken) + .or_else(ftl::static_ref<sp<DisplayDevice>>([] { return nullptr; })) + .value(); } sp<const DisplayDevice> getDisplayDeviceLocked(PhysicalDisplayId id) const @@ -1011,10 +1013,10 @@ private: */ sp<display::DisplayToken> getPhysicalDisplayTokenLocked(PhysicalDisplayId displayId) const REQUIRES(mStateLock) { - const sp<display::DisplayToken> nullToken; return mPhysicalDisplays.get(displayId) .transform([](const display::PhysicalDisplay& display) { return display.token(); }) - .value_or(std::cref(nullToken)); + .or_else([] { return std::optional<sp<display::DisplayToken>>(nullptr); }) + .value(); } std::optional<PhysicalDisplayId> getPhysicalDisplayIdLocked( |