From 464a4bf527b9da30985a6576f702429621a849a6 Mon Sep 17 00:00:00 2001 From: jacqueline Date: Fri, 21 Apr 2023 18:42:49 +1000 Subject: [PATCH] Add a RAII-friendly DI wrapper for driver instances --- src/drivers/driver_cache.cpp | 43 ++++++++++++++++++++++ src/drivers/include/driver_cache.hpp | 54 ++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/drivers/driver_cache.cpp create mode 100644 src/drivers/include/driver_cache.hpp diff --git a/src/drivers/driver_cache.cpp b/src/drivers/driver_cache.cpp new file mode 100644 index 00000000..650e6f16 --- /dev/null +++ b/src/drivers/driver_cache.cpp @@ -0,0 +1,43 @@ +#include "driver_cache.hpp" + +#include +#include + +#include "display.hpp" +#include "display_init.hpp" +#include "storage.hpp" +#include "touchwheel.hpp" + +namespace drivers { + +DriverCache::DriverCache() : gpios_(std::make_unique()) {} +DriverCache::~DriverCache() {} + +auto DriverCache::AcquireGpios() -> GpioExpander* { + return gpios_.get(); +} + +auto DriverCache::AcquireDac() -> std::shared_ptr { + return Acquire(dac_, [&]() -> AudioDac* { + return AudioDac::create(AcquireGpios()).value_or(nullptr); + }); +} + +auto DriverCache::AcquireDisplay() -> std::shared_ptr { + return Acquire(display_, [&]() -> Display* { + return Display::create(AcquireGpios(), displays::kST7735R); + }); +} + +auto DriverCache::AcquireStorage() -> std::shared_ptr { + return Acquire(storage_, [&]() -> SdStorage* { + return SdStorage::create(AcquireGpios()).value_or(nullptr); + }); +} + +auto DriverCache::AcquireTouchWheel() -> std::shared_ptr { + return Acquire(touchwheel_, + [&]() -> TouchWheel* { return new TouchWheel(); }); +} + +} // namespace drivers diff --git a/src/drivers/include/driver_cache.hpp b/src/drivers/include/driver_cache.hpp new file mode 100644 index 00000000..c56ebc3f --- /dev/null +++ b/src/drivers/include/driver_cache.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include +#include + +#include "dac.hpp" +#include "display.hpp" +#include "gpio_expander.hpp" +#include "storage.hpp" +#include "touchwheel.hpp" + +namespace drivers { + +class DriverCache { + private: + std::unique_ptr gpios_; + std::weak_ptr dac_; + std::weak_ptr display_; + std::weak_ptr storage_; + std::weak_ptr touchwheel_; + // TODO(jacqueline): Haptics, samd + + std::mutex mutex_; + + template + auto Acquire(std::weak_ptr ptr, F factory) -> std::shared_ptr { + std::shared_ptr acquired = ptr.lock(); + if (acquired) { + return acquired; + } + + std::lock_guard lock(mutex_); + + acquired = ptr.lock(); + if (acquired) { + return acquired; + } + acquired.reset(factory()); + ptr = acquired; + return acquired; + } + + public: + DriverCache(); + ~DriverCache(); + + auto AcquireGpios() -> GpioExpander*; + auto AcquireDac() -> std::shared_ptr; + auto AcquireDisplay() -> std::shared_ptr; + auto AcquireStorage() -> std::shared_ptr; + auto AcquireTouchWheel() -> std::shared_ptr; +}; + +} // namespace drivers