Merge branch 'master' into easysetup & CBOR changes
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / serverBuilder / src / RCSResourceObject.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 88c36a1..ffbf522
@@ -26,6 +26,7 @@
 
 #include <RequestHandler.h>
 #include <AssertUtils.h>
+#include <AtomicHelper.h>
 #include <ResourceAttributesConverter.h>
 
 #include <logger.h>
@@ -75,14 +76,16 @@ namespace
         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)
@@ -93,16 +96,17 @@ namespace
         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,
@@ -148,14 +152,14 @@ namespace OIC
         }
 
         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;
@@ -171,18 +175,11 @@ namespace OIC
             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;
 
@@ -190,7 +187,7 @@ namespace OIC
         }
 
 
-        RCSResourceObject::RCSResourceObject(uint8_t properties, ResourceAttributes&& attrs) :
+        RCSResourceObject::RCSResourceObject(uint8_t properties, RCSResourceAttributes&& attrs) :
                 m_properties { properties },
                 m_resourceHandle{ },
                 m_resourceAttributes{ std::move(attrs) },
@@ -203,6 +200,7 @@ namespace OIC
                 m_mutex{ },
                 m_mutexKeyAttributeUpdate{ }
         {
+            m_lockOwner.reset(new AtomicThreadId);
         }
 
         RCSResourceObject::~RCSResourceObject()
@@ -220,56 +218,52 @@ namespace OIC
             }
         }
 
-        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);
@@ -277,13 +271,21 @@ namespace OIC
 
         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
@@ -292,13 +294,13 @@ namespace OIC
             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;
@@ -306,12 +308,22 @@ namespace OIC
 
         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);
@@ -336,8 +348,7 @@ namespace OIC
         {
             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);
         }
@@ -359,15 +370,15 @@ namespace OIC
         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)
@@ -385,16 +396,23 @@ namespace OIC
             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();
         }
 
@@ -474,14 +492,14 @@ namespace OIC
             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]);
                 }
             }
 
@@ -490,10 +508,8 @@ namespace OIC
         }
 
         OCEntityHandlerResult RCSResourceObject::handleObserve(
-                std::shared_ptr< OC::OCResourceRequest > request)
+                std::shared_ptr< OC::OCResourceRequest >)
         {
-            assert(request != nullptr);
-
             if (!isObservable())
             {
                 return OC_EH_ERROR;
@@ -530,9 +546,9 @@ namespace OIC
 
         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();
         }
@@ -543,17 +559,17 @@ namespace OIC
 
             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,
@@ -565,9 +581,10 @@ namespace OIC
                 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;
             }
         }
@@ -576,6 +593,7 @@ namespace OIC
         {
             if (m_isOwningLock)
             {
+                m_resourceObject.setLockOwner(std::thread::id{ });
                 m_resourceObject.m_mutex.unlock();
             }
         }
@@ -584,5 +602,6 @@ namespace OIC
         {
             return m_isOwningLock;
         }
+
     }
 }