blob: 4961ee3a0c7622943a1fd6f1e77a36c659ad5a1d [file] [log] [blame]
// Copyright 2024 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
#pragma once
#include "pw_function/function.h"
namespace pw::thread {
/// An old-style ThreadRoutine function pointer.
///
/// This is deprecated and should not be used in new code.
using DeprecatedFnPtr = void (*)(void* arg);
/// An old-style ThreadRoutine function pointer and argument.
///
/// This is deprecated and should not be used in new code.
struct DeprecatedFnPtrAndArg {
DeprecatedFnPtr fn_ptr_;
void* fn_arg_;
};
/// For internal thread backend implementation only.
///
/// This is used to store either a deprecated ThreadRoutine or a pw::Function.
class DeprecatedOrNewThreadFn {
public:
DeprecatedOrNewThreadFn() : fn_(), is_deprecated_(false) {}
DeprecatedOrNewThreadFn(const DeprecatedOrNewThreadFn&) = delete;
DeprecatedOrNewThreadFn& operator=(const DeprecatedOrNewThreadFn&) = delete;
DeprecatedOrNewThreadFn(DeprecatedOrNewThreadFn&& other)
: is_deprecated_(other.is_deprecated_) {
if (other.is_deprecated_) {
deprecated_ = other.deprecated_;
} else {
new (&fn_) Function<void()>(std::move(other.fn_));
}
}
DeprecatedOrNewThreadFn& operator=(DeprecatedOrNewThreadFn&& other) {
DestroyIfFunction();
if (other.is_deprecated_) {
deprecated_ = other.deprecated_;
is_deprecated_ = true;
} else {
new (&fn_) Function<void()>(std::move(other.fn_));
is_deprecated_ = false;
}
return *this;
}
DeprecatedOrNewThreadFn& operator=(std::nullptr_t) {
*this = Function<void()>(nullptr);
return *this;
}
DeprecatedOrNewThreadFn(DeprecatedFnPtrAndArg&& deprecated)
: deprecated_(deprecated), is_deprecated_(true) {}
DeprecatedOrNewThreadFn& operator=(DeprecatedFnPtrAndArg&& deprecated) {
DestroyIfFunction();
deprecated_ = deprecated;
is_deprecated_ = true;
return *this;
}
DeprecatedOrNewThreadFn(Function<void()>&& fn)
: fn_(std::move(fn)), is_deprecated_(false) {}
DeprecatedOrNewThreadFn& operator=(Function<void()>&& fn) {
DestroyIfFunction();
new (&fn_) Function<void()>(std::move(fn));
is_deprecated_ = false;
return *this;
}
~DeprecatedOrNewThreadFn() { DestroyIfFunction(); }
void operator()() {
if (is_deprecated_) {
deprecated_.fn_ptr_(deprecated_.fn_arg_);
} else {
fn_();
}
}
private:
void DestroyIfFunction() {
if (!is_deprecated_) {
std::destroy_at(&fn_);
}
}
union {
DeprecatedFnPtrAndArg deprecated_;
Function<void()> fn_;
};
bool is_deprecated_;
};
} // namespace pw::thread