// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 #pragma once #include "Thread.h" #include <atomic> namespace Aws { namespace IoTFleetWise { namespace OffboardConnectivityAwsIot { using namespace Aws::IoTFleetWise::Platform::Linux; enum class RetryStatus { SUCCESS, RETRY, ABORT }; class IRetryable { public: /** * @brief This function will be called for every retry * @return decides if the function can be retried later or succeeded or unrecoverable failed */ virtual RetryStatus attempt() = 0; /** * @brief Is called after the retries stopped which means it succeeded or is aborted * @param code signals how it finished: if it was aborted or succeeded. retry should be never observed here */ virtual void onFinished( RetryStatus code ) = 0; virtual ~IRetryable() = default; }; class RetryThread { public: RetryThread( IRetryable &retryable, uint32_t startBackoffMs, uint32_t maxBackoffMs ); /** * @brief start the thread * @return true if thread starting was successful */ bool start(); /** * @brief stops the thread * @return true if thread stopping was successful */ bool stop(); /** * @brief check if thread is currently running * @return true if thread is currently running */ bool isAlive() { return fThread.isValid() && fThread.isActive(); } ~RetryThread() { // To make sure the thread stops during teardown of tests. if ( isAlive() ) { stop(); } } RetryThread( const RetryThread & ) = delete; RetryThread &operator=( const RetryThread & ) = delete; RetryThread( RetryThread && ) = delete; RetryThread &operator=( RetryThread && ) = delete; private: static void doWork( void *data ); static std::atomic<int> fInstanceCounter; IRetryable &fRetryable; int fInstance; const uint32_t fStartBackoffMs; const uint32_t fMaxBackoffMs; uint32_t fCurrentWaitTime; Thread fThread; std::atomic<bool> fShouldStop; std::mutex fThreadMutex; Signal fWait; }; } // namespace OffboardConnectivityAwsIot } // namespace IoTFleetWise } // namespace Aws