Added get/set apis with query params in RCSRemoteResourceObject.
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / serverBuilder / src / RCSResourceObject.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "RCSResourceObject.h"
22
23 #include <string>
24 #include <functional>
25 #include <vector>
26
27 #include "RequestHandler.h"
28 #include "AssertUtils.h"
29 #include "AtomicHelper.h"
30 #include "ResourceAttributesConverter.h"
31 #include "ResourceAttributesUtils.h"
32 #include "RCSRequest.h"
33 #include "RCSRepresentation.h"
34
35 #include "logger.h"
36 #include "OCPlatform.h"
37
38 #define LOG_TAG "RCSResourceObject"
39
40 namespace
41 {
42     using namespace OIC::Service;
43
44     inline bool hasProperty(uint8_t base, uint8_t target)
45     {
46         return (base & target) == target;
47     }
48
49     inline uint8_t makePropertyFlags(uint8_t base, uint8_t target, bool add)
50     {
51         if (add)
52         {
53             return base | target;
54         }
55
56         return base & ~target;
57     }
58
59     inline bool requestContainsInterface(const std::shared_ptr< OC::OCResourceRequest >& request,
60             const std::string& interface)
61     {
62         return request->getQueryParameters().find(interface) != request->getQueryParameters().end();
63     }
64
65     OCEntityHandlerResult sendResponse(const std::shared_ptr< OC::OCResourceRequest >& ocRequest,
66             const std::shared_ptr< OC::OCResourceResponse >& ocResponse)
67     {
68         ocResponse->setRequestHandle(ocRequest->getRequestHandle());
69         ocResponse->setResourceHandle(ocRequest->getResourceHandle());
70
71         try
72         {
73             if (OC::OCPlatform::sendResponse(ocResponse) == OC_STACK_OK)
74             {
75                 return OC_EH_OK;
76             }
77         }
78         catch (const OC::OCException& e)
79         {
80             OIC_LOG_V(WARNING, LOG_TAG, "Error (%s)", e.what());
81         }
82
83         return OC_EH_ERROR;
84     }
85
86
87     template <typename RESPONSE>
88     OCEntityHandlerResult sendResponse(RCSResourceObject& resource,
89             const std::shared_ptr< OC::OCResourceRequest >& ocRequest, RESPONSE&& response)
90     {
91         return sendResponse(ocRequest, response.getHandler()->buildResponse(resource));
92     }
93
94     RCSResourceAttributes getAttributesFromOCRequest(
95             const std::shared_ptr< OC::OCResourceRequest >& request)
96     {
97         return ResourceAttributesConverter::fromOCRepresentation(
98                 request->getResourceRepresentation());
99     }
100
101     template< typename HANDLER, typename RESPONSE =
102             typename std::decay<HANDLER>::type::result_type >
103     RESPONSE invokeHandler(RCSResourceAttributes& attrs,
104             const std::shared_ptr< OC::OCResourceRequest >& ocRequest,
105             std::shared_ptr< HANDLER > handler)
106     {
107         if (handler)
108         {
109             return (*handler)(RCSRequest{ ocRequest }, attrs);
110         }
111
112         return RESPONSE::defaultAction();
113     }
114
115     typedef void (RCSResourceObject::* AutoNotifyFunc)
116             (bool, RCSResourceObject::AutoNotifyPolicy) const;
117
118     std::function<void()> createAutoNotifyInvoker(AutoNotifyFunc autoNotifyFunc,
119             const RCSResourceObject& resourceObject, const RCSResourceAttributes& resourceAttributes,
120             RCSResourceObject::AutoNotifyPolicy autoNotifyPolicy)
121     {
122         if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::UPDATED)
123         {
124             auto&& compareAttributesFunc =
125                     std::bind(std::not_equal_to<RCSResourceAttributes>(),
126                                 resourceAttributes,
127                                 std::cref(resourceAttributes));
128             return std::bind(autoNotifyFunc,
129                     &resourceObject, std::move(compareAttributesFunc), autoNotifyPolicy);
130         }
131         else if(autoNotifyPolicy == RCSResourceObject::AutoNotifyPolicy::ALWAYS)
132         {
133             return std::bind(autoNotifyFunc,
134                     &resourceObject, true, autoNotifyPolicy);
135         }
136         return {};
137     }
138
139     OCEntityHandlerResult handleBatchInterfaceGetRequest(
140             const std::shared_ptr< OC::OCResourceRequest >& request,
141             const RCSResourceObject* resourceObject)
142     {
143         auto rcsRep = resourceObject->toRepresentation();
144
145         for (const auto& bound : resourceObject->getBoundResources())
146         {
147             rcsRep.addChild(bound->toRepresentation());
148         }
149
150         auto response = std::make_shared< OC::OCResourceResponse >();
151
152         response->setResponseResult(OC_EH_OK);
153         response->setErrorCode(200);
154         response->setResourceRepresentation(
155                 RCSRepresentation::toOCRepresentation(std::move(rcsRep)));
156
157         return sendResponse(request, response);
158     }
159
160 } // unnamed namespace
161
162 namespace OIC
163 {
164     namespace Service
165     {
166
167         RCSResourceObject::Builder::Builder(const std::string& uri, const std::string& type,
168                 const std::string& interface) :
169                 m_uri{ uri },
170                 m_types{ type },
171                 m_interfaces{ interface },
172                 m_properties{ OC_DISCOVERABLE | OC_OBSERVABLE },
173                 m_resourceAttributes{ }
174         {
175         }
176
177         RCSResourceObject::Builder& RCSResourceObject::Builder::addInterface(
178                 const std::string& interface)
179         {
180             return addInterface(std::string{ interface });
181         }
182
183         RCSResourceObject::Builder& RCSResourceObject::Builder::addInterface(
184                 std::string&& interface)
185         {
186             m_interfaces.push_back(std::move(interface));
187             return *this;
188         }
189
190         RCSResourceObject::Builder& RCSResourceObject::Builder::addType(const std::string& type)
191         {
192             return addType(std::string{ type });
193         }
194
195         RCSResourceObject::Builder& RCSResourceObject::Builder::addType(std::string&& type)
196         {
197             m_types.push_back(std::move(type));
198             return *this;
199         }
200
201         RCSResourceObject::Builder& RCSResourceObject::Builder::setDiscoverable(
202                 bool discoverable)
203         {
204             m_properties = ::makePropertyFlags(m_properties, OC_DISCOVERABLE, discoverable);
205             return *this;
206         }
207
208         RCSResourceObject::Builder& RCSResourceObject::Builder::setObservable(
209                 bool observable)
210         {
211             m_properties = ::makePropertyFlags(m_properties, OC_OBSERVABLE, observable);
212             return *this;
213         }
214
215         RCSResourceObject::Builder& RCSResourceObject::Builder::setSecureFlag(
216             bool secureFlag)
217         {
218             m_properties = ::makePropertyFlags(m_properties, OC_SECURE, secureFlag);
219             return *this;
220         }
221         RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
222                 const RCSResourceAttributes& attrs)
223         {
224             m_resourceAttributes = attrs;
225             return *this;
226         }
227
228         RCSResourceObject::Builder& RCSResourceObject::Builder::setAttributes(
229                 RCSResourceAttributes&& attrs)
230         {
231             m_resourceAttributes = std::move(attrs);
232             return *this;
233         }
234
235         RCSResourceObject::Ptr RCSResourceObject::Builder::build()
236         {
237             OCResourceHandle handle{ nullptr };
238
239             RCSResourceObject::Ptr server {
240                 new RCSResourceObject{ m_uri, m_properties, std::move(m_resourceAttributes) } };
241
242             OC::EntityHandler entityHandler{ std::bind(&RCSResourceObject::entityHandler,
243                     server.get(), std::placeholders::_1) };
244
245             typedef OCStackResult (*RegisterResource)(OCResourceHandle&, std::string&,
246                     const std::string&, const std::string&, OC::EntityHandler, uint8_t);
247
248             invokeOCFunc(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
249                     handle, m_uri, m_types[0], m_interfaces[0], entityHandler, m_properties);
250
251             std::for_each(m_interfaces.begin() + 1, m_interfaces.end(),
252                     [&handle](const std::string& interfaceName){
253                 invokeOCFunc(OC::OCPlatform::bindInterfaceToResource, handle, interfaceName);
254             });
255
256             std::for_each(m_types.begin() + 1, m_types.end(),
257                     [&handle](const std::string& typeName){
258                 invokeOCFunc(OC::OCPlatform::bindTypeToResource, handle, typeName);
259             });
260
261             server->m_resourceHandle = handle;
262             server->m_interfaces = m_interfaces;
263             server->m_types = m_types;
264
265             return server;
266         }
267
268
269         RCSResourceObject::RCSResourceObject(const std::string& uri,
270                 uint8_t properties, RCSResourceAttributes&& attrs) :
271                 m_properties{ properties },
272                 m_uri{ uri },
273                 m_interfaces{ },
274                 m_types{ },
275                 m_resourceHandle{ },
276                 m_resourceAttributes{ std::move(attrs) },
277                 m_getRequestHandler{ },
278                 m_setRequestHandler{ },
279                 m_autoNotifyPolicy{ AutoNotifyPolicy::UPDATED },
280                 m_setRequestHandlerPolicy{ SetRequestHandlerPolicy::NEVER },
281                 m_attributeUpdatedListeners{ },
282                 m_lockOwner{ },
283                 m_mutex{ },
284                 m_mutexAttributeUpdatedListeners{ }
285         {
286             m_lockOwner.reset(new AtomicThreadId);
287         }
288
289         RCSResourceObject::~RCSResourceObject()
290         {
291             if (m_resourceHandle)
292             {
293                 try
294                 {
295                     OC::OCPlatform::unregisterResource(m_resourceHandle);
296                 }
297                 catch (...)
298                 {
299                     OIC_LOG(WARNING, LOG_TAG, "Failed to unregister resource.");
300                 }
301             }
302         }
303
304         template< typename K, typename V >
305         void RCSResourceObject::setAttributeInternal(K&& key, V&& value)
306         {
307             bool needToNotify = false;
308             bool valueUpdated = false;
309
310             {
311                 WeakGuard lock(*this);
312
313                 if (lock.hasLocked())
314                 {
315                     needToNotify = true;
316                     valueUpdated = testValueUpdated(key, value);
317                 }
318
319                 m_resourceAttributes[std::forward< K >(key)] = std::forward< V >(value);
320             }
321
322             if (needToNotify) autoNotify(valueUpdated);
323         }
324         void RCSResourceObject::setAttribute(const std::string& key,
325                 const RCSResourceAttributes::Value& value)
326         {
327             setAttributeInternal(key, value);
328         }
329
330         void RCSResourceObject::setAttribute(const std::string& key,
331                 RCSResourceAttributes::Value&& value)
332         {
333             setAttributeInternal(key, std::move(value));
334         }
335
336         void RCSResourceObject::setAttribute(std::string&& key,
337                 const RCSResourceAttributes::Value& value)
338         {
339             setAttributeInternal(std::move(key), value);
340         }
341
342         void RCSResourceObject::setAttribute(std::string&& key,
343                 RCSResourceAttributes::Value&& value)
344         {
345             setAttributeInternal(std::move(key), std::move(value));
346         }
347
348         RCSResourceAttributes::Value RCSResourceObject::getAttributeValue(
349                 const std::string& key) const
350         {
351             WeakGuard lock(*this);
352             return m_resourceAttributes.at(key);
353         }
354
355         bool RCSResourceObject::removeAttribute(const std::string& key)
356         {
357             bool needToNotify = false;
358             bool erased = false;
359             {
360                 WeakGuard lock(*this);
361
362                 if (m_resourceAttributes.erase(key))
363                 {
364                     erased = true;
365                     needToNotify = lock.hasLocked();
366                 }
367             }
368
369             if (needToNotify) autoNotify(true);
370
371             return erased;
372         }
373
374         bool RCSResourceObject::containsAttribute(const std::string& key) const
375         {
376             WeakGuard lock(*this);
377             return m_resourceAttributes.contains(key);
378         }
379
380         RCSResourceAttributes& RCSResourceObject::getAttributes()
381         {
382             expectOwnLock();
383             return m_resourceAttributes;
384         }
385
386         const RCSResourceAttributes& RCSResourceObject::getAttributes() const
387         {
388             expectOwnLock();
389             return m_resourceAttributes;
390         }
391
392         void RCSResourceObject::expectOwnLock() const
393         {
394             if (getLockOwner() != std::this_thread::get_id())
395             {
396                 throw NoLockException{ "Must acquire the lock first using LockGuard." };
397             }
398         }
399
400         std::thread::id RCSResourceObject::getLockOwner() const noexcept
401         {
402             return *m_lockOwner;
403         }
404
405         void RCSResourceObject::setLockOwner(std::thread::id&& id) const noexcept
406         {
407             m_lockOwner->store(std::move(id));
408         }
409
410         bool RCSResourceObject::isObservable() const
411         {
412             return ::hasProperty(m_properties, OC_OBSERVABLE);
413         }
414
415         bool RCSResourceObject::isDiscoverable() const
416         {
417             return ::hasProperty(m_properties, OC_DISCOVERABLE);
418         }
419
420         void RCSResourceObject::setGetRequestHandler(GetRequestHandler h)
421         {
422             m_getRequestHandler = std::make_shared< GetRequestHandler >(std::move(h));
423         }
424
425         void RCSResourceObject::setSetRequestHandler(SetRequestHandler h)
426         {
427             m_setRequestHandler = std::make_shared< SetRequestHandler >(std::move(h));
428         }
429
430         void RCSResourceObject::notify() const
431         {
432             typedef OCStackResult (*NotifyAllObservers)(OCResourceHandle);
433
434             invokeOCFuncWithResultExpect({ OC_STACK_OK, OC_STACK_NO_OBSERVERS },
435                     static_cast< NotifyAllObservers >(OC::OCPlatform::notifyAllObservers),
436                     m_resourceHandle);
437         }
438
439         void RCSResourceObject::addAttributeUpdatedListener(const std::string& key,
440                 AttributeUpdatedListener h)
441         {
442             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
443
444             m_attributeUpdatedListeners[key] =
445                     std::make_shared< AttributeUpdatedListener >(std::move(h));
446         }
447
448         void RCSResourceObject::addAttributeUpdatedListener(std::string&& key,
449                 AttributeUpdatedListener h)
450         {
451             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
452
453             m_attributeUpdatedListeners[std::move(key)] =
454                     std::make_shared< AttributeUpdatedListener >(std::move(h));
455         }
456
457         bool RCSResourceObject::removeAttributeUpdatedListener(const std::string& key)
458         {
459             std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
460
461             return m_attributeUpdatedListeners.erase(key) != 0;
462         }
463
464         bool RCSResourceObject::testValueUpdated(const std::string& key,
465                 const RCSResourceAttributes::Value& value) const
466         {
467             return m_resourceAttributes.contains(key) == false
468                     || m_resourceAttributes.at(key) != value;
469         }
470
471         void RCSResourceObject::setAutoNotifyPolicy(AutoNotifyPolicy policy)
472         {
473             m_autoNotifyPolicy = policy;
474         }
475
476         RCSResourceObject::AutoNotifyPolicy RCSResourceObject::getAutoNotifyPolicy() const
477         {
478             return m_autoNotifyPolicy;
479         }
480
481         void RCSResourceObject::setSetRequestHandlerPolicy(SetRequestHandlerPolicy policy)
482         {
483             m_setRequestHandlerPolicy = policy;
484         }
485
486         auto RCSResourceObject::getSetRequestHandlerPolicy() const -> SetRequestHandlerPolicy
487         {
488             return m_setRequestHandlerPolicy;
489         }
490
491         void RCSResourceObject::bindResource(const RCSResourceObject::Ptr& resource)
492         {
493             if (!resource || resource.get() == this)
494             {
495                 throw RCSInvalidParameterException("The resource is invalid!");
496             }
497
498             invokeOCFunc(OC::OCPlatform::bindResource,
499                     m_resourceHandle, resource->m_resourceHandle);
500
501             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
502             m_boundResources.push_back(resource);
503         }
504
505         void RCSResourceObject::unbindResource(const RCSResourceObject::Ptr& resource)
506         {
507             if (!resource || resource.get() == this)
508             {
509                 throw RCSInvalidParameterException("The resource is invalid!");
510             }
511
512             invokeOCFunc(OC::OCPlatform::unbindResource,
513                     m_resourceHandle, resource->m_resourceHandle);
514
515             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
516             m_boundResources.erase(std::find(m_boundResources.begin(), m_boundResources.end(),
517                     resource));
518         }
519
520         std::vector< RCSResourceObject::Ptr > RCSResourceObject::getBoundResources() const
521         {
522             std::lock_guard< std:: mutex > lock{ m_mutexForBoundResources };
523             return m_boundResources;
524         }
525
526         std::vector< std::string > RCSResourceObject::getInterfaces() const
527         {
528             return m_interfaces;
529         }
530
531         std::vector< std::string > RCSResourceObject::getTypes() const
532         {
533             return m_types;
534         }
535
536         RCSRepresentation RCSResourceObject::toRepresentation() const
537         {
538             return RCSRepresentation{ m_uri, m_interfaces, m_types, m_resourceAttributes };
539          }
540
541         void RCSResourceObject::autoNotify(bool isAttributesChanged) const
542         {
543             autoNotify(isAttributesChanged, m_autoNotifyPolicy);
544         }
545
546         void RCSResourceObject::autoNotify(
547                         bool isAttributesChanged, AutoNotifyPolicy autoNotifyPolicy) const
548         {
549             if(autoNotifyPolicy == AutoNotifyPolicy::NEVER) return;
550             if(autoNotifyPolicy == AutoNotifyPolicy::UPDATED &&
551                     isAttributesChanged == false) return;
552
553             notify();
554         }
555
556         OCEntityHandlerResult RCSResourceObject::entityHandler(
557                 const std::shared_ptr< OC::OCResourceRequest >& request)
558         {
559             OIC_LOG(WARNING, LOG_TAG, "entityHandler");
560             if (!request)
561             {
562                 return OC_EH_ERROR;
563             }
564
565             try
566             {
567                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::RequestFlag)
568                 {
569                     return handleRequest(request);
570                 }
571
572                 if (request->getRequestHandlerFlag() & OC::RequestHandlerFlag::ObserverFlag)
573                 {
574                     return handleObserve(request);
575                 }
576             }
577             catch (const std::exception& e)
578             {
579                 OIC_LOG_V(WARNING, LOG_TAG, "Failed to handle request : %s", e.what());
580                 throw;
581             }
582             catch (...)
583             {
584                 OIC_LOG(WARNING, LOG_TAG, "Failed to handle request.");
585                 throw;
586             }
587
588             return OC_EH_ERROR;
589         }
590
591         OCEntityHandlerResult RCSResourceObject::handleRequest(
592                 const std::shared_ptr< OC::OCResourceRequest >& request)
593         {
594             assert(request != nullptr);
595
596             if (request->getRequestType() == "GET")
597             {
598                 return handleRequestGet(request);
599             }
600
601             if (request->getRequestType() == "POST")
602             {
603                 return handleRequestSet(request);
604             }
605
606             return OC_EH_ERROR;
607         }
608
609         OCEntityHandlerResult RCSResourceObject::handleRequestGet(
610                 const std::shared_ptr< OC::OCResourceRequest >& request)
611         {
612             assert(request != nullptr);
613
614             if (requestContainsInterface(request, OC::BATCH_INTERFACE))
615             {
616                 return handleBatchInterfaceGetRequest(request, this);
617             }
618
619             auto attrs = getAttributesFromOCRequest(request);
620
621             return sendResponse(*this, request, invokeHandler(attrs, request, m_getRequestHandler));
622         }
623
624         bool RCSResourceObject::applyAcceptanceMethod(const RCSSetResponse& response,
625                 const RCSResourceAttributes& requstAttrs)
626         {
627             auto requestHandler = response.getHandler();
628
629             assert(requestHandler != nullptr);
630
631             auto replaced = requestHandler->applyAcceptanceMethod(response.getAcceptanceMethod(),
632                     *this, requstAttrs);
633
634             OIC_LOG_V(WARNING, LOG_TAG, "replaced num %zu", replaced.size());
635             for (const auto& attrKeyValPair : replaced)
636             {
637                 std::shared_ptr< AttributeUpdatedListener > foundListener;
638                 {
639                     std::lock_guard< std::mutex > lock(m_mutexAttributeUpdatedListeners);
640
641                     auto it = m_attributeUpdatedListeners.find(attrKeyValPair.first);
642                     if (it != m_attributeUpdatedListeners.end())
643                     {
644                         foundListener = it->second;
645                     }
646                 }
647
648                 if (foundListener)
649                 {
650                     (*foundListener)(attrKeyValPair.second, requstAttrs.at(attrKeyValPair.first));
651                 }
652             }
653
654             return !replaced.empty();
655         }
656
657         OCEntityHandlerResult RCSResourceObject::handleRequestSet(
658                 const std::shared_ptr< OC::OCResourceRequest >& request)
659         {
660             assert(request != nullptr);
661
662             auto attrs = getAttributesFromOCRequest(request);
663             auto response = invokeHandler(attrs, request, m_setRequestHandler);
664
665             auto attrsChanged = applyAcceptanceMethod(response, attrs);
666
667             try
668             {
669                 autoNotify(attrsChanged, m_autoNotifyPolicy);
670                 return sendResponse(*this, request, response);
671             } catch (const RCSPlatformException& e) {
672                 OIC_LOG_V(ERROR, LOG_TAG, "Error : %s ", e.what());
673                 return OC_EH_ERROR;
674             }
675         }
676
677         OCEntityHandlerResult RCSResourceObject::handleObserve(
678                 const std::shared_ptr< OC::OCResourceRequest >&)
679         {
680             if (!isObservable())
681             {
682                 return OC_EH_ERROR;
683             }
684
685             return OC_EH_OK;
686         }
687
688         RCSResourceObject::LockGuard::LockGuard(const RCSResourceObject::Ptr ptr) :
689                 m_resourceObject(*ptr),
690                 m_autoNotifyPolicy{ ptr->getAutoNotifyPolicy() },
691                 m_isOwningLock{ false }
692         {
693             init();
694         }
695
696         RCSResourceObject::LockGuard::LockGuard(
697                 const RCSResourceObject& serverResource) :
698                 m_resourceObject(serverResource),
699                 m_autoNotifyPolicy{ serverResource.getAutoNotifyPolicy() },
700                 m_isOwningLock{ false }
701         {
702             init();
703         }
704
705         RCSResourceObject::LockGuard::LockGuard(
706                 const RCSResourceObject::Ptr ptr, AutoNotifyPolicy autoNotifyPolicy) :
707                 m_resourceObject(*ptr),
708                 m_autoNotifyPolicy { autoNotifyPolicy },
709                 m_isOwningLock{ false }
710         {
711             init();
712         }
713
714         RCSResourceObject::LockGuard::LockGuard(
715                 const RCSResourceObject& resourceObject, AutoNotifyPolicy autoNotifyPolicy) :
716                 m_resourceObject(resourceObject),
717                 m_autoNotifyPolicy { autoNotifyPolicy },
718                 m_isOwningLock{ false }
719         {
720             init();
721         }
722
723         RCSResourceObject::LockGuard::~LockGuard() noexcept(false)
724         {
725             if (!std::uncaught_exception() && m_autoNotifyFunc) m_autoNotifyFunc();
726
727             if (m_isOwningLock)
728             {
729                 m_resourceObject.setLockOwner(std::thread::id{ });
730                 m_resourceObject.m_mutex.unlock();
731             }
732         }
733
734         void RCSResourceObject::LockGuard::init()
735         {
736             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
737             {
738                 m_resourceObject.m_mutex.lock();
739                 m_resourceObject.setLockOwner(std::this_thread::get_id());
740                 m_isOwningLock = true;
741             }
742             m_autoNotifyFunc = ::createAutoNotifyInvoker(&RCSResourceObject::autoNotify,
743                     m_resourceObject, m_resourceObject.m_resourceAttributes, m_autoNotifyPolicy);
744         }
745
746         RCSResourceObject::WeakGuard::WeakGuard(
747                 const RCSResourceObject& resourceObject) :
748                 m_isOwningLock{ false },
749                 m_resourceObject(resourceObject)
750         {
751             if (m_resourceObject.getLockOwner() != std::this_thread::get_id())
752             {
753                 m_resourceObject.m_mutex.lock();
754                 m_resourceObject.setLockOwner(std::this_thread::get_id());
755                 m_isOwningLock = true;
756             }
757         }
758
759         RCSResourceObject::WeakGuard::~WeakGuard()
760         {
761             if (m_isOwningLock)
762             {
763                 m_resourceObject.setLockOwner(std::thread::id{ });
764                 m_resourceObject.m_mutex.unlock();
765             }
766         }
767
768         bool RCSResourceObject::WeakGuard::hasLocked() const
769         {
770             return m_isOwningLock;
771         }
772
773     }
774 }