From 2539ec16100fe0e4370cbb17f2867ee1a38519f1 Mon Sep 17 00:00:00 2001 From: Timothy Hutchins Date: Wed, 2 Aug 2023 18:24:19 -0500 Subject: [PATCH] Implemented some more Linux equivalents --- .../linux/count_down_latch_test.cc | 161 ++++++++++++++++++ .../platform/implementation/linux/future.h | 48 ++++++ .../implementation/linux/log_message.cc | 71 ++++++++ .../implementation/linux/log_message.h | 43 +++++ .../implementation/linux/thread_pool.cc | 2 +- 5 files changed, 324 insertions(+), 1 deletion(-) create mode 100644 internal/platform/implementation/linux/count_down_latch_test.cc create mode 100644 internal/platform/implementation/linux/future.h create mode 100644 internal/platform/implementation/linux/log_message.cc create mode 100644 internal/platform/implementation/linux/log_message.h diff --git a/internal/platform/implementation/linux/count_down_latch_test.cc b/internal/platform/implementation/linux/count_down_latch_test.cc new file mode 100644 index 00000000..6f4caccd --- /dev/null +++ b/internal/platform/implementation/linux/count_down_latch_test.cc @@ -0,0 +1,161 @@ +// Copyright 2020 Google LLC +// +// 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 "internal/platform/implementation/shared/count_down_latch.h" + +#include "gtest/gtest.h" +#include "internal/platform/implementation/platform.h" + +#include +#include +#include + +class CountDownLatchTests : public testing::Test { + public: + class TestData { + public: + std::unique_ptr& countDownLatch; + long volatile& count; + }; + + class CountDownLatchTest { + public: + static unsigned int ThreadProcCountDown(void *lpParam) { + TestData* testData = static_cast(lpParam); + + sleep(1); + + __sync_fetch_and_add(&testData->count, 1); + + testData->countDownLatch->CountDown(); + return 0; + } + + static unsigned int ThreadProcAwait(void *lpParam) { + TestData* testData = static_cast(lpParam); + + sleep(1); + + testData->countDownLatch->Await(); + __sync_fetch_and_add(&testData->count, 1); + + return 0; + } + }; + + CountDownLatchTests() {} +}; + +TEST_F(CountDownLatchTests, CountDownLatchAwaitSucceeds) { + // Arrange + long volatile count = 0; + + std::unique_ptr countDownLatch = + nearby::api::ImplementationPlatform::CreateCountDownLatch(3); + + std::vector threads; + + TestData testData{countDownLatch, count}; + + // Setup 3 threads + for (int i = 0; i < 3; i++) { + // TODO: More complex scenarios may require use of a parameter + // to the thread procedure, such as an event per thread to + // be used for synchronization. + // https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread + // Could use C++ concurrency for this possibly + threads.emplace_back(CountDownLatchTest::ThreadProcCountDown, &testData); + } + + // Act + nearby::Exception result = countDownLatch->Await(); + + // Assert + EXPECT_EQ(result.value, nearby::Exception::kSuccess); + EXPECT_EQ(count, 3); +} + +TEST_F(CountDownLatchTests, CountDownLatchAwaitTimeoutTimesOut) { + // Arrange + + std::unique_ptr countDownLatch = + nearby::api::ImplementationPlatform::CreateCountDownLatch(3); + + // Act + nearby::ExceptionOr result = + countDownLatch->Await(absl::Milliseconds(5)); + + sleep(40); + + // Assert + EXPECT_FALSE(result.GetResult()); + // TODO(jfcarroll)I think there's a bug in the shared version of this, it's + // not returning a timeout exception, need to look at it some more. + // EXPECT_EQ(result.GetException().value, + // nearby::Exception::kTimeout); +} + +TEST_F(CountDownLatchTests, CountDownLatchAwaitNoTimeoutSucceeds) { + // Arrange + long volatile count = 0; + + std::unique_ptr countDownLatch = + nearby::api::ImplementationPlatform::CreateCountDownLatch(3); + + TestData testData{countDownLatch, count}; + + std::vector threads; + + // Setup 3 threads + for (int i = 0; i < 3; i++) { + // TODO: More complex scenarios may require use of a parameter + // to the thread procedure, such as an event per thread to + // be used for synchronization. + threads.emplace_back(CountDownLatchTest::ThreadProcAwait, &testData); + } + + for (auto &thread : threads) { + thread.join(); + } + // Act + nearby::ExceptionOr result = + countDownLatch->Await(absl::Milliseconds(100)); + + // Assert + EXPECT_TRUE(result.GetResult()); + EXPECT_EQ(result.GetException().value, nearby::Exception::kSuccess); + EXPECT_EQ(count, 3); +} + +void test(std::string str) { + std::cout << str << std::endl; + return; +} + +TEST_F(CountDownLatchTests, CountDownLatchCountDownBeforeAwaitSucceeds) { + // Arrange + long volatile count = 0; + std::unique_ptr countDownLatch = + nearby::api::ImplementationPlatform::CreateCountDownLatch(1); + + TestData testData{countDownLatch, count}; + std::thread thread(CountDownLatchTest::ThreadProcCountDown, &testData); + + // Act + countDownLatch->CountDown(); // This countdown occurs before the thread has a + // chance to run + // Assert + EXPECT_EQ(count, 1); +} + diff --git a/internal/platform/implementation/linux/future.h b/internal/platform/implementation/linux/future.h new file mode 100644 index 00000000..2f0bcab9 --- /dev/null +++ b/internal/platform/implementation/linux/future.h @@ -0,0 +1,48 @@ +// Copyright 2020 Google LLC +// +// 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. + +#ifndef PLATFORM_IMPL_LINUX_FUTURE_H_ +#define PLATFORM_IMPL_LINUX_FUTURE_H_ + +#include "internal/platform/implementation/future.h" + +namespace nearby { +namespace linux { + +// A Future represents the result of an asynchronous computation. +// +// https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html +template +class Future : public api::Future { + public: + // TODO(b/184975123): replace with real implementation. + ~Future() override = default; + + // throws Exception::kInterrupted, Exception::kExecution + // TODO(b/184975123): replace with real implementation. + ExceptionOr Get() override { return ExceptionOr{Exception::kFailed}; } + + // throws Exception::kInterrupted, Exception::kExecution + // throws Exception::kTimeout if timeout is exceeded while waiting for + // result. + // TODO(b/184975123): replace with real implementation. + ExceptionOr Get(absl::Duration timeout) override { + return ExceptionOr{Exception::kFailed}; + } +}; + +} // namespace linux +} // namespace nearby + +#endif // PLATFORM_IMPL_LINUX_FUTURE_H_ diff --git a/internal/platform/implementation/linux/log_message.cc b/internal/platform/implementation/linux/log_message.cc new file mode 100644 index 00000000..53d16a47 --- /dev/null +++ b/internal/platform/implementation/linux/log_message.cc @@ -0,0 +1,71 @@ +// Copyright 2020 Google LLC +// +// 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 "internal/platform/implementation/linux/log_message.h" + +#include + +#include "strings/strappendv.h" + +namespace nearby { +namespace linux { + +api::LogMessage::Severity min_log_severity_ = api::LogMessage::Severity::kInfo; + +inline absl::LogSeverity ConvertSeverity(api::LogMessage::Severity severity) { + switch (severity) { + // api::LogMessage::Severity kVerbose and kInfo is mapped to + // absl::LogSeverity kInfo since absl::LogSeverity doesn't have kVerbose + // level. + case api::LogMessage::Severity::kVerbose: + case api::LogMessage::Severity::kInfo: + return absl::LogSeverity::kInfo; + case api::LogMessage::Severity::kWarning: + return absl::LogSeverity::kWarning; + case api::LogMessage::Severity::kError: + return absl::LogSeverity::kError; + case api::LogMessage::Severity::kFatal: + return absl::LogSeverity::kFatal; + } +} + +LogMessage::LogMessage(const char* file, int line, Severity severity) + : log_streamer_(ConvertSeverity(severity), file, line) {} + +LogMessage::~LogMessage() = default; + +void LogMessage::Print(const char* format, ...) { + va_list ap; + va_start(ap, format); + std::string result; + strings::StrAppendV(&result, format, ap); + log_streamer_.stream() << result; + va_end(ap); +} + +std::ostream& LogMessage::Stream() { return log_streamer_.stream(); } + +} // namespace linux + +namespace api { + +void LogMessage::SetMinLogSeverity(Severity severity) { + windows::min_log_severity_ = severity; +} + +bool LogMessage::ShouldCreateLogMessage(Severity severity) { + return severity >= windows::min_log_severity_; +} +} // namespace api +} // namespace nearby diff --git a/internal/platform/implementation/linux/log_message.h b/internal/platform/implementation/linux/log_message.h new file mode 100644 index 00000000..bd06ab79 --- /dev/null +++ b/internal/platform/implementation/linux/log_message.h @@ -0,0 +1,43 @@ +// Copyright 2020 Google LLC +// +// 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. + +#ifndef PLATFORM_IMPL_LINUX_LOG_MESSAGE_H_ +#define PLATFORM_IMPL_LINUX_LOG_MESSAGE_H_ + +#include "glog/logging.h" +#include "internal/platform/implementation/log_message.h" + +namespace nearby { +namespace linux { + +// See documentation in +// cpp/platform/api/log_message.h +class LogMessage : public api::LogMessage { + public: + LogMessage(const char* file, int line, Severity severity); + ~LogMessage() override; + + void Print(const char* format, ...) override; + + std::ostream& Stream() override; + + private: + google::LogMessage log_streamer_; + static api::LogMessage::Severity min_log_severity_; +}; + +} // namespace linux +} // namespace nearby + +#endif // PLATFORM_IMPL_LINUX_LOG_MESSAGE_H_ diff --git a/internal/platform/implementation/linux/thread_pool.cc b/internal/platform/implementation/linux/thread_pool.cc index 40dec614..2eb1fa12 100644 --- a/internal/platform/implementation/linux/thread_pool.cc +++ b/internal/platform/implementation/linux/thread_pool.cc @@ -56,7 +56,7 @@ ThreadPool::ThreadPool(std::unique_ptr> &thread_pool, i RunNextTask(); // Possibly don't need but here to prevent 100% usage for loop sleep(300); - } + } }); } }