Remove beast::SharedData

This commit is contained in:
Nik Bougalis
2015-10-10 19:34:59 -07:00
parent 206cd3b529
commit d4c4a03e42
5 changed files with 50 additions and 391 deletions

View File

@@ -24,7 +24,6 @@
#include <beast/threads/TryLockGuard.h>
#include <beast/threads/SharedLockGuard.h>
#include <beast/threads/SharedMutexAdapter.h>
#include <beast/threads/SharedData.h>
#include <beast/threads/SpinLock.h>
#include <beast/threads/Stoppable.h>
#include <beast/threads/Thread.h>

View File

@@ -20,13 +20,13 @@
#include <beast/asio/IPAddressConversion.h>
#include <beast/asio/placeholders.h>
#include <beast/intrusive/List.h>
#include <beast/threads/SharedData.h>
#include <boost/asio/ip/tcp.hpp>
#include <boost/optional.hpp>
#include <cassert>
#include <climits>
#include <deque>
#include <functional>
#include <mutex>
#include <set>
#include <sstream>
#include <thread>
@@ -192,13 +192,6 @@ private:
max_packet_size = 1472
};
struct StateType
{
List <StatsDMetricBase> metrics;
};
using State = SharedData <StateType>;
Journal m_journal;
IP::Endpoint m_address;
std::string m_prefix;
@@ -208,7 +201,8 @@ private:
boost::asio::deadline_timer m_timer;
boost::asio::ip::udp::socket m_socket;
std::deque <std::string> m_data;
State m_state;
std::recursive_mutex metricsLock_;
List <StatsDMetricBase> metrics_;
// Must come last for order of init
std::thread m_thread;
@@ -288,14 +282,14 @@ public:
void add (StatsDMetricBase& metric)
{
State::Access state (m_state);
state->metrics.push_back (metric);
std::lock_guard<std::recursive_mutex> _(metricsLock_);
metrics_.push_back (metric);
}
void remove (StatsDMetricBase& metric)
{
State::Access state (m_state);
state->metrics.erase (state->metrics.iterator_to (metric));
std::lock_guard<std::recursive_mutex> _(metricsLock_);
metrics_.erase (metrics_.iterator_to (metric));
}
//--------------------------------------------------------------------------
@@ -425,11 +419,10 @@ public:
return;
}
State::Access state (m_state);
std::lock_guard<std::recursive_mutex> _(metricsLock_);
for (List <StatsDMetricBase>::iterator iter (state->metrics.begin());
iter != state->metrics.end(); ++iter)
iter->do_process();
for (auto& m : metrics_)
m.do_process();
send_buffers ();

View File

