瀏覽代碼

* Implemented locked type (used the get locked access to any resource)

* Moved files from 'threading' to 'synchronization'
master
bergmann 6 年之前
父節點
當前提交
fec33596d6
共有 8 個檔案被更改,包括 288 行新增2 行删除
  1. +1
    -1
      include/cppcore.h
  2. +1
    -0
      include/cppcore/synchronization.h
  3. +0
    -0
      include/cppcore/synchronization/cancellation_token.h
  4. +0
    -0
      include/cppcore/synchronization/cancellation_token.inl
  5. +125
    -0
      include/cppcore/synchronization/locked.h
  6. +123
    -0
      include/cppcore/synchronization/locked.inl
  7. +1
    -1
      test/cppcore/synchronization/cancellation_token_tests.cpp
  8. +37
    -0
      test/cppcore/synchronization/locked_tests.cpp

+ 1
- 1
include/cppcore.h 查看文件

@@ -4,4 +4,4 @@
#include "cppcore/defines.h"
#include "cppcore/misc.h"
#include "cppcore/platform.h"
#include "cppcore/threading.h"
#include "cppcore/synchronization.h"

include/cppcore/threading.h → include/cppcore/synchronization.h 查看文件

@@ -1,3 +1,4 @@
#pragma once

#include "threading/cancellation_token.h"
#include "threading/locked.h"

include/cppcore/threading/cancellation_token.h → include/cppcore/synchronization/cancellation_token.h 查看文件


include/cppcore/threading/cancellation_token.inl → include/cppcore/synchronization/cancellation_token.inl 查看文件


+ 125
- 0
include/cppcore/synchronization/locked.h 查看文件

@@ -0,0 +1,125 @@
#pragma once

#include <mutex>
#include <memory>
#include <chrono>

namespace cppcore
{

template<
typename T_value,
typename T_lock = std::mutex>
struct locked
{
public:
template<typename T_locked_value>
struct locked_ref;

using value_type = T_value;
using lock_type = T_lock;
using guard_type = std::unique_lock<lock_type>;
using locked_ref_type = locked_ref<value_type>;
using locked_ref_ptr_u = std::unique_ptr<locked_ref_type>;
using locked_const_ref_type = locked_ref<const value_type>;
using locked_const_ref_ptr_u = std::unique_ptr<const locked_ref_type>;

template<typename T_locked_value>
struct locked_ref
{
public:
using value_type = T_locked_value;
using reference_type = value_type&;
using pointer_type = value_type*;

private:
guard_type _guard;

public:
value_type& value;

public:
/**
* @brief Constructor.
*/
inline locked_ref(
guard_type&& p_guard,
value_type& p_value);

inline pointer_type operator->();
inline reference_type operator*();
};

private:
mutable lock_type _lock;
value_type _value;

public:
/**
* @brief Constructor.
*/
template<typename... X_args>
inline locked(X_args&&... p_args);

public:
/**
* @brief Lock the resource stored in this object and return the locked reference.
*/
inline locked_ref_type lock();

/**
* @brief Try to lock the resource stored in this object and return the locked reference.
*/
inline locked_ref_ptr_u try_lock();

/**
* @brief Try to lock the resource stored in this object and return the locked reference.
*/
template<typename X_value, typename X_ratio>
inline locked_ref_ptr_u try_lock_for(
const std::chrono::duration<X_value, X_ratio>& timeout);

/**
* @brief Try to lock the resource stored in this object and return the locked reference.
*/
template<typename X_clock, typename X_duration>
inline locked_ref_ptr_u try_lock_until(
const std::chrono::time_point<X_clock, X_duration>& timeout);

public:
/**
* @brief Lock the resource stored in this object and return the locked reference.
*/
inline locked_const_ref_type lock() const;

/**
* @brief Try to lock the resource stored in this object and return the locked reference.
*/
inline locked_const_ref_ptr_u try_lock() const;

/**
* @brief Try to lock the resource stored in this object and return the locked reference.
*/
template<typename X_value, typename X_ratio>
inline locked_const_ref_ptr_u try_lock_for(
const std::chrono::duration<X_value, X_ratio>& timeout) const;

/**
* @brief Try to lock the resource stored in this object and return the locked reference.
*/
template<typename X_clock, typename X_duration>
inline locked_const_ref_ptr_u try_lock_until(
const std::chrono::time_point<X_clock, X_duration>& timeout) const;
};

/**
* @brief Construct a locked object with the passed arguments.
*/
template<
typename T_value,
typename... X_args>
inline locked<T_value> make_locked(X_args&&... p_args);

}

#include "locked.inl"

+ 123
- 0
include/cppcore/synchronization/locked.inl 查看文件

@@ -0,0 +1,123 @@
#pragma once

#include "locked.h"

