blob: 159932bf499c1cc1e5916ff7bd8ce73ed3b0afc9 [file] [log] [blame] [edit]
#ifndef THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_UTILS_STD_THREAD_H_
#define THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_UTILS_STD_THREAD_H_
#include <exception> // NOLINT: This is only used/built in gBMC.
#include <memory>
#include <string>
#include <system_error> // NOLINT: This is only used/built in gBMC.
#include <thread> // NOLINT: This is only used/built in gBMC.
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "utils/thread.h"
inline constexpr int kThreadStartRetryCount = 12;
inline constexpr absl::Duration kThreadStartRetrySleepDuration =
absl::Seconds(5);
namespace milotic {
class StdThread : public MiloticThread {
public:
explicit StdThread(absl::string_view name_prefix,
absl::AnyInvocable<void() &&> functor)
: name_prefix_(name_prefix), functor_(std::move(functor)) {}
absl::Status Start() override {
// Wrap the functor in a shared_ptr so we can pass a copy to the thread
// lambda. If thread creation fails, the lambda (and its copy of the
// shared_ptr) is destroyed, but the underlying functor remains valid for
// the next retry. Use std::move(*shared_functor) to properly invoke the
// &&-qualified AnyInvocable when the thread actually runs.
auto shared_functor =
std::make_shared<absl::AnyInvocable<void() &&>>(std::move(functor_));
bool started = false;
for (int i = 0; i < kThreadStartRetryCount; ++i) {
try { // NOLINT(misc-include-cleaner): This is only used/built in gBMC.
thread_ =
std::thread([shared_functor]() { std::move (*shared_functor)(); });
started = true;
break;
} catch (...) { // NOLINT(misc-include-cleaner)
LOG(ERROR) << name_prefix_ << " Failed to create/start thread: "
<< ", retrying in " << kThreadStartRetrySleepDuration;
thread_ = std::thread();
absl::SleepFor(kThreadStartRetrySleepDuration);
}
}
if (!started) {
return absl::ResourceExhaustedError(absl::StrCat(
"Failed to create/start thread after ",
kThreadStartRetryCount * kThreadStartRetrySleepDuration));
}
return absl::OkStatus();
}
void Join() override { thread_.join(); }
~StdThread() override = default;
private:
std::thread thread_;
std::string name_prefix_;
absl::AnyInvocable<void() &&> functor_;
};
} // namespace milotic
#endif // THIRD_PARTY_MILOTIC_INTERNAL_CC_PROXY_UTILS_STD_THREAD_H_