@@ -1,287 +0,0 @@
//------------------------------------------------------------------------------
/*
This file is part of Beast: https://github.com/vinniefalco/Beast
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#ifndef BEAST_THREADS_SHAREDDATA_H_INCLUDED
#define BEAST_THREADS_SHAREDDATA_H_INCLUDED
#include <beast/threads/RecursiveMutex.h>
#include <beast/threads/SharedMutexAdapter.h>
namespace beast {
/** Structured, multi-threaded access to a shared state.
This container combines locking semantics with data access semantics to
create an alternative to the typical synchronization method of first
acquiring a lock and then accessing data members.
With this container, access to the underlying data is only possible after
first acquiring a lock. The steps of acquiring the lock and obtaining
a const or non-const reference to the data are combined into one
RAII style operation.
There are three types of access:
- Access
Provides access to the shared state via a non-const reference or pointer.
Access acquires a unique lock on the mutex associated with the
container.
- ConstAccess
Provides access to the shared state via a const reference or pointer.
ConstAccess acquires a shared lock on the mutex associated with the
container.
- ConstUnlockedAccess
Provides access to the shared state via a const reference or pointer.
No locking is performed. It is the callers responsibility to ensure that
the operation is synchronized. This can be useful for diagnostics or
assertions, or for when it is known that no other threads can access
the data.
- UnlockedAccess
Provides access to the shared state via a reference or pointer.
No locking is performed. It is the callers responsibility to ensure that
the operation is synchronized. This can be useful for diagnostics or
assertions, or for when it is known that no other threads can access
the data.
Usage example:
@code
struct State
{
int value1;
String value2;
};
using SharedState = SharedData <State>;
SharedState m_state;
void readExample ()
{
SharedState::ConstAccess state (m_state);
print (state->value1); // read access
print (state->value2); // read access
state->value1 = 42; // write disallowed: compile error
}
void writeExample ()
{
SharedState::Access state (m_state);
state->value2 = "Label"; // write access, allowed
}
@endcode
Requirements for Value:
Constructible
Destructible
Requirements for SharedMutexType:
X is SharedMutexType, a is an instance of X:
X a; DefaultConstructible
X::LockGuardType Names a type that implements the LockGuard concept.
X::SharedLockGuardType Names a type that implements the SharedLockGuard concept.
@tparam Value The type which the container holds.
@tparam SharedMutexType The type of shared mutex to use.
*/
template <typename Value, class SharedMutexType =
SharedMutexAdapter <RecursiveMutex> >
class SharedData
{
private:
using LockGuardType = typename SharedMutexType::LockGuardType;
using SharedLockGuardType = typename SharedMutexType::SharedLockGuardType;
public:
using ValueType = Value;
class Access;
class ConstAccess;
class UnlockedAccess;
class ConstUnlockedAccess;
/** Create a shared data container.
Up to 8 parameters can be specified in the constructor. These parameters
are forwarded to the corresponding constructor in Data. If no
constructor in Data matches the parameter list, a compile error is
generated.
*/
/** @{ */
SharedData () = default;
template <class T1>
explicit SharedData (T1 t1)
: m_value (t1) { }
template <class T1, class T2>
SharedData (T1 t1, T2 t2)
: m_value (t1, t2) { }
template <class T1, class T2, class T3>
SharedData (T1 t1, T2 t2, T3 t3)
: m_value (t1, t2, t3) { }
template <class T1, class T2, class T3, class T4>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4)
: m_value (t1, t2, t3, t4) { }
template <class T1, class T2, class T3, class T4, class T5>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
: m_value (t1, t2, t3, t4, t5) { }
template <class T1, class T2, class T3, class T4, class T5, class T6>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
: m_value (t1, t2, t3, t4, t5, t6) { }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7) : m_value (t1, t2, t3, t4, t5, t6, t7) { }
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
SharedData (T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
: m_value (t1, t2, t3, t4, t5, t6, t7, t8) { }
/** @} */
SharedData (SharedData const&) = delete;
SharedData& operator= (SharedData const&) = delete;
private:
Value m_value;
SharedMutexType m_mutex;
};
//------------------------------------------------------------------------------
/** Provides non-const access to the contents of a SharedData.
This acquires a unique lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::Access
{
public:
explicit Access (SharedData& state)
: m_state (state)
, m_lock (m_state.m_mutex)
{ }
Access (Access const&) = delete;
Access& operator= (Access const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
Data& get () { return m_state.m_value; }
Data& operator* () { return get (); }
Data* operator-> () { return &get (); }
private:
SharedData& m_state;
typename SharedData::LockGuardType m_lock;
};
//------------------------------------------------------------------------------
/** Provides const access to the contents of a SharedData.
This acquires a shared lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::ConstAccess
{
public:
/** Create a ConstAccess from the specified SharedData */
explicit ConstAccess (SharedData const volatile& state)
: m_state (const_cast <SharedData const&> (state))
, m_lock (m_state.m_mutex)
{ }
ConstAccess (ConstAccess const&) = delete;
ConstAccess& operator= (ConstAccess const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
private:
SharedData const& m_state;
typename SharedData::SharedLockGuardType m_lock;
};
//------------------------------------------------------------------------------
/** Provides const access to the contents of a SharedData.
This acquires a shared lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::ConstUnlockedAccess
{
public:
/** Create an UnlockedAccess from the specified SharedData */
explicit ConstUnlockedAccess (SharedData const volatile& state)
: m_state (const_cast <SharedData const&> (state))
{ }
ConstUnlockedAccess (ConstUnlockedAccess const&) = delete;
ConstUnlockedAccess& operator= (ConstUnlockedAccess const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
private:
SharedData const& m_state;
};
//------------------------------------------------------------------------------
/** Provides access to the contents of a SharedData.
This acquires a shared lock on the underlying mutex.
*/
template <class Data, class SharedMutexType>
class SharedData <Data, SharedMutexType>::UnlockedAccess
{
public:
/** Create an UnlockedAccess from the specified SharedData */
explicit UnlockedAccess (SharedData& state)
: m_state (state)
{ }
UnlockedAccess (UnlockedAccess const&) = delete;
UnlockedAccess& operator= (UnlockedAccess const&) = delete;
Data const& get () const { return m_state.m_value; }
Data const& operator* () const { return get (); }
Data const* operator-> () const { return &get (); }
Data& get () { return m_state.m_value; }
Data& operator* () { return get (); }
Data* operator-> () { return &get (); }
private:
SharedData& m_state;
};
}
#endif

View File

