-
Notifications
You must be signed in to change notification settings - Fork 791
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix destruction data-race on participant removal in intra-process (#5034
) (#5367) * Fix destruction data-race on participant removal in intra-process (#5034) * Refs #21293: Add BB test Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: Reinforce test to fail more frequently Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: Add RefCountedPointer.hpp to utils Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: Add unittests for RefCountedPointer Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: LocalReaderPointer.hpp Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: BaseReader aggregates LocalReaderPointer Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: ReaderLocator aggregates LocalReaderPointer Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: RTPSDomainImpl::find_local_reader returns a sared_ptr<LocalReaderPointer> and properly calls local_actions_on_reader_removed() Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: RTPSWriters properly using LocalReaderPointer::Instance when accessing local reader Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: Linter Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: Fix windows warnings Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: Address Miguel's review Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: Apply last comment Signed-off-by: Mario Dominguez <[email protected]> * Refs #21293: NIT Signed-off-by: Mario Dominguez <[email protected]> --------- Signed-off-by: Mario Dominguez <[email protected]> (cherry picked from commit 456e45f) # Conflicts: # include/fastdds/rtps/writer/ReaderLocator.h # include/fastdds/rtps/writer/ReaderProxy.h # src/cpp/rtps/RTPSDomain.cpp # src/cpp/rtps/RTPSDomainImpl.hpp # src/cpp/rtps/participant/RTPSParticipantImpl.cpp # src/cpp/rtps/participant/RTPSParticipantImpl.h # src/cpp/rtps/reader/BaseReader.cpp # src/cpp/rtps/reader/BaseReader.hpp # src/cpp/rtps/writer/ReaderLocator.cpp # src/cpp/rtps/writer/StatefulWriter.cpp # src/cpp/rtps/writer/StatelessWriter.cpp # test/blackbox/common/DDSBlackboxTestsBasic.cpp # test/mock/rtps/ReaderLocator/fastdds/rtps/writer/ReaderLocator.h # test/unittest/utils/CMakeLists.txt * Solve conflicts Signed-off-by: Mario Dominguez <[email protected]> * Apply Miguel's suggestions: make LocalReaderPointer inherit RefCounterPointer<> and add DOXYGEN_SHOULD_SKIP_THIS_PUBLIC Signed-off-by: Mario Dominguez <[email protected]> * Apply NIT Signed-off-by: Mario Dominguez <[email protected]> * Construct LocalReaderPointer in RTPSReader Signed-off-by: Mario Dominguez <[email protected]> --------- Signed-off-by: Mario Dominguez <[email protected]> Co-authored-by: Mario Domínguez López <[email protected]> Co-authored-by: Mario Dominguez <[email protected]>
- Loading branch information
1 parent
725e8ab
commit 28e2ce8
Showing
18 changed files
with
667 additions
and
68 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
/** | ||
* @file LocalReaderPointer.hpp | ||
*/ | ||
|
||
#ifndef FASTDDS_RTPS_READER__LOCALREADERPOINTER_HPP | ||
#define FASTDDS_RTPS_READER__LOCALREADERPOINTER_HPP | ||
|
||
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC | ||
|
||
#include <fastrtps/utils/RefCountedPointer.hpp> | ||
|
||
namespace eprosima { | ||
namespace fastrtps { | ||
namespace rtps { | ||
|
||
class RTPSReader; | ||
|
||
struct LocalReaderPointer : public RefCountedPointer<RTPSReader> | ||
{ | ||
LocalReaderPointer( | ||
RTPSReader* ptr) | ||
: RefCountedPointer<RTPSReader>(ptr) | ||
{ | ||
} | ||
|
||
virtual ~LocalReaderPointer() = default; | ||
|
||
}; | ||
|
||
} // namespace rtps | ||
} // namespace fastdds | ||
} // namespace eprosima | ||
|
||
#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC | ||
|
||
#endif // FASTDDS_RTPS_READER__LOCALREADERPOINTER_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
// Copyright 2024 Proyectos y Sistemas de Mantenimiento SL (eProsima). | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
/** | ||
* @file RefCountedPointer.hpp | ||
*/ | ||
|
||
#ifndef UTILS__REFCOUNTEDPOINTER_HPP | ||
#define UTILS__REFCOUNTEDPOINTER_HPP | ||
|
||
#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC | ||
|
||
#include <atomic> | ||
#include <cassert> | ||
#include <condition_variable> | ||
#include <cstdint> | ||
#include <memory> | ||
#include <mutex> | ||
|
||
namespace eprosima { | ||
namespace fastrtps { | ||
|
||
/** | ||
* @brief Class to manage a local pointer with reference counting. | ||
* | ||
* It is similar to std::shared_ptr, but designed for cases where | ||
* a shared pointer cannot be used due to API restrictions. | ||
* | ||
* USAGE: | ||
* - On T class: | ||
* - Add a shared_ptr<RefCountedPointer<T>> local_ptr_ member. | ||
* - Call local_ptr_->deactivate() before destroying T. | ||
* | ||
* - On classes that need to use a pointer to T: | ||
* - Keep a copy of the shared_ptr<RefCountedPointer<T>>. | ||
* - Whenever you need to access T: | ||
* RefCountedPointer<T>::Instance instance(local_ptr_) | ||
* if (instance) | ||
* { | ||
* ptr->method(); | ||
* } | ||
*/ | ||
template<typename T> | ||
class RefCountedPointer | ||
{ | ||
public: | ||
|
||
class Instance; | ||
|
||
/** | ||
* @brief Explicit constructor. | ||
* @param ptr Pointer to manage. | ||
* | ||
* @pre nullptr != ptr. We must ensure that the pointer we | ||
* are manaing is valid. | ||
*/ | ||
explicit RefCountedPointer( | ||
T* ptr) | ||
: ptr_(ptr) | ||
, is_active_(true) | ||
, instances_(0) | ||
{ | ||
assert(nullptr != ptr); | ||
} | ||
|
||
~RefCountedPointer() = default; | ||
|
||
// Non-copyable and non-movable | ||
RefCountedPointer( | ||
const RefCountedPointer&) = delete; | ||
RefCountedPointer& operator =( | ||
const RefCountedPointer&) = delete; | ||
RefCountedPointer( | ||
RefCountedPointer&&) = delete; | ||
RefCountedPointer& operator =( | ||
RefCountedPointer&&) = delete; | ||
|
||
/** | ||
* @brief Class to manage the local pointer instance. | ||
* It will increase the reference count on construction and decrease | ||
* it on destruction. Provides a facade to access the pointee. | ||
*/ | ||
class Instance | ||
{ | ||
public: | ||
|
||
/** | ||
* @brief Constructor. | ||
* @param parent Shared pointer reference to its RefCountedPointer. | ||
*/ | ||
explicit Instance( | ||
const std::shared_ptr<RefCountedPointer<T>>& parent) | ||
: parent_(parent) | ||
, ptr_(parent && parent->is_active_ ? parent->ptr_ : nullptr) | ||
{ | ||
if (parent_) | ||
{ | ||
parent_->inc_instances(); | ||
} | ||
} | ||
|
||
/** | ||
* @brief Destructor. | ||
*/ | ||
~Instance() | ||
{ | ||
if (parent_) | ||
{ | ||
parent_->dec_instances(); | ||
} | ||
} | ||
|
||
// Non-copyable, default movable | ||
Instance( | ||
const Instance&) = delete; | ||
Instance& operator =( | ||
const Instance&) = delete; | ||
Instance( | ||
Instance&&) = default; | ||
Instance& operator =( | ||
Instance&&) = default; | ||
|
||
/** | ||
* @brief operator to check if the pointer is valid. | ||
*/ | ||
operator bool() const | ||
{ | ||
return nullptr != ptr_; | ||
} | ||
|
||
/** | ||
* @brief operator to call the T methods. | ||
*/ | ||
T* operator ->() const | ||
{ | ||
assert(nullptr != ptr_); | ||
return ptr_; | ||
} | ||
|
||
private: | ||
|
||
std::shared_ptr<RefCountedPointer<T>> parent_; | ||
T* const ptr_; | ||
}; | ||
|
||
/** | ||
* @brief Ensure no more valid local pointer instances are created, and wait for current ones to die. | ||
*/ | ||
void deactivate() | ||
{ | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
is_active_ = false; | ||
cv_.wait(lock, [this]() -> bool | ||
{ | ||
return instances_ == 0; | ||
}); | ||
} | ||
|
||
private: | ||
|
||
/** | ||
* @brief Increase the reference count. | ||
*/ | ||
void inc_instances() | ||
{ | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
++instances_; | ||
} | ||
|
||
/** | ||
* @brief Decrease the reference count. | ||
*/ | ||
void dec_instances() | ||
{ | ||
std::unique_lock<std::mutex> lock(mutex_); | ||
--instances_; | ||
if (instances_ == 0) | ||
{ | ||
cv_.notify_one(); | ||
} | ||
} | ||
|
||
/** | ||
* Pointer to the managed object. | ||
*/ | ||
T* const ptr_; | ||
|
||
/** | ||
* Indicates whether the pointee is still alive | ||
* and accessing the pointer is valid. | ||
*/ | ||
std::atomic<bool> is_active_; | ||
|
||
/** | ||
* Protections for the number of instances. | ||
*/ | ||
mutable std::mutex mutex_; | ||
std::condition_variable cv_; | ||
|
||
/** | ||
* Number of active instances (currently using the pointee). | ||
*/ | ||
size_t instances_; | ||
}; | ||
|
||
} // namespace fastdds | ||
} // namespace eprosima | ||
|
||
#endif // DOXYGEN_SHOULD_SKIP_THIS_PUBLIC | ||
|
||
#endif // UTILS__REFCOUNTEDPOINTER_HPP |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.