Skip to content

Commit

Permalink
Feature/appveyor (#21)
Browse files Browse the repository at this point in the history
* Add MS Visual Studio tests with Appveyor.

Co-authored-by: LCC <[email protected]>
  • Loading branch information
LouisCharlesC and LCC committed Mar 11, 2020
1 parent 4d95cf7 commit 2f24b6f
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 29 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ install:
- git clone https://github.com/onqtam/doctest.git
- mkdir doctest/build
- cd doctest/build
- cmake ..
- cmake -D DOCTEST_WITH_TESTS=OFF -D DOCTEST_WITH_MAIN_IN_STATIC_LIB=OFF -D CMAKE_BUILD_TYPE=Release ..
- sudo make -j2 install
- cd $TRAVIS_BUILD_DIR
- mkdir install
Expand All @@ -43,6 +43,6 @@ install:
script:
- mkdir build
- cd build
- cmake -D CMAKE_BUILD_TYPE=Release ../tests
- cmake -D CMAKE_BUILD_TYPE=Debug ../tests
- make -j2
- ./tests
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# *Every variable protected by a mutex should be wrapped with safe.*

[![Build Status](https://travis-ci.org/LouisCharlesC/safe.svg?branch=master)](https://travis-ci.org/LouisCharlesC/safe)
[![Build status](https://ci.appveyor.com/api/projects/status/9q4mvbg5y630x6kp/branch/master?svg=true)](https://ci.appveyor.com/project/LouisCharlesC/safe/branch/master)
## Contents
*safe* is a header-only library that makes code with mutexes safer and easier to understand.
This readme will walk you through the important features of the library using several code examples. Read on, and enjoy safe mutexes!
Expand Down Expand Up @@ -110,7 +111,7 @@ However, if all you need to do is assign a new value, then you might as well use
```c++
safeValue.assign(42);
```
Finally, to get a copy of the value object, call the copy function:
Finally, if a copy of the value object is all you need, call the copy function:
```c++
int value = safeValue.copy();
```
Expand Down Expand Up @@ -193,7 +194,7 @@ cv.wait(value.lock, [](){return true;});
```
## Advanced usage
### Enforcing read-only access
You can inform the *safe* library that some locks that you use are read-only (e.g. std::shared_lock, boost::shared_lock_guard). If you do so, trying to instantiate a WriteAccess object with these locks will trigger a compilation error. Use the trait class safe::LockTraits to customize this behavior.
You can inform the *safe* library that some locks that you use are read-only (e.g. std::shared_lock, boost::shared_lock_guard). If you do so, trying to instantiate a WriteAccess object with these locks will trigger a compilation error. Use the trait class safe::LockTraits to customize this behavior.

Here is how the trait works:
- If no specialization of the type trait exists for a lock type, the lock can be used with read-write and read-only Access objects.
Expand All @@ -203,11 +204,12 @@ Here is how the trait works:

As an example, here is how to specialize the trait for std::shared_lock (you will find this exact code snippet in safe/traits.h):
```c++
template<>
struct AccessTraits<std::shared_lock>
template<typename MutexType>
struct AccessTraits<std::shared_lock<MutexType>>
{
static constexpr bool IsReadOnly = true;
};
```
# Acknowledgment
Thanks to all contributors, issue raisers and stargazers!
Most cmake code comes from this repo: https://github.com/bsamseth/cpp-project and Craig Scott's CppCon 2019 talk: Deep CMake for Library Authors. Many thanks to the authors!
56 changes: 56 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
image:
- Visual Studio 2019
- Visual Studio 2017
- Visual Studio 2015
configuration:
- Debug
- Release
platform:
- x86
- x64
- ARM
- Any CPU
init:
- pwsh: >-
cmake --version
msbuild /version
install:
- pwsh: >-
git clone https://github.com/onqtam/doctest.git
cd doctest
mkdir build
cd build
cmake -D DOCTEST_WITH_TESTS=OFF -D DOCTEST_WITH_MAIN_IN_STATIC_LIB=OFF -D CMAKE_CONFIGURATION_TYPES=Release -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=$env:APPVEYOR_BUILD_FOLDER/../share ..
cmake --build . --config Release --target install
build_script:
- pwsh: >-
cd $env:APPVEYOR_BUILD_FOLDER
mkdir build
cd build
mkdir install
cd install
cmake -D CMAKE_CONFIGURATION_TYPES=$env:CONFIGURATION -D CMAKE_BUILD_TYPE=$env:CONFIGURATION -D CMAKE_INSTALL_PREFIX=$env:APPVEYOR_BUILD_FOLDER/../share ../..
cmake --build . --config $env:CONFIGURATION --target install
cd ..
cmake -D CMAKE_CONFIGURATION_TYPES=$env:CONFIGURATION -D CMAKE_BUILD_TYPE=$env:CONFIGURATION -D CMAKE_PREFIX_PATH=$env:APPVEYOR_BUILD_FOLDER/../share ../tests
cmake --build . --config $env:CONFIGURATION
test_script:
- cmd: >-
cd build
ctest --output-on-failure --timeout 10 -C %CONFIGURATION%
14 changes: 7 additions & 7 deletions include/safe/accessmode.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,24 @@ namespace safe
ReadWrite
};

template<template<typename> class LockType>
template<typename LockType>
struct AccessTraits
{
static constexpr bool IsReadOnly = false;
};
template<>
struct AccessTraits<std::lock_guard>
template<typename MutexType>
struct AccessTraits<std::lock_guard<MutexType>>
{
static constexpr bool IsReadOnly = false;
};
template<>
struct AccessTraits<std::unique_lock>
template<typename MutexType>
struct AccessTraits<std::unique_lock<MutexType>>
{
static constexpr bool IsReadOnly = false;
};
#if __cplusplus >= 201402L
template<>
struct AccessTraits<std::shared_lock>
template<typename MutexType>
struct AccessTraits<std::shared_lock<MutexType>>
{
static constexpr bool IsReadOnly = true;
};
Expand Down
5 changes: 4 additions & 1 deletion include/safe/safe.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ namespace safe
class Access
{
// Make sure AccessMode is ReadOnly if a read-only lock is used
static_assert(!(AccessTraits<LockType>::IsReadOnly && Mode==AccessMode::ReadWrite), "Cannot have ReadWrite access mode with ReadOnly lock. Check the value of AccessTraits<LockType>::IsReadOnly if it exists.");
static_assert(!(AccessTraits<LockType<RemoveRefMutexType>>::IsReadOnly && Mode==AccessMode::ReadWrite), "Cannot have ReadWrite access mode with ReadOnly lock. Check the value of AccessTraits<LockType>::IsReadOnly if it exists.");

/// ValueType with const qualifier if AccessMode is ReadOnly.
using ConstIfReadOnlyValueType = typename std::conditional<Mode==AccessMode::ReadOnly, const RemoveRefValueType, RemoveRefValueType>::type;
Expand Down Expand Up @@ -354,3 +354,6 @@ namespace safe
template<typename> class LockType=DefaultReadWriteLock>
using WriteAccess = typename SafeType::template WriteAccess<LockType>;
} // namespace safe

#undef EXPLICIT_IF_CPP17
#undef EXPLICITLY_CONSTRUCT_RETURN_TYPE_IF_CPP17
19 changes: 9 additions & 10 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,21 @@ include(CTest)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
include(Warnings)

find_package(safe 1.0 REQUIRED)
find_package(doctest REQUIRED)
find_package(safe CONFIG REQUIRED)
find_package(doctest CONFIG REQUIRED )

set(TEST_MAIN ${PROJECT_NAME})

find_package(Threads REQUIRED)
add_executable(${TEST_MAIN} test_main.cpp test_readme.cpp test_safe.cpp)
target_link_libraries(${TEST_MAIN} PUBLIC Threads::Threads)
target_link_libraries(${TEST_MAIN} PRIVATE safe::safe doctest::doctest Threads::Threads)
target_set_warnings(${TEST_MAIN} ENABLE ALL AS_ERROR ALL DISABLE Annoying)
add_executable(${PROJECT_NAME} test_main.cpp test_readme.cpp test_safe.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE safe::safe doctest::doctest)
target_set_warnings(${PROJECT_NAME} ENABLE ALL AS_ERROR ALL DISABLE Annoying)
set_target_properties(
${TEST_MAIN}
${PROJECT_NAME}
PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS NO
)

add_test(NAME safe.${PROJECT_NAME} COMMAND ${PROJECT_NAME} -s)

set(TEST_MAIN ${PROJECT_NAME})
# Adds a 'coverage' target to compile ${TEST_MAIN}.
include(CoverageTarget)
11 changes: 6 additions & 5 deletions tests/test_readme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,33 +153,34 @@ TEST_CASE("Readme flexibly construct lock")
{
safe::Safe<int> safeValue; // given a Safe object
safeValue.mutex().lock(); // with the mutex already locked...
CHECK_EQ(safeValue.mutex().try_lock(), false);
// Because the mutex is already locked, you need to pass the std::adopt_lock tag to std::lock_guard when you construct your Access object.

// Fortunately, arguments passed to WriteAccess's constructor are forwarded to the lock's constructor.
{
safe::WriteAccess<safe::Safe<int>> value(safeValue, std::adopt_lock);
CHECK_EQ(&*value, &safeValue.unsafe());
}
CHECK_EQ(safeValue.mutex().try_lock(), true);

safeValue.mutex().lock();
{
safe::Safe<int>::WriteAccess<> value(safeValue, std::adopt_lock);
CHECK_EQ(&*value, &safeValue.unsafe());
}
CHECK_EQ(safeValue.mutex().try_lock(), true);

#if __cplusplus >= 201703L
safeValue.mutex().lock();
{
auto value = safeValue.writeAccess(std::adopt_lock);
CHECK_EQ(&*value, &safeValue.unsafe());
}
CHECK_EQ(safeValue.mutex().try_lock(), true);
#endif

safeValue.mutex().lock();
{
auto value = safeValue.writeAccess<std::unique_lock>(std::adopt_lock);
CHECK_EQ(&*value, &safeValue.unsafe());
CHECK_EQ(value.lock.mutex(), &safeValue.mutex());
}
CHECK_EQ(safeValue.mutex().try_lock(), true);
}

TEST_CASE("Readme legacy")
Expand Down

0 comments on commit 2f24b6f

Please sign in to comment.