diff options
Diffstat (limited to 'pw_thread_stl')
17 files changed, 605 insertions, 0 deletions
diff --git a/pw_thread_stl/BUILD b/pw_thread_stl/BUILD new file mode 100644 index 000000000..e7624a606 --- /dev/null +++ b/pw_thread_stl/BUILD @@ -0,0 +1,131 @@ +# Copyright 2020 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. + +load( + "//pw_build:pigweed.bzl", + "pw_cc_library", + "pw_cc_test", +) + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) # Apache License 2.0 + +pw_cc_library( + name = "id_headers", + hdrs = [ + "public/pw_thread_stl/id_inline.h", + "public/pw_thread_stl/id_native.h", + "public_overrides/pw_thread_backend/id_inline.h", + "public_overrides/pw_thread_backend/id_native.h", + ], + includes = [ + "public", + "public_overrides", + ], +) + +pw_cc_library( + name = "id", + deps = [ + ":id_headers", + "//pw_thread:id_facade", + ], +) + +pw_cc_library( + name = "sleep_headers", + hdrs = [ + "public/pw_thread_stl/sleep_inline.h", + "public_overrides/pw_thread_backend/sleep_inline.h", + ], + includes = [ + "public", + "public_overrides", + ], + deps = [ + "//pw_chrono:system_clock", + ], +) + +pw_cc_library( + name = "sleep", + deps = [ + ":sleep_headers", + "//pw_chrono:system_clock", + "//pw_thread:sleep_facade", + ], +) + +pw_cc_library( + name = "thread_headers", + hdrs = [ + "public/pw_thread_stl/options.h", + "public/pw_thread_stl/thread_inline.h", + "public/pw_thread_stl/thread_native.h", + "public_overrides/pw_thread_backend/thread_inline.h", + "public_overrides/pw_thread_backend/thread_native.h", + ], + includes = [ + "public", + "public_overrides", + ], +) + +pw_cc_library( + name = "thread", + deps = [ + ":thread_headers", + "//pw_thread:thread_facade", + ], +) + +pw_cc_library( + name = "test_threads", + deps = [ + "//pw_thread:thread_facade", + "//pw_thread:test_threads_header", + ], + srcs = [ + "test_threads.cc", + ] +) + +pw_cc_test( + name = "thread_backend_test", + deps = [ + "//pw_thread:thread_facade_test", + ":test_threads", + ] +) + +pw_cc_library( + name = "yield_headers", + hdrs = [ + "public/pw_thread_stl/yield_inline.h", + "public_overrides/pw_thread_backend/yield_inline.h", + ], + includes = [ + "public", + "public_overrides", + ], +) + +pw_cc_library( + name = "yield", + deps = [ + ":yield_headers", + "//pw_thread:yield_facade", + ], +) diff --git a/pw_thread_stl/BUILD.gn b/pw_thread_stl/BUILD.gn new file mode 100644 index 000000000..37ccf9b11 --- /dev/null +++ b/pw_thread_stl/BUILD.gn @@ -0,0 +1,122 @@ +# Copyright 2020 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. + +import("//build_overrides/pigweed.gni") + +import("$dir_pw_build/target_types.gni") +import("$dir_pw_chrono/backend.gni") +import("$dir_pw_docgen/docs.gni") +import("$dir_pw_thread/backend.gni") +import("$dir_pw_unit_test/test.gni") + +config("public_include_path") { + include_dirs = [ "public" ] + visibility = [ ":*" ] +} + +config("backend_config") { + include_dirs = [ "public_overrides" ] + visibility = [ ":*" ] +} + +# This target provides the backend for pw::thread::Id & pw::this_thread::get_id. +pw_source_set("id") { + public_configs = [ + ":public_include_path", + ":backend_config", + ] + public = [ + "public/pw_thread_stl/id_inline.h", + "public/pw_thread_stl/id_native.h", + "public_overrides/pw_thread_backend/id_inline.h", + "public_overrides/pw_thread_backend/id_native.h", + ] + deps = [ "$dir_pw_thread:id.facade" ] +} + +# This target provides the backend for pw::thread::Thread with joining +# joining capability. +pw_source_set("thread") { + public_configs = [ + ":public_include_path", + ":backend_config", + ] + public = [ + "public/pw_thread_stl/options.h", + "public/pw_thread_stl/thread_inline.h", + "public/pw_thread_stl/thread_native.h", + "public_overrides/pw_thread_backend/thread_inline.h", + "public_overrides/pw_thread_backend/thread_native.h", + ] + allow_circular_includes_from = [ "$dir_pw_thread:thread.facade" ] + deps = [ "$dir_pw_thread:thread.facade" ] +} + +# This target provides the backend for pw::this_thread::sleep_{for,until}. +pw_source_set("sleep") { + public_configs = [ + ":public_include_path", + ":backend_config", + ] + public = [ + "public/pw_thread_stl/sleep_inline.h", + "public_overrides/pw_thread_backend/sleep_inline.h", + ] + deps = [ + "$dir_pw_chrono:system_clock", + "$dir_pw_thread:sleep.facade", + ] + assert( + pw_chrono_SYSTEM_CLOCK_BACKEND == "" || + pw_chrono_SYSTEM_CLOCK_BACKEND == "$dir_pw_chrono_stl:system_clock", + "The STL pw::this_thread::sleep_{for,until} backend only works with " + + "the STL pw::chrono::SystemClock backend " + + "(pw_chrono_SYSTEM_CLOCK_BACKEND = " + + "\"$dir_pw_chrono_stl:system_clock\")") +} + +# This target provides the backend for pw::this_thread::yield. +pw_source_set("yield") { + public_configs = [ + ":public_include_path", + ":backend_config", + ] + public = [ + "public/pw_thread_stl/yield_inline.h", + "public_overrides/pw_thread_backend/yield_inline.h", + ] + deps = [ "$dir_pw_thread:yield.facade" ] +} + +pw_test_group("tests") { + tests = [ ":thread_backend_test" ] +} + +pw_source_set("test_threads") { + public_deps = [ "$dir_pw_thread:test_threads" ] + sources = [ "test_threads.cc" ] + deps = [ "$dir_pw_thread:thread" ] +} + +pw_test("thread_backend_test") { + enable_if = pw_thread_THREAD_BACKEND == "$dir_pw_thread_stl:thread" + deps = [ + ":test_threads", + "$dir_pw_thread:thread_facade_test", + ] +} + +pw_doc_group("docs") { + sources = [ "docs.rst" ] +} diff --git a/pw_thread_stl/docs.rst b/pw_thread_stl/docs.rst new file mode 100644 index 000000000..116902066 --- /dev/null +++ b/pw_thread_stl/docs.rst @@ -0,0 +1,8 @@ +.. _module-pw_thread_stl: + +------------- +pw_thread_stl +------------- +This is a set of backends for pw_thread based on the C++ STL. It is not ready +for use, and is under construction. + diff --git a/pw_thread_stl/public/pw_thread_stl/id_inline.h b/pw_thread_stl/public/pw_thread_stl/id_inline.h new file mode 100644 index 000000000..2d36a732e --- /dev/null +++ b/pw_thread_stl/public/pw_thread_stl/id_inline.h @@ -0,0 +1,24 @@ +// Copyright 2020 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 <thread> + +#include "pw_thread/id.h" + +namespace pw::this_thread { + +inline thread::Id get_id() noexcept { return std::this_thread::get_id(); } + +} // namespace pw::this_thread diff --git a/pw_thread_stl/public/pw_thread_stl/id_native.h b/pw_thread_stl/public/pw_thread_stl/id_native.h new file mode 100644 index 000000000..26a213c17 --- /dev/null +++ b/pw_thread_stl/public/pw_thread_stl/id_native.h @@ -0,0 +1,22 @@ +// Copyright 2020 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 <thread> + +namespace pw::thread::backend { + +using NativeId = std::thread::id; + +} // namespace pw::thread::backend diff --git a/pw_thread_stl/public/pw_thread_stl/options.h b/pw_thread_stl/public/pw_thread_stl/options.h new file mode 100644 index 000000000..26f5bf578 --- /dev/null +++ b/pw_thread_stl/public/pw_thread_stl/options.h @@ -0,0 +1,26 @@ +// Copyright 2020 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_thread/thread.h" + +namespace pw::thread::stl { + +// Unfortunately std::thread:attributes was not accepted into the C++ standard. +// Instead, users are expected to start the thread and after dynamically adjust +// the thread's attributes using std::thread::native_handle based on the native +// threading APIs. +class Options : public thread::Options {}; + +} // namespace pw::thread::stl diff --git a/pw_thread_stl/public/pw_thread_stl/sleep_inline.h b/pw_thread_stl/public/pw_thread_stl/sleep_inline.h new file mode 100644 index 000000000..2b0a9149b --- /dev/null +++ b/pw_thread_stl/public/pw_thread_stl/sleep_inline.h @@ -0,0 +1,42 @@ +// Copyright 2020 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 <thread> + +#include "pw_chrono/system_clock.h" +#include "pw_thread/sleep.h" + +namespace pw::this_thread { + +inline void sleep_for(chrono::SystemClock::duration for_at_least) { + for_at_least = std::max(for_at_least, chrono::SystemClock::duration::zero()); + // Although many implementations do yield with sleep_for(0), it is not + // required, ergo we explicitly add handling. + if (for_at_least == chrono::SystemClock::duration::zero()) { + return std::this_thread::yield(); + } + return std::this_thread::sleep_for(for_at_least); +} + +inline void sleep_until(chrono::SystemClock::time_point until_at_least) { + // Although many implementations do yield with deadlines in the past until + // the current time, it is not required, ergo we explicitly add handling. + if (chrono::SystemClock::now() >= until_at_least) { + return std::this_thread::yield(); + } + return std::this_thread::sleep_until(until_at_least); +} + +} // namespace pw::this_thread diff --git a/pw_thread_stl/public/pw_thread_stl/thread_inline.h b/pw_thread_stl/public/pw_thread_stl/thread_inline.h new file mode 100644 index 000000000..018e80755 --- /dev/null +++ b/pw_thread_stl/public/pw_thread_stl/thread_inline.h @@ -0,0 +1,47 @@ +// Copyright 2020 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 <thread> + +namespace pw::thread { + +inline Thread::Thread() : native_type_() {} + +inline Thread::Thread(const Options&, ThreadRoutine entry, void* arg) { + native_type_ = std::thread(entry, arg); +} + +inline Thread& Thread::operator=(Thread&& other) { + native_type_ = std::move(other.native_type_); + return *this; +} + +inline Thread::~Thread() = default; + +inline Id Thread::get_id() const { return native_type_.get_id(); } + +inline void Thread::join() { native_type_.join(); } + +inline void Thread::detach() { native_type_.detach(); } + +inline void Thread::swap(Thread& other) { + native_type_.swap(other.native_handle()); +} + +inline Thread::native_handle_type Thread::native_handle() { + return native_type_; +} + +} // namespace pw::thread diff --git a/pw_thread_stl/public/pw_thread_stl/thread_native.h b/pw_thread_stl/public/pw_thread_stl/thread_native.h new file mode 100644 index 000000000..d3592de1b --- /dev/null +++ b/pw_thread_stl/public/pw_thread_stl/thread_native.h @@ -0,0 +1,25 @@ +// Copyright 2020 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 <thread> + +#define PW_THREAD_JOINING_ENABLED 1 + +namespace pw::thread::backend { + +using NativeThread = std::thread; +using NativeThreadHandle = std::thread&; + +} // namespace pw::thread::backend diff --git a/pw_thread_stl/public/pw_thread_stl/yield_inline.h b/pw_thread_stl/public/pw_thread_stl/yield_inline.h new file mode 100644 index 000000000..ec018533d --- /dev/null +++ b/pw_thread_stl/public/pw_thread_stl/yield_inline.h @@ -0,0 +1,22 @@ +// Copyright 2020 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 <thread> + +namespace pw::this_thread { + +inline void yield() noexcept { std::this_thread::yield(); } + +} // namespace pw::this_thread diff --git a/pw_thread_stl/public_overrides/pw_thread_backend/id_inline.h b/pw_thread_stl/public_overrides/pw_thread_backend/id_inline.h new file mode 100644 index 000000000..56f5e5d4f --- /dev/null +++ b/pw_thread_stl/public_overrides/pw_thread_backend/id_inline.h @@ -0,0 +1,16 @@ +// Copyright 2020 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_thread_stl/id_inline.h" diff --git a/pw_thread_stl/public_overrides/pw_thread_backend/id_native.h b/pw_thread_stl/public_overrides/pw_thread_backend/id_native.h new file mode 100644 index 000000000..82aa09685 --- /dev/null +++ b/pw_thread_stl/public_overrides/pw_thread_backend/id_native.h @@ -0,0 +1,16 @@ +// Copyright 2020 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_thread_stl/id_native.h" diff --git a/pw_thread_stl/public_overrides/pw_thread_backend/sleep_inline.h b/pw_thread_stl/public_overrides/pw_thread_backend/sleep_inline.h new file mode 100644 index 000000000..8d0132a85 --- /dev/null +++ b/pw_thread_stl/public_overrides/pw_thread_backend/sleep_inline.h @@ -0,0 +1,16 @@ +// Copyright 2020 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_thread_stl/sleep_inline.h" diff --git a/pw_thread_stl/public_overrides/pw_thread_backend/thread_inline.h b/pw_thread_stl/public_overrides/pw_thread_backend/thread_inline.h new file mode 100644 index 000000000..2a52ee866 --- /dev/null +++ b/pw_thread_stl/public_overrides/pw_thread_backend/thread_inline.h @@ -0,0 +1,16 @@ +// Copyright 2020 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_thread_stl/thread_inline.h" diff --git a/pw_thread_stl/public_overrides/pw_thread_backend/thread_native.h b/pw_thread_stl/public_overrides/pw_thread_backend/thread_native.h new file mode 100644 index 000000000..272a59577 --- /dev/null +++ b/pw_thread_stl/public_overrides/pw_thread_backend/thread_native.h @@ -0,0 +1,16 @@ +// Copyright 2020 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_thread_stl/thread_native.h" diff --git a/pw_thread_stl/public_overrides/pw_thread_backend/yield_inline.h b/pw_thread_stl/public_overrides/pw_thread_backend/yield_inline.h new file mode 100644 index 000000000..61528f66b --- /dev/null +++ b/pw_thread_stl/public_overrides/pw_thread_backend/yield_inline.h @@ -0,0 +1,16 @@ +// Copyright 2020 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_thread_stl/yield_inline.h" diff --git a/pw_thread_stl/test_threads.cc b/pw_thread_stl/test_threads.cc new file mode 100644 index 000000000..64ab33e40 --- /dev/null +++ b/pw_thread_stl/test_threads.cc @@ -0,0 +1,40 @@ +// Copyright 2020 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. + +#include "pw_thread/test_threads.h" + +#include "pw_thread_stl/options.h" + +namespace pw::thread::test { + +// The STL doesn't offer any options so the default constructed options are used +// directly. + +const Options& TestOptionsThread0() { + static constexpr stl::Options thread_0_options; + return thread_0_options; +} + +const Options& TestOptionsThread1() { + static constexpr stl::Options thread_1_options; + return thread_1_options; +} + +// Thanks to the dynamic allocation, there's no need to wait here as there's +// no re-use of contexts. In addition we have a very large heap so we expect +// the risk to be minimal to non-existent for heap exhaustion to occur if this +// test is run back to back. +void WaitUntilDetachedThreadsCleanedUp() {} + +} // namespace pw::thread::test |