Skip to content

Commit

Permalink
Merge pull request #41 from leapmotion/ref-simpleobjects
Browse files Browse the repository at this point in the history
Remove unused utilities
  • Loading branch information
gtremper committed Aug 8, 2014
2 parents 6134d94 + 4f8809c commit ac4307e
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 386 deletions.
33 changes: 17 additions & 16 deletions autowiring/AutoSelfUpdate.h
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
#pragma once
#include "NewAutoFilter.h"
#include "shared_object.h"
#include "atomic_object.h"

///<summary>
///Enables an automatic self-update when a packet is decorated with the object type.
///Provides the prior object (the last decorated instance) to all subsequent packets.
///</summary>
///<remarks>
///In order to ensure that this method will be consistent with any other AutoFilter calls,
///the object inherits from shared_object, which implements basic locking functionality.
///the object inherits from atomic_object, which implements basic locking functionality.
///</remarks>
template<class object, class lock = std::mutex>
template<class object_type, class lock_type = std::mutex>
class AutoSelfUpdate:
public shared_object<object, lock> {
protected:
using shared_object<object, lock>::get_lock;
using shared_object<object, lock>::get_object;

public atomic_object<object_type, lock_type> {
public:
typedef atomic_object<object_type, lock_type> atomic;
typedef typename atomic::object object;
typedef typename atomic::lock lock;
typedef typename atomic::unlock unlock;
typedef typename atomic::shared shared;

AutoSelfUpdate() {}
AutoSelfUpdate(const shared_object<object, lock>& source) : shared_object<object, lock>(source) {}
AutoSelfUpdate(const object& source) : shared_object<object, lock>(source) {}
using shared_object<object, lock>::operator =;
using shared_object<object, lock>::operator object;
AutoSelfUpdate(const atomic_object<object, lock>& source) : atomic_object<object, lock>(source) {}
AutoSelfUpdate(const object& source) : atomic_object<object, lock>(source) {}
using atomic_object<object, lock>::operator =;
using atomic_object<object, lock>::operator object;

//The distinct type assigned to the prior value of the object
class prior_object: public object {
Expand All @@ -33,8 +34,8 @@ public shared_object<object, lock> {

//Avoid intermediate copy by defining an explicit cast
operator prior_object() const {
std::lock_guard<lock> lock_this(get_lock());
return prior_object(get_object());
std::lock_guard<lock> lock_this(atomic_object<object, lock>::m_lock);
return prior_object(atomic_object<object, lock>::m_object);
}

//Decorates all packets with instances of prior_object
Expand All @@ -44,7 +45,7 @@ public shared_object<object, lock> {

//Updates this object
void AutoGather(const object& update) {
shared_object<object, lock>::operator = (update);
atomic_object<object, lock>::operator = (update);
}

NewAutoFilter<decltype(&AutoSelfUpdate<object>::AutoGather), &AutoSelfUpdate<object>::AutoGather> SelfUpdate;
Expand Down
121 changes: 16 additions & 105 deletions autowiring/atomic_object.h
Original file line number Diff line number Diff line change
@@ -1,38 +1,38 @@
// Copyright (C) 2012-2014 Leap Motion, Inc. All rights reserved.
// Copyright (c) 2010 - 2014 Leap Motion. All rights reserved. Proprietary and confidential.
#pragma once
#include MUTEX_HEADER

template<class object, class lock> class shared_object;
#include "unlock_object.h"
template<class object, class lock> class unlock_object;

///<summary>
///This class provides a standard thread-safe wrapper for data structures.
///Because instantiation may be separate from initialization, this class
///also tracks the initialization status.
///</summary>
///<remarks>
///This class supports two modes of use:
/// - Atomic assignments which can be used to create a mutable local copy,
/// or to modify the contents of shared_object.
/// - Held locks, via unlock_object, which will block all other interactions.
/// or to modify the contents of atomic_object.
/// - Held locks, via child classes that manipulate the protected lock member.
///</remarks>
template<class object, class lock = std::mutex>
template<class object_type, class lock_type = std::mutex>
class atomic_object {
friend class shared_object<object, lock>;
friend class unlock_object<object, lock>;
public:
friend class unlock_object<object_type, lock_type>;
typedef object_type object;
typedef lock_type lock;
typedef unlock_object<object, lock> unlock;
typedef std::shared_ptr<atomic_object<object, lock>> shared;

protected:
//CONTRACT: If !m_initialized then m_object == object();
mutable lock m_lock;
object m_object;
bool m_initialized;

public:
///<summary>
///Default constructor yielding initialized() == false.
///</summary>
atomic_object():
m_initialized(false) {};
atomic_object() {};

///<summary>
///Initialization yielding initialized() == source.initialized().
Expand All @@ -44,22 +44,21 @@ class atomic_object {
atomic_object(const atomic_object<object>& source) {
std::lock_guard<lock> lock_source(source.m_lock);
m_object = source.m_object;
m_initialized = source.m_initialized;
}

///<summary>
///Initialization yielding initialized() == true.
///</summary>
atomic_object(const object& source):
m_object(source),
m_initialized(true) {}
m_object(source)
{}

///<summary>
///Assignment yielding initialized() == source.initialized().
///</summary>
///<remarks>
///This method avoids deadlocks due to self-assignment, and intermediate
///copies due to implicit casting.
///This method avoids deadlocks due to self-assignment,
///and intermediate copies due to implicit casting.
///</remarks>
atomic_object<object, lock>& operator = (const atomic_object<object>& source) {
if (this == &source)
Expand All @@ -70,7 +69,6 @@ class atomic_object {
//could deadlock with its counterpart in source.
std::lock(m_lock, source.m_lock);
m_object = source.m_object;
m_initialized = source.m_initialized;
m_lock.unlock();
source.m_lock.unlock();
return *this;
Expand All @@ -81,7 +79,6 @@ class atomic_object {
///</summary>
atomic_object<object, lock>& operator = (const object& source) {
std::lock_guard<lock> lock_this(m_lock);
m_initialized = true;
m_object = source;
return *this;
}
Expand All @@ -93,90 +90,4 @@ class atomic_object {
std::lock_guard<lock> lock_this(m_lock);
return m_object;
}

///<summary>
///Reset using default constructor yielding initialized() == false.
///</summary>
///<return>True if the object was not assigned default values</return>
bool reset() {
std::lock_guard<lock> lock_this(m_lock);
bool was_initialized = m_initialized;
m_initialized = false;
m_object = object();
return was_initialized;
}

///<summary>
///Atomic copy of target to this object, only if initialized() == false.
///</summary>
///<return>True if the object was not assigned default values</return>
bool reset(const object& target) {
std::lock_guard<lock> lock_this(m_lock);
bool was_initialized = m_initialized;
if (!m_initialized)
m_object = target;
m_initialized = true;
return was_initialized;
}

///<return>True if the object was not assigned default values</return>
bool initialized() const {
std::lock_guard<lock> lock_this(m_lock);
return m_initialized;
}

///<summary>
///Atomic copy of this object to target, only if initialized() == true.
///</summary>
///<return>True if the object was not assigned default values</return>
bool initialized(object& target) const {
std::lock_guard<lock> lock_this(m_lock);
if (m_initialized)
target = m_object;
return m_initialized;
}

///<summary>
///If uninitialized uses target for initialization.
///If initialized assigns current value to target.
///</summary>
///<returns> Returns +1 for transfer from target to this, -1 for transfer from this to target</returns>
int transfer(object& target) {
std::lock_guard<lock> lock_this(m_lock);
int val = 0;
if (m_initialized) {
target = m_object;
val = +1;
} else {
m_object = target;
m_initialized = true;
val = -1;
}
return val;
}

///<summary>
///If neither this nor target are uninitialized, no transfer occurs.
///If this is uninitialized and target is not, then this is initialized by target.
///If target is uninitialized and this is, then target is initialized by this.
///If both this and target are initialized, no transfer occurs.
///</summary>
///<returns> Returns +1 for transfer from target to this, -1 for transfer from this to target, else 0</returns>
int transfer(atomic_object<object, lock>& target) {
std::lock(m_lock, target.m_lock);
int val = 0;
if (m_initialized && !target.m_initialized) {
target.m_object = m_object;
target.m_initialized = true;
val = -1;
}
if (!m_initialized && target.m_initialized) {
m_object = target.m_object;
m_initialized = true;
val = +1;
}
m_lock.unlock();
target.m_lock.unlock();
return val;
}
};
Loading

0 comments on commit ac4307e

Please sign in to comment.