@@ -21,9 +21,9 @@
#define BEAST_UTILITY_PROPERTYSTREAM_H_INCLUDED
#include <beast/intrusive/List.h>
#include <beast/threads/SharedData.h>
#include <cstdint>
#include <mutex>
#include <sstream>
#include <string>
#include <utility>
@@ -274,31 +274,11 @@ public:
class PropertyStream::Source
{
private:
struct State
{
explicit State (Source* source)
: item (source)
, parent (nullptr)
{ }
Item item;
Source* parent;
List <Item> children;
};
using SharedState = SharedData <State>;
std::string const m_name;
SharedState m_state;
//--------------------------------------------------------------------------
void remove (SharedState::Access& state,
SharedState::Access& childState);
void removeAll (SharedState::Access& state);
void write (SharedState::Access& state, PropertyStream& stream);
std::recursive_mutex lock_;
Item item_;
Source* parent_;
List <Item> children_;
public:
explicit Source (std::string const& name);
@@ -326,7 +306,7 @@ public:
/** Remove a child source from this Source. */
void remove (Source& child);
/** Remove all child sources of this Source. */
/** Remove all child sources from this Source. */
void removeAll ();
/** Write only this Source to the stream. */

View File

@@ -173,16 +173,17 @@ PropertyStream const& PropertyStream::Set::stream() const
PropertyStream::Source::Source (std::string const& name)
: m_name (name)
, m_state (this)
, item_ (this)
, parent_ (nullptr)
{
}
PropertyStream::Source::~Source ()
{
SharedState::Access state (m_state);
if (state->parent != nullptr)
state->parent->remove (*this);
removeAll (state);
std::lock_guard<std::recursive_mutex> _(lock_);
if (parent_ != nullptr)
parent_->remove (*this);
removeAll ();
}
std::string const& PropertyStream::Source::name () const
@@ -192,37 +193,35 @@ std::string const& PropertyStream::Source::name () const
void PropertyStream::Source::add (Source& source)
{
SharedState::Access state (m_state);
SharedState::Access childState (source.m_state);
bassert (childState->parent == nullptr);
state->children.push_back (childState->item);
childState->parent = this;
std::lock(lock_, source.lock_);
std::lock_guard<std::recursive_mutex> lk1(lock_, std::adopt_lock);
std::lock_guard<std::recursive_mutex> lk2(source.lock_, std::adopt_lock);
bassert (source.parent_ == nullptr);
children_.push_back (source.item_);
source.parent_ = this;
}
void PropertyStream::Source::remove (Source& child)
{
SharedState::Access state (m_state);
SharedState::Access childState (child.m_state);
remove (state, childState);
std::lock(lock_, child.lock_);
std::lock_guard<std::recursive_mutex> lk1(lock_, std::adopt_lock);
std::lock_guard<std::recursive_mutex> lk2(child.lock_, std::adopt_lock);
bassert (child.parent_ == this);
children_.erase (
children_.iterator_to (
child.item_));
child.parent_ = nullptr;
}
void PropertyStream::Source::removeAll ()
{
SharedState::Access state (m_state);
removeAll (state);
}
//------------------------------------------------------------------------------
void PropertyStream::Source::write (
SharedState::Access& state, PropertyStream &stream)
{
for (List <Item>::iterator iter (state->children.begin());
iter != state->children.end(); ++iter)
std::lock_guard<std::recursive_mutex> _(lock_);
for (auto iter = children_.begin(); iter != children_.end(); )
{
Source& source (iter->source());
Map map (source.name(), stream);
source.write (stream);
std::lock_guard<std::recursive_mutex> _cl((*iter)->lock_);
remove (*(*iter));
}
}
@@ -239,14 +238,10 @@ void PropertyStream::Source::write (PropertyStream& stream)
Map map (m_name, stream);
onWrite (map);
SharedState::Access state (m_state);
std::lock_guard<std::recursive_mutex> _(lock_);
for (List <Item>::iterator iter (state->children.begin());
iter != state->children.end(); ++iter)
{
Source& source (iter->source());
source.write (stream);
}
for (auto& child : children_)
child.source().write (stream);
}
void PropertyStream::Source::write (PropertyStream& stream, std::string const& path)
@@ -330,8 +325,9 @@ PropertyStream::Source* PropertyStream::Source::find_one_deep (std::string const
Source* found = find_one (name);
if (found != nullptr)
return found;
SharedState::Access state (this->m_state);
for (auto& s : state->children)
std::lock_guard<std::recursive_mutex> _(lock_);
for (auto& s : children_)
{
found = s.source().find_one_deep (name);
if (found != nullptr)
@@ -360,8 +356,8 @@ PropertyStream::Source* PropertyStream::Source::find_path (std::string path)
// If no immediate children match, then return nullptr
PropertyStream::Source* PropertyStream::Source::find_one (std::string const& name)
{
SharedState::Access state (this->m_state);
for (auto& s : state->children)
std::lock_guard<std::recursive_mutex> _(lock_);
for (auto& s : children_)
{
if (s.source().m_name == name)
return &s.source();
@@ -373,28 +369,6 @@ void PropertyStream::Source::onWrite (Map&)
{
}
//------------------------------------------------------------------------------
void PropertyStream::Source::remove (
SharedState::Access& state, SharedState::Access& childState)
{
bassert (childState->parent == this);
state->children.erase (
state->children.iterator_to (
childState->item));
childState->parent = nullptr;
}
void PropertyStream::Source::removeAll (SharedState::Access& state)
{
for (List <Item>::iterator iter (state->children.begin());
iter != state->children.end();)
{
SharedState::Access childState ((*iter)->m_state);
remove (state, childState);
}
}
//------------------------------------------------------------------------------
//
// PropertyStream