• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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