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 <cstddef> 17 #include <limits> 18 19 #include "pw_thread/attrs.h" 20 #include "pw_thread/stack.h" 21 #include "pw_thread_backend/context.h" 22 23 namespace pw { 24 25 inline constexpr size_t kExternallyAllocatedThreadStack = 26 std::numeric_limits<size_t>::max(); 27 28 /// Represents the resources required for one thread. May include OS data 29 /// structures, the thread stack, or be empty, depending on the platform. 30 /// 31 /// `ThreadContext` may be reused or deleted if the associated thread is 32 /// joined. 33 /// 34 /// `ThreadContext` takes an optional stack size template parameter. If a stack 35 /// size is provided, the context allocates a stack internally, if supported by 36 /// the backend. If no stack is is provided (`ThreadContext<>`), the 37 /// `ThreadContext` must be paired with a `pw::ThreadStack`. 38 template <size_t kStackSizeBytes = kExternallyAllocatedThreadStack> 39 class ThreadContext { 40 public: 41 constexpr ThreadContext() = default; 42 43 ThreadContext(const ThreadContext&) = delete; 44 ThreadContext& operator=(const ThreadContext&) = delete; 45 native()46 constexpr thread::backend::NativeContextWithStack<kStackSizeBytes>& native() { 47 return native_context_; 48 } 49 50 private: 51 thread::backend::NativeContextWithStack<kStackSizeBytes> native_context_; 52 }; 53 54 // ThreadContext with externally allocated stack. 55 template <> 56 class ThreadContext<kExternallyAllocatedThreadStack> { 57 public: 58 constexpr ThreadContext() = default; 59 60 ThreadContext(const ThreadContext&) = delete; 61 ThreadContext& operator=(const ThreadContext&) = delete; 62 native()63 constexpr thread::backend::NativeContext& native() { return native_context_; } 64 65 private: 66 thread::backend::NativeContext native_context_; 67 }; 68 69 /// Declares a `ThreadContext` that is associated with a specific set of thread 70 /// attributes. The `ThreadContext` may be reused if the associated thread is 71 /// joined, but all threads use the same `ThreadAttrs`. 72 template <const ThreadAttrs& kAttributes> 73 class ThreadContextFor { 74 public: 75 constexpr ThreadContextFor() = default; 76 77 ThreadContextFor(const ThreadContextFor&) = delete; 78 ThreadContextFor& operator=(const ThreadContextFor&) = delete; 79 native()80 constexpr auto& native() { return context_.native(); } 81 82 private: 83 ThreadContext<kAttributes.has_external_stack() 84 ? kExternallyAllocatedThreadStack 85 : kAttributes.stack_size_bytes()> 86 context_; 87 }; 88 89 /// Alias for ThreadContext with the backend's default stack size. 90 using DefaultThreadContext = 91 ThreadContext<thread::backend::kDefaultStackSizeBytes>; 92 93 } // namespace pw 94