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 a41f41f..ffbf522
@@ -26,6 +26,7 @@
 
 #include <RequestHandler.h>
 #include <AssertUtils.h>
+#include <AtomicHelper.h>
 #include <ResourceAttributesConverter.h>
 
 #include <logger.h>
@@ -174,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;
 
@@ -206,6 +200,7 @@ namespace OIC
                 m_mutex{ },
                 m_mutexKeyAttributeUpdate{ }
         {
+            m_lockOwner.reset(new AtomicThreadId);
         }
 
         RCSResourceObject::~RCSResourceObject()
@@ -223,56 +218,48 @@ namespace OIC
             }
         }
 
-        void RCSResourceObject::setAttribute(const std::string& key,
-                const RCSResourceAttributes::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);
+                WeakGuard lock(*this);
+
+                if (lock.hasLocked())
+                {
+                    needToNotify = true;
+                    valueUpdated = testValueUpdated(key, value);
+                }
+
+                m_resourceAttributes[std::forward< K >(key)] = std::forward< V >(value);
             }
 
-            m_resourceAttributes[key] = value;
+            if (needToNotify) autoNotify(valueUpdated);
+        }
+        void RCSResourceObject::setAttribute(const std::string& key,
+                const RCSResourceAttributes::Value& value)
+        {
+            setAttributeInternal(key, value);
         }
 
         void RCSResourceObject::setAttribute(const std::string& key,
                 RCSResourceAttributes::Value&& value)
         {
-            WeakGuard lock(*this);
-
-            if(lock.hasLocked())
-            {
-                autoNotifyIfNeeded(key, value);
-            }
-
-            m_resourceAttributes[key] = std::move(value);
+            setAttributeInternal(key, std::move(value));
         }
 
         void RCSResourceObject::setAttribute(std::string&& key,
                 const RCSResourceAttributes::Value& value)
         {
-            WeakGuard lock(*this);
-
-            if(lock.hasLocked())
-            {
-                autoNotifyIfNeeded(key, value);
-            }
-
-            m_resourceAttributes[std::move(key)] = value;
+            setAttributeInternal(std::move(key), value);
         }
 
         void RCSResourceObject::setAttribute(std::string&& key,
                 RCSResourceAttributes::Value&& value)
         {
-            WeakGuard lock(*this);
-
-            if(lock.hasLocked())
-            {
-                autoNotifyIfNeeded(key, value);
-            }
-
-            m_resourceAttributes[std::move(key)] = std::move(value);
+            setAttributeInternal(std::move(key), std::move(value));
         }
 
         RCSResourceAttributes::Value RCSResourceObject::getAttributeValue(
@@ -284,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
@@ -313,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);
@@ -343,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);
         }
@@ -366,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 RCSResourceAttributes::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)
@@ -397,11 +401,18 @@ namespace OIC
             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();
         }
 
@@ -481,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]);
                 }
             }
 
@@ -497,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;
@@ -537,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();
         }
@@ -550,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,
@@ -572,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;
             }
         }
@@ -583,6 +593,7 @@ namespace OIC
         {
             if (m_isOwningLock)
             {
+                m_resourceObject.setLockOwner(std::thread::id{ });
                 m_resourceObject.m_mutex.unlock();
             }
         }
@@ -591,5 +602,6 @@ namespace OIC
         {
             return m_isOwningLock;
         }
+
     }
 }