1 // Copyright 2024 The Pigweed Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not 4 // use this file except in compliance with the License. You may obtain a copy of 5 // the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 // License for the specific language governing permissions and limitations under 13 // the License. 14 #pragma once 15 16 #include "pw_function/function.h" 17 18 namespace pw::thread { 19 20 /// An old-style ThreadRoutine function pointer. 21 /// 22 /// This is deprecated and should not be used in new code. 23 using DeprecatedFnPtr = void (*)(void* arg); 24 25 /// An old-style ThreadRoutine function pointer and argument. 26 /// 27 /// This is deprecated and should not be used in new code. 28 struct DeprecatedFnPtrAndArg { 29 DeprecatedFnPtr fn_ptr_; 30 void* fn_arg_; 31 }; 32 33 /// For internal thread backend implementation only. 34 /// 35 /// This is used to store either a deprecated ThreadRoutine or a pw::Function. 36 class DeprecatedOrNewThreadFn { 37 public: DeprecatedOrNewThreadFn()38 DeprecatedOrNewThreadFn() : fn_(), is_deprecated_(false) {} 39 DeprecatedOrNewThreadFn(const DeprecatedOrNewThreadFn&) = delete; 40 DeprecatedOrNewThreadFn& operator=(const DeprecatedOrNewThreadFn&) = delete; 41 DeprecatedOrNewThreadFn(DeprecatedOrNewThreadFn && other)42 DeprecatedOrNewThreadFn(DeprecatedOrNewThreadFn&& other) 43 : is_deprecated_(other.is_deprecated_) { 44 if (other.is_deprecated_) { 45 deprecated_ = other.deprecated_; 46 } else { 47 new (&fn_) Function<void()>(std::move(other.fn_)); 48 } 49 } 50 51 DeprecatedOrNewThreadFn& operator=(DeprecatedOrNewThreadFn&& other) { 52 DestroyIfFunction(); 53 if (other.is_deprecated_) { 54 deprecated_ = other.deprecated_; 55 is_deprecated_ = true; 56 } else { 57 new (&fn_) Function<void()>(std::move(other.fn_)); 58 is_deprecated_ = false; 59 } 60 return *this; 61 } 62 63 DeprecatedOrNewThreadFn& operator=(std::nullptr_t) { 64 *this = Function<void()>(nullptr); 65 return *this; 66 } 67 DeprecatedOrNewThreadFn(DeprecatedFnPtrAndArg && deprecated)68 DeprecatedOrNewThreadFn(DeprecatedFnPtrAndArg&& deprecated) 69 : deprecated_(deprecated), is_deprecated_(true) {} 70 71 DeprecatedOrNewThreadFn& operator=(DeprecatedFnPtrAndArg&& deprecated) { 72 DestroyIfFunction(); 73 deprecated_ = deprecated; 74 is_deprecated_ = true; 75 return *this; 76 } 77 DeprecatedOrNewThreadFn(Function<void ()> && fn)78 DeprecatedOrNewThreadFn(Function<void()>&& fn) 79 : fn_(std::move(fn)), is_deprecated_(false) {} 80 81 DeprecatedOrNewThreadFn& operator=(Function<void()>&& fn) { 82 DestroyIfFunction(); 83 new (&fn_) Function<void()>(std::move(fn)); 84 is_deprecated_ = false; 85 return *this; 86 } 87 ~DeprecatedOrNewThreadFn()88 ~DeprecatedOrNewThreadFn() { DestroyIfFunction(); } 89 operator()90 void operator()() { 91 if (is_deprecated_) { 92 deprecated_.fn_ptr_(deprecated_.fn_arg_); 93 } else { 94 fn_(); 95 } 96 } 97 98 private: DestroyIfFunction()99 void DestroyIfFunction() { 100 if (!is_deprecated_) { 101 std::destroy_at(&fn_); 102 } 103 } 104 105 union { 106 DeprecatedFnPtrAndArg deprecated_; 107 Function<void()> fn_; 108 }; 109 bool is_deprecated_; 110 }; 111 112 } // namespace pw::thread 113