Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a configuration concept to Autowiring #858

Merged
merged 15 commits into from
Mar 2, 2016
Merged
Empty file.
Empty file added contrib/json11/stdafx.h
Empty file.
9 changes: 9 additions & 0 deletions src/autowiring/AnySharedPointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ class AnySharedPointerT:
AnySharedPointer(std::shared_ptr<T>{})
{}

AnySharedPointerT(T&& value) :
AnySharedPointer(std::make_shared<T>(std::forward<T&&>(value)))
{}

template<typename U>
AnySharedPointerT(U&& value) :
AnySharedPointer(std::make_shared<T>(std::forward<U&&>(value)))
{}

T& operator*(void) { return *as<T>(); }
const T& operator*(void) const { return *as<T>(); }

Expand Down
2 changes: 1 addition & 1 deletion src/autowiring/Autowired.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ class Autowired:
};

template<typename U, typename... Args>
signal_relay<U,Args...> operator()(autowiring::signal<void(Args...)> U::*sig) {
signal_relay<U, Args...> operator()(autowiring::signal<void(Args...)> U::*sig) {
static_assert(std::is_base_of<U, T>::value, "Cannot reference member of unrelated type");
return signal_relay<U, Args... >(*this, sig);
}
Expand Down
11 changes: 11 additions & 0 deletions src/autowiring/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ set(Autowiring_SRCS
callable.h
CallExtractor.h
CallExtractor.cpp
config.h
config_descriptor.h
config_descriptor.cpp
ConfigManager.h
ConfigManager.cpp
ConfigRegistry.h
ConfigRegistry.cpp
ContextEnumerator.cpp
ContextEnumerator.h
ContextMap.h
Expand Down Expand Up @@ -104,6 +111,7 @@ set(Autowiring_SRCS
hash_tuple.h
has_autofilter.h
has_autoinit.h
has_getconfigdescriptor.h
has_simple_constructor.h
has_static_new.h
has_validate.h
Expand All @@ -116,6 +124,7 @@ set(Autowiring_SRCS
is_shared_ptr.h
ManualThreadPool.h
ManualThreadPool.cpp
marshaller.h
member_new_type.h
MemoEntry.h
MemoEntry.cpp
Expand All @@ -127,8 +136,10 @@ set(Autowiring_SRCS
ObjectPool.h
ObjectPoolMonitor.cpp
ObjectPoolMonitor.h
observable.h
once.h
once.cpp
optional.h
Parallel.h
Parallel.cpp
registration.h
Expand Down
51 changes: 51 additions & 0 deletions src/autowiring/ConfigManager.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "ConfigManager.h"
#include <mutex>

using namespace autowiring;

ConfigManager::ConfigManager(void) :
m_empty("")
{}

void ConfigManager::Register(void* pObj, const config_descriptor& desc) {
std::lock_guard<autowiring::spin_lock> lk(m_lock);
for (const auto& field : desc.fields) {
Entry& entry = m_config[field.second.name];
entry.attached.push_back({
&field.second,
static_cast<uint8_t*>(pObj) + field.second.offset
});

if (entry.value)
entry.attached.back().field->marshaller->unmarshal(
entry.attached.back().pObj,
entry.value->c_str()
);
}
}

const std::string& ConfigManager::Get(std::string name) const {
auto q = m_config.find(name);
if (q == m_config.end())
return m_empty;

return *q->second.value;
}

void ConfigManager::Set(std::string&& name, std::string&& value) {
std::lock_guard<autowiring::spin_lock> lk(m_lock);
auto q = m_config.find(name);
if (q == m_config.end())
q = m_config.insert(q, { std::move(name), {} });

Entry& entry = q->second;
entry.value = std::move(value);

for (Entry::Attachment& attachment : entry.attached)
attachment.field->marshaller->unmarshal(
attachment.pObj,
entry.value->c_str()
);
}
57 changes: 57 additions & 0 deletions src/autowiring/ConfigManager.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#pragma once
#include "config_descriptor.h"
#include "optional.h"
#include "spin_lock.h"
#include <string>
#include <unordered_map>
#include <vector>

namespace autowiring {
class ConfigManager {
public:
ConfigManager(void);

private:
spin_lock m_lock;

// A single entry, which has a string representation part paired
// with a pointer to the value part
struct Entry {
// The value held here
optional<std::string> value;

struct Attachment {
const config_field* field;
void* pObj;
};

// Fields attached on this entry:
std::vector<Attachment> attached;
};

// Empty string sentry, used when a miss occurs
const std::string m_empty;

// All configuration values
std::unordered_map<std::string, Entry> m_config;

public:
/// <summary>
/// Registers a new configurable object
/// </summary>
/// <param name="pObj">The object that may be configured</param>
/// <param name="desc">A descriptor for the object</param>
void Register(void* pObj, const config_descriptor& desc);

/// <summary>
/// Gets the current configuration value from the map
/// </summary>
const std::string& Get(std::string name) const;

/// <summary>
/// Sets the named config value in the map
/// </summary>
void Set(std::string&& name, std::string&& value);
};
}
11 changes: 11 additions & 0 deletions src/autowiring/ConfigRegistry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#include "stdafx.h"
#include "ConfigRegistry.h"

using namespace autowiring;

std::atomic<config_registry_entry_base*> autowiring::g_pFirstEntry;

config_registry_entry_base::config_registry_entry_base(void) {
while (!g_pFirstEntry.compare_exchange_weak(pFlink, this));
}
64 changes: 64 additions & 0 deletions src/autowiring/ConfigRegistry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#pragma once
#include "config_descriptor.h"
#include <atomic>

namespace autowiring {
struct config_registry_entry_base {
protected:
config_registry_entry_base(void);

public:
// Next entry in the registry:
config_registry_entry_base* pFlink = nullptr;
};

template<typename T, typename = void>
struct config_registry_entry {
static const config_descriptor* desc(void) { return nullptr; }
};

template<typename T>
struct config_registry_entry<T, typename std::enable_if<has_getconfigdescriptor<T>::value>::type> :
config_registry_entry_base
{
public:
static const config_descriptor* desc(void) {
static const config_descriptor desc = T::GetConfigDescriptor();
return &desc;
}
};

extern std::atomic<config_registry_entry_base*> g_pFirstEntry;

/// <summary>
/// Gets a string representation of the named configuration value
/// </summary>
template<typename T>
std::string ConfigGet(const char* name, T& obj) {
const config_descriptor& desc = *config_registry_entry<T>::desc();
auto q = desc.fields.find(name);
if (q == desc.fields.end())
throw std::invalid_argument("Configuration name not found in the specified object's configuration descriptor");

const autowiring::config_field& f = q->second;
return f.marshaller->marshal(reinterpret_cast<uint8_t*>(&obj) + f.offset);
}

/// <summary>
/// Sets the named configuration value to the specified string value
/// </summary>
template<typename T>
void ConfigSet(const char* name, T& obj, const char* value) {
const config_descriptor& desc = *config_registry_entry<T>::desc();
auto q = desc.fields.find(name);
if (q == desc.fields.end())
throw std::invalid_argument("Configuration name not found in the specified object's configuration descriptor");

const autowiring::config_field& f = q->second;
f.marshaller->unmarshal(
reinterpret_cast<uint8_t*>(&obj) + f.offset,
value
);
}
}
15 changes: 13 additions & 2 deletions src/autowiring/CoreContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Bolt.h"
#include "CallExtractor.h"
#include "CoreRunnable.h"
#include "ConfigManager.h"
#include "ContextMember.h"
#include "CoreContextStateBlock.h"
#include "CoreObjectDescriptor.h"
Expand Down Expand Up @@ -133,6 +134,9 @@ class CoreContext:
// Asserted any time a new object is added to the context
autowiring::signal<void(const CoreObjectDescriptor&)> newObject;

// The one and only configuration manager type
autowiring::ConfigManager Config;

virtual ~CoreContext(void);

/// <summary>
Expand Down Expand Up @@ -235,7 +239,7 @@ class CoreContext:
typedef std::shared_ptr<CoreContext> (*t_pfnCreate)(
std::shared_ptr<CoreContext> pParent,
t_childList::iterator backReference
);
);

/// \internal
/// <summary>
Expand Down Expand Up @@ -606,13 +610,20 @@ class CoreContext:
std::shared_ptr<typename CreationRules::TActual> retVal(
CreationRules::New(*this, std::forward<Args>(args)...)
);
CoreObjectDescriptor objDesc(retVal, (T*)nullptr);

// Configure if the object is configurable, use a static check rather than checking the
// value of pConfigDesc because it's a little faster and one necessarily follows the other
// We also want this to happen before the AutoInit call is made
if(autowiring::has_getconfigdescriptor<T>::value)
Config.Register(static_cast<T*>(retVal.get()), *objDesc.pConfigDesc);

// AutoInit if sensible to do so:
CallAutoInit(*retVal, has_autoinit<T>());

try {
// Pass control to the insertion routine, which will handle injection from this point:
AddInternal(CoreObjectDescriptor(retVal, (T*)nullptr));
AddInternal(objDesc);
}
catch(autowiring_error&) {
// We know why this exception occurred. It's because, while we were constructing our
Expand Down
5 changes: 5 additions & 0 deletions src/autowiring/CoreObjectDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "auto_id.h"
#include "AutoFilterDescriptor.h"
#include "BoltBase.h"
#include "ConfigRegistry.h"
#include "ContextMember.h"
#include "CoreObject.h"
#include "CoreRunnable.h"
Expand Down Expand Up @@ -49,6 +50,7 @@ struct CoreObjectDescriptor {
pBasicThread(autowiring::fast_pointer_cast<BasicThread>(value)),
pFilter(autowiring::fast_pointer_cast<ExceptionFilter>(value)),
pBoltBase(autowiring::fast_pointer_cast<BoltBase>(value)),
pConfigDesc(autowiring::config_registry_entry<T>::desc()),
primitiveOffset(
reinterpret_cast<size_t>(
static_cast<T*>(
Expand Down Expand Up @@ -123,6 +125,9 @@ struct CoreObjectDescriptor {
std::shared_ptr<ExceptionFilter> pFilter;
std::shared_ptr<BoltBase> pBoltBase;

// Configuration descriptor, if the object provides one
const autowiring::config_descriptor* pConfigDesc;

// Distance from TActual to T
size_t primitiveOffset;
};
3 changes: 0 additions & 3 deletions src/autowiring/Decompose.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
// Copyright (C) 2012-2015 Leap Motion, Inc. All rights reserved.
#pragma once
#include "is_any.h"
#include <tuple>
#include <typeinfo>

template<class... Ts>
struct TemplatePack {
static const int N = sizeof...(Ts);

typedef std::tuple<Ts...> t_args;

/// <returns>
/// An array of type T, parameterized by the bound function's arguments
/// </returns>
Expand Down
9 changes: 4 additions & 5 deletions src/autowiring/DecorationDisposition.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,24 @@
#include <cassert>
#include <set>
#include <vector>
#include TYPE_INDEX_HEADER

struct SatCounter;

struct DecorationKey {
DecorationKey(void) = default;

explicit DecorationKey(auto_id id, int tshift) :
id(id),
tshift(tshift)
{}

// The type index
auto_id id;

// Zero refers to a decoration created on this packet, a positive number [tshift] indicates
// a decoration attached [tshift] packets ago.
int tshift = -1;

bool operator==(const DecorationKey& rhs) const {
return id == rhs.id && tshift == rhs.tshift;
}
Expand Down Expand Up @@ -126,7 +125,7 @@ struct DecorationDisposition

// The current state of this disposition
DispositionState m_state = DispositionState::Unsatisfied;

/// <returns>
/// True if all publishers have run on this disposition
/// </summary>
Expand Down
1 change: 0 additions & 1 deletion src/autowiring/DispatchQueue.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#include "DispatchThunk.h"
#include "once.h"
#include <atomic>
#include <list>
#include <queue>
#include MUTEX_HEADER
#include RVALUE_HEADER
Expand Down
1 change: 0 additions & 1 deletion src/autowiring/Parallel.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "DispatchQueue.h"
#include <iterator>
#include <unordered_map>
#include <typeindex>
#include <deque>

class CoreContext;
Expand Down
Loading