namespace cppcore
{
/* locked_ref */

template<typename T_value, typename T_lock>
template<typename T_locked_value>
locked<T_value, T_lock>::locked_ref<T_locked_value>::locked_ref(
guard_type&& p_guard,
value_type& p_value)
: _guard(std::move(p_guard))
, value (p_value)
{ }

template<typename T_value, typename T_lock>
template<typename T_locked_value>
typename locked<T_value, T_lock>::template locked_ref<T_locked_value>::pointer_type
locked<T_value, T_lock>::locked_ref<T_locked_value>::operator->()
{ return &value; }

template<typename T_value, typename T_lock>
template<typename T_locked_value>
typename locked<T_value, T_lock>::template locked_ref<T_locked_value>::reference_type
locked<T_value, T_lock>::locked_ref<T_locked_value>::operator*()
{ return value; }

/* locked */

template<typename T_value, typename T_lock>
template<typename... X_args>
locked<T_value, T_lock>::locked(X_args&&... p_args)
: _value(std::forward<X_args>(p_args)...)
{ }

template<typename T_value, typename T_lock>
typename locked<T_value, T_lock>::locked_ref_type
locked<T_value, T_lock>::lock()
{ return locked_ref_type(guard_type(_lock), _value); }

template<typename T_value, typename T_lock>
typename locked<T_value, T_lock>::locked_ref_ptr_u
locked<T_value, T_lock>::try_lock()
{
guard_type guard(_lock, std::defer_lock);
return guard.try_lock()
? std::make_unique<locked_ref_type>(std::move(guard), _value)
: nullptr;
}

template<typename T_value, typename T_lock>
template<typename X_value, typename X_ratio>
typename locked<T_value, T_lock>::locked_ref_ptr_u
locked<T_value, T_lock>::try_lock_for(
const std::chrono::duration<X_value, X_ratio>& timeout)
{
guard_type guard(_lock, std::defer_lock);
return guard.try_lock_for(timeout)
? std::make_unique<locked_ref_type>(std::move(guard), _value)
: nullptr;
}

template<typename T_value, typename T_lock>
template<typename X_clock, typename X_duration>
typename locked<T_value, T_lock>::locked_ref_ptr_u
locked<T_value, T_lock>::try_lock_until(
const std::chrono::time_point<X_clock, X_duration>& timeout)
{
guard_type guard(_lock, std::defer_lock);
return guard.try_lock_until(timeout)
? std::make_unique<locked_ref_type>(std::move(guard), _value)
: nullptr;
}

template<typename T_value, typename T_lock>
typename locked<T_value, T_lock>::locked_const_ref_type
locked<T_value, T_lock>::lock() const
{ return locked_const_ref_type(guard_type(_lock), _value); }

template<typename T_value, typename T_lock>
typename locked<T_value, T_lock>::locked_const_ref_ptr_u
locked<T_value, T_lock>::try_lock() const
{
guard_type guard(_lock, std::defer_lock);
return guard.try_lock()
? std::make_unique<locked_const_ref_type>(std::move(guard), _value)
: nullptr;
}

template<typename T_value, typename T_lock>
template<typename X_value, typename X_ratio>
typename locked<T_value, T_lock>::locked_const_ref_ptr_u
locked<T_value, T_lock>::try_lock_for(
const std::chrono::duration<X_value, X_ratio>& timeout) const
{
guard_type guard(_lock, std::defer_lock);
return guard.try_lock_for(timeout)
? std::make_unique<locked_const_ref_type>(std::move(guard), _value)
: nullptr;
}

template<typename T_value, typename T_lock>
template<typename X_clock, typename X_duration>
typename locked<T_value, T_lock>::locked_const_ref_ptr_u
locked<T_value, T_lock>::try_lock_until(
const std::chrono::time_point<X_clock, X_duration>& timeout) const
{
guard_type guard(_lock, std::defer_lock);
return guard.try_lock_until(timeout)
? std::make_unique<locked_const_ref_type>(std::move(guard), _value)
: nullptr;
}

/* misc */

template<
typename T_value,
typename... X_args>
locked<T_value> make_locked(X_args&&... p_args)
{ return locked<T_value>(std::forward<X_args>(p_args)...); }
}

test/cppcore/threading/cancellation_token_tests.cpp → test/cppcore/synchronization/cancellation_token_tests.cpp 查看文件

@@ -1,5 +1,5 @@
#include <gtest/gtest.h>
#include <cppcore/threading/cancellation_token.h>
#include <cppcore/synchronization/cancellation_token.h>

using namespace ::cppcore;


+ 37
- 0
test/cppcore/synchronization/locked_tests.cpp 查看文件

@@ -0,0 +1,37 @@
#include <gtest/gtest.h>
#include <cppcore/synchronization/locked.h>

using namespace ::cppcore;

TEST(locked_tests, simple)
{
auto l = make_locked<int>();

{
auto ref = l.lock();
*ref = 5;
}

{
auto ref = l.lock();
EXPECT_EQ(5, *ref);
}
}

TEST(locked_tests, try_lock)
{
auto l = make_locked<int>();

{
auto ref = l.lock();
*ref = 5;

EXPECT_FALSE(l.try_lock());
}

{
auto ref = l.try_lock();
ASSERT_TRUE(ref);
EXPECT_EQ (5, **ref);
}
}

Loading…
取消
儲存