#include <RequestHandler.h>
#include <AssertUtils.h>
+#include <AtomicHelper.h>
#include <ResourceAttributesConverter.h>
#include <logger.h>
return OC_EH_ERROR;
}
- ResourceAttributes getAttributesFromOCRequest(std::shared_ptr< OC::OCResourceRequest > request)
+ RCSResourceAttributes getAttributesFromOCRequest(
+ std::shared_ptr< OC::OCResourceRequest > request)
{
return ResourceAttributesConverter::fromOCRepresentation(
request->getResourceRepresentation());
}
- template< typename HANDLER, typename RESPONSE = typename std::decay<HANDLER>::type::result_type >
- RESPONSE invokeHandler(ResourceAttributes& attrs,
+ template< typename HANDLER, typename RESPONSE =
+ typename std::decay<HANDLER>::type::result_type >
+ RESPONSE invokeHandler(RCSResourceAttributes& attrs,
std::shared_ptr< OC::OCResourceRequest > ocRequest, HANDLER&& handler)
{
if (handler)
return RESPONSE::defaultAction();
}
- typedef void (RCSResourceObject::* AutoNotifyFunc)(bool, RCSResourceObject::AutoNotifyPolicy) const;
+ typedef void (RCSResourceObject::* AutoNotifyFunc)
+ (bool, RCSResourceObject::AutoNotifyPolicy) const;
std::function <void ()> createAutoNotifyInvoker(AutoNotifyFunc autoNotifyFunc,
- const RCSResourceObject& resourceObject, const ResourceAttributes& resourceAttributes,
+ const RCSResourceObject& resourceObject, const RCSResourceAttributes& resourceAttributes,
RCSResourceObject::AutoNotifyPolicy autoNotifyPolicy)
{
if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::UPDATED)
{
auto&& compareAttributesFunc =
- std::bind(std::not_equal_to<ResourceAttributes>(),
+ std::bind(std::not_equal_to<RCSResourceAttributes>(),
resourceAttributes,
std::cref(resourceAttributes));
return std::bind(autoNotifyFunc,
}
RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
- const ResourceAttributes& attrs)
+ const RCSResourceAttributes& attrs)
{
m_resourceAttributes = attrs;
return *this;
}
RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
- ResourceAttributes&& attrs)
+ RCSResourceAttributes&& attrs)
{
m_resourceAttributes = std::move(attrs);
return *this;
OC::EntityHandler entityHandler{ std::bind(&RCSResourceObject::entityHandler,
server.get(), std::placeholders::_1) };
- try
- {
- typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&,
- const std::string&, const std::string&, OC::EntityHandler, uint8_t);
+ typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&,
+ const std::string&, const std::string&, OC::EntityHandler, uint8_t);
- invokeOCFunc(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
- handle, m_uri, m_type, m_interface, entityHandler, m_properties);
- }
- catch (OC::OCException& e)
- {
- throw PlatformException(e.code());
- }
+ invokeOCFunc(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
+ handle, m_uri, m_type, m_interface, entityHandler, m_properties);
server->m_resourceHandle = handle;
}
- RCSResourceObject::RCSResourceObject(uint8_t properties, ResourceAttributes&& attrs) :
+ RCSResourceObject::RCSResourceObject(uint8_t properties, RCSResourceAttributes&& attrs) :
m_properties { properties },
m_resourceHandle{ },
m_resourceAttributes{ std::move(attrs) },
m_mutex{ },
m_mutexKeyAttributeUpdate{ }
{
+ m_lockOwner.reset(new AtomicThreadId);
}
RCSResourceObject::~RCSResourceObject()
}
}
- void RCSResourceObject::setAttribute(const std::string& key,
- const ResourceAttributes::Value& value)
+ template< typename K, typename V >
+ void RCSResourceObject::setAttributeInternal(K&& key, V&& value)
{
- WeakGuard lock(*this);
+ bool needToNotify = false;
+ bool valueUpdated = false;
- if(lock.hasLocked())
{
- autoNotifyIfNeeded(key, value);
- }
-
- m_resourceAttributes[key] = value;
- }
+ WeakGuard lock(*this);
- void RCSResourceObject::setAttribute(const std::string& key, ResourceAttributes::Value&& value)
- {
- WeakGuard lock(*this);
+ if (lock.hasLocked())
+ {
+ needToNotify = true;
+ valueUpdated = testValueUpdated(key, value);
+ }
- if(lock.hasLocked())
- {
- autoNotifyIfNeeded(key, value);
+ m_resourceAttributes[std::forward< K >(key)] = std::forward< V >(value);
}
- m_resourceAttributes[key] = std::move(value);
+ if (needToNotify) autoNotify(valueUpdated);
}
-
- void RCSResourceObject::setAttribute(std::string&& key, const ResourceAttributes::Value& value)
+ void RCSResourceObject::setAttribute(const std::string& key,
+ const RCSResourceAttributes::Value& value)
{
- WeakGuard lock(*this);
-
- if(lock.hasLocked())
- {
- autoNotifyIfNeeded(key, value);
- }
-
- m_resourceAttributes[std::move(key)] = value;
+ setAttributeInternal(key, value);
}
- void RCSResourceObject::setAttribute(std::string&& key, ResourceAttributes::Value&& value)
+ void RCSResourceObject::setAttribute(const std::string& key,
+ RCSResourceAttributes::Value&& value)
{
- WeakGuard lock(*this);
+ setAttributeInternal(key, std::move(value));
+ }
- if(lock.hasLocked())
- {
- autoNotifyIfNeeded(key, value);
- }
+ void RCSResourceObject::setAttribute(std::string&& key,
+ const RCSResourceAttributes::Value& value)
+ {
+ setAttributeInternal(std::move(key), value);
+ }
- m_resourceAttributes[std::move(key)] = std::move(value);
+ void RCSResourceObject::setAttribute(std::string&& key,
+ RCSResourceAttributes::Value&& value)
+ {
+ setAttributeInternal(std::move(key), std::move(value));
}
- ResourceAttributes::Value RCSResourceObject::getAttributeValue(const std::string& key) const
+ RCSResourceAttributes::Value RCSResourceObject::getAttributeValue(
+ const std::string& key) const
{
WeakGuard lock(*this);
return m_resourceAttributes.at(key);
bool RCSResourceObject::removeAttribute(const std::string& key)
{
- WeakGuard lock(*this);
- if (m_resourceAttributes.erase(key))
+ bool needToNotify = false;
+ bool erased = false;
{
- autoNotify(true, getAutoNotifyPolicy());
- return true;
+ WeakGuard lock(*this);
+
+ if (m_resourceAttributes.erase(key))
+ {
+ erased = true;
+ needToNotify = lock.hasLocked();
+ }
}
- return false;
+
+ if (needToNotify) autoNotify(true);
+
+ return erased;
}
bool RCSResourceObject::containsAttribute(const std::string& key) const
return m_resourceAttributes.contains(key);
}
- ResourceAttributes& RCSResourceObject::getAttributes()
+ RCSResourceAttributes& RCSResourceObject::getAttributes()
{
expectOwnLock();
return m_resourceAttributes;
}
- const ResourceAttributes& RCSResourceObject::getAttributes() const
+ const RCSResourceAttributes& RCSResourceObject::getAttributes() const
{
expectOwnLock();
return m_resourceAttributes;
void RCSResourceObject::expectOwnLock() const
{
- if (m_lockOwner != std::this_thread::get_id())
+ if (getLockOwner() != std::this_thread::get_id())
{
throw NoLockException{ "Must acquire the lock first using LockGuard." };
}
}
+ std::thread::id RCSResourceObject::getLockOwner() const noexcept
+ {
+ return *m_lockOwner;
+ }
+
+ void RCSResourceObject::setLockOwner(std::thread::id&& id) const noexcept
+ {
+ m_lockOwner->store(std::move(id));
+ }
+
bool RCSResourceObject::isObservable() const
{
return ::hasProperty(m_properties, OC_OBSERVABLE);
{
typedef OCStackResult (*NotifyAllObservers)(OCResourceHandle);
- invokeOCFuncWithResultExpect(
- { OC_STACK_OK, OC_STACK_NO_OBSERVERS },
+ invokeOCFuncWithResultExpect({ OC_STACK_OK, OC_STACK_NO_OBSERVERS },
static_cast< NotifyAllObservers >(OC::OCPlatform::notifyAllObservers),
m_resourceHandle);
}
bool RCSResourceObject::removeAttributeUpdatedListener(const std::string& key)
{
std::lock_guard<std::mutex> lock(m_mutexKeyAttributeUpdate);
- return (bool) m_keyAttributesUpdatedListeners.erase(key);
+
+ return m_keyAttributesUpdatedListeners.erase(key) != 0;
}
- void RCSResourceObject::autoNotifyIfNeeded(const std::string& key,
- const ResourceAttributes::Value& value)
+ bool RCSResourceObject::testValueUpdated(const std::string& key,
+ const RCSResourceAttributes::Value& value) const
{
- autoNotify( m_resourceAttributes.contains(key) == false
- || m_resourceAttributes.at(key) != value
- , m_autoNotifyPolicy);
+ return m_resourceAttributes.contains(key) == false
+ || m_resourceAttributes.at(key) != value;
}
void RCSResourceObject::setAutoNotifyPolicy(AutoNotifyPolicy policy)
m_setRequestHandlerPolicy = policy;
}
- RCSResourceObject::SetRequestHandlerPolicy RCSResourceObject::getSetRequestHandlerPolicy() const
+ auto RCSResourceObject::getSetRequestHandlerPolicy() const -> SetRequestHandlerPolicy
{
return m_setRequestHandlerPolicy;
}
+ void RCSResourceObject::autoNotify(bool isAttributesChanged) const
+ {
+ autoNotify(isAttributesChanged, m_autoNotifyPolicy);
+ }
+
void RCSResourceObject::autoNotify(
bool isAttributesChanged, AutoNotifyPolicy autoNotifyPolicy) const
{
if(autoNotifyPolicy == AutoNotifyPolicy::NEVER) return;
- if(autoNotifyPolicy == AutoNotifyPolicy::UPDATED && isAttributesChanged == false) return;
+ if(autoNotifyPolicy == AutoNotifyPolicy::UPDATED &&
+ isAttributesChanged == false) return;
+
notify();
}
AttrKeyValuePairs replaced = requestHandler->applyAcceptanceMethod(
response.getAcceptanceMethod(), *this, attrs);
- for (const auto& it : replaced)
+ for (const auto& attrKeyValPair : replaced)
{
std::lock_guard<std::mutex> lock(m_mutexKeyAttributeUpdate);
- auto keyAttribute = m_keyAttributesUpdatedListeners.find(it.first);
- if(keyAttribute != m_keyAttributesUpdatedListeners.end())
+ auto keyAttrListener = m_keyAttributesUpdatedListeners.find(attrKeyValPair.first);
+ if(keyAttrListener != m_keyAttributesUpdatedListeners.end())
{
- keyAttribute-> second(it.second, attrs[it.first]);
+ keyAttrListener-> second(attrKeyValPair.second, attrs[attrKeyValPair.first]);
}
}
}
OCEntityHandlerResult RCSResourceObject::handleObserve(
- std::shared_ptr< OC::OCResourceRequest > request)
+ std::shared_ptr< OC::OCResourceRequest >)
{
- assert(request != nullptr);
-
if (!isObservable())
{
return OC_EH_ERROR;
RCSResourceObject::LockGuard::LockGuard(
const RCSResourceObject& resourceObject, AutoNotifyPolicy autoNotifyPolicy) :
- m_resourceObject(resourceObject),
- m_autoNotifyPolicy { autoNotifyPolicy },
- m_isOwningLock{ false }
+ m_resourceObject(resourceObject),
+ m_autoNotifyPolicy { autoNotifyPolicy },
+ m_isOwningLock{ false }
{
init();
}
if (m_isOwningLock)
{
- m_resourceObject.m_lockOwner = std::thread::id{ };
+ m_resourceObject.setLockOwner(std::thread::id{ });
m_resourceObject.m_mutex.unlock();
}
}
void RCSResourceObject::LockGuard::init()
{
- if (m_resourceObject.m_lockOwner != std::this_thread::get_id())
+ if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
{
m_resourceObject.m_mutex.lock();
- m_resourceObject.m_lockOwner = std::this_thread::get_id();
+ m_resourceObject.setLockOwner(std::this_thread::get_id());
m_isOwningLock = true;
}
m_autoNotifyFunc = ::createAutoNotifyInvoker(&RCSResourceObject::autoNotify,
m_isOwningLock{ false },
m_resourceObject(resourceObject)
{
- if (resourceObject.m_lockOwner != std::this_thread::get_id())
+ if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
{
m_resourceObject.m_mutex.lock();
+ m_resourceObject.setLockOwner(std::this_thread::get_id());
m_isOwningLock = true;
}
}
{
if (m_isOwningLock)
{
+ m_resourceObject.setLockOwner(std::thread::id{ });
m_resourceObject.m_mutex.unlock();
}
}
{
return m_isOwningLock;
}
+
}
}