Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions cpp/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Build directories
build/
*/build/

# CMake
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
_deps

# Object files
*.o
*.a
*.so
*.dll
*.dylib

# IDE
.vscode/
.idea/
*.user
*.vcxproj
*.sln

# OS
.DS_Store
Thumbs.db
108 changes: 108 additions & 0 deletions cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
cmake_minimum_required(VERSION 3.15)

project(Platform.Threading
VERSION 1.0.0
DESCRIPTION "C++ translation of Platform.Threading library"
LANGUAGES CXX
)

# Set C++20 standard (required for std::jthread)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Compiler-specific options
if(MSVC)
add_compile_options(/W4 /permissive-)
# Enable std::jthread on MSVC
add_definitions(-D_WIN32_WINNT=0x0A00)
else()
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# Platform.Threading library
set(PLATFORM_THREADING_HEADERS
Platform.Threading/ThreadHelpers.h
Platform.Threading/TaskExtensions.h
Platform.Threading/ConcurrentQueueExtensions.h
Platform.Threading/Synchronization/ISynchronization.h
Platform.Threading/Synchronization/ReaderWriterLockSynchronization.h
Platform.Threading/Synchronization/Unsynchronization.h
Platform.Threading/Synchronization/ISynchronized.h
Platform.Threading/Synchronization/ISynchronizationExtensions.h
)

set(PLATFORM_THREADING_SOURCES
Platform.Threading/ThreadHelpers.cpp
)

add_library(Platform.Threading ${PLATFORM_THREADING_SOURCES} ${PLATFORM_THREADING_HEADERS})

target_include_directories(Platform.Threading
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)

# Find required packages
find_package(Threads REQUIRED)

# Link threading library
target_link_libraries(Platform.Threading PUBLIC Threads::Threads)

# Set properties
set_target_properties(Platform.Threading PROPERTIES
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN YES
VERSION ${PROJECT_VERSION}
SOVERSION 1
)

# Enable testing
enable_testing()

# Tests
if(BUILD_TESTING)
add_subdirectory(Platform.Threading.Tests)
endif()

# Install targets
install(TARGETS Platform.Threading
EXPORT Platform.ThreadingTargets
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)

# Install headers
install(DIRECTORY Platform.Threading/
DESTINATION include/Platform.Threading
FILES_MATCHING PATTERN "*.h"
)

# Create package config files
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"Platform.ThreadingConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion
)

install(EXPORT Platform.ThreadingTargets
FILE Platform.ThreadingTargets.cmake
NAMESPACE Platform::
DESTINATION lib/cmake/Platform.Threading
)

configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/Platform.ThreadingConfig.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/Platform.ThreadingConfig.cmake"
@ONLY
)

install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/Platform.ThreadingConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/Platform.ThreadingConfigVersion.cmake"
DESTINATION lib/cmake/Platform.Threading
)
36 changes: 36 additions & 0 deletions cpp/Platform.Threading.Tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Platform.Threading.Tests

# Find or download Google Test
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/03597a01ee50f33f9142fd2db5e2bc3d47f18e95.zip
)

# For Windows: Prevent overriding the parent project's compiler/linker settings
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(googletest)

# Test sources
set(TEST_SOURCES
ThreadHelpersTests.cpp
)

# Create test executable
add_executable(Platform.Threading.Tests ${TEST_SOURCES})

# Link libraries
target_link_libraries(Platform.Threading.Tests
Platform.Threading
gtest_main
gmock_main
)

# Include directories
target_include_directories(Platform.Threading.Tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/../
)

# Discover tests
include(GoogleTest)
gtest_discover_tests(Platform.Threading.Tests)
82 changes: 66 additions & 16 deletions cpp/Platform.Threading.Tests/ThreadHelpersTests.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,68 @@
ο»Ώnamespace Platform::Threading::Tests
#include <gtest/gtest.h>
#include <Platform.Threading/ThreadHelpers.h>
#include <atomic>

using namespace Platform::Threading;

class ThreadHelpersTests : public ::testing::Test
{
TEST_CLASS(ThreadHelpersTests)
{
public: TEST_METHOD(InvokeTest)
{
auto number = 0;
ThreadHelpers.InvokeWithExtendedMaxStackSize([&]()-> auto { return number = 1; });
Assert::AreEqual(1, number);
ThreadHelpers.InvokeWithExtendedMaxStackSize(2, param { return number = (std::int32_t)param); }
Assert::AreEqual(2, number);
ThreadHelpers.InvokeWithModifiedMaxStackSize([&]()-> auto { return number = 1; }, maxStackSize: 512);
Assert::AreEqual(1, number);
ThreadHelpers.InvokeWithModifiedMaxStackSize(2, param { return number = (std::int32_t)param, maxStackSize: 512); }
Assert::AreEqual(2, number);
}
};
protected:
void SetUp() override {}
void TearDown() override {}
};

TEST_F(ThreadHelpersTests, InvokeTest)
{
std::atomic<int> number{0};

// Test InvokeWithExtendedMaxStackSize with lambda
ThreadHelpers::InvokeWithExtendedMaxStackSize([&number]() {
number = 1;
});
EXPECT_EQ(1, number.load());

// Test InvokeWithExtendedMaxStackSize with parameter
ThreadHelpers::InvokeWithExtendedMaxStackSize(2, [&number](int param) {
number = param;
});
EXPECT_EQ(2, number.load());

// Test InvokeWithModifiedMaxStackSize with lambda
ThreadHelpers::InvokeWithModifiedMaxStackSize([&number]() {
number = 3;
}, 512);
EXPECT_EQ(3, number.load());

// Test InvokeWithModifiedMaxStackSize with parameter
ThreadHelpers::InvokeWithModifiedMaxStackSize(4, [&number](int param) {
number = param;
}, 512);
EXPECT_EQ(4, number.load());
}

TEST_F(ThreadHelpersTests, StartNewTest)
{
std::atomic<int> number{0};

// Test StartNew with lambda
auto thread1 = ThreadHelpers::StartNew([&number]() {
number = 10;
});
thread1.join();
EXPECT_EQ(10, number.load());

// Test StartNew with parameter
auto thread2 = ThreadHelpers::StartNew(20, [&number](int param) {
number = param;
});
thread2.join();
EXPECT_EQ(20, number.load());
}

TEST_F(ThreadHelpersTests, SleepTest)
{
// Test that Sleep doesn't crash
ThreadHelpers::Sleep();
// Test passes if no exception is thrown
SUCCEED();
}
Loading
Loading