diff -pruN 2.7.0+ds-2/CMakeLists.txt 2.7.1+ds-1/CMakeLists.txt
--- 2.7.0+ds-2/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -30,7 +30,7 @@ endif()
 ###############################################################################
 # Project                                                                     #
 ###############################################################################
-project(fastrtps VERSION "2.7.0" LANGUAGES C CXX)
+project(fastrtps VERSION "2.7.1" LANGUAGES C CXX)
 
 set(PROJECT_NAME_LARGE "Fast RTPS")
 string(TOUPPER "${PROJECT_NAME}" PROJECT_NAME_UPPER)
@@ -62,7 +62,8 @@ if(MSVC OR MSVC_IDE)
     # C4555  expression has no effect; expected expression with side-effect
     # C4715: 'Test': not all control paths return a value
     # C5038 data member 'member1' will be initialized after data member 'member2'
-    add_compile_options(/w34101 /w34189 /w34555 /w34715 /w35038)
+    # C4100 'identifier' : unreferenced formal parameter (matches clang -Wunused-lambda-capture)
+    add_compile_options(/w34101 /w34189 /w34555 /w34715 /w35038 /w44100)
 
     if(EPROSIMA_BUILD)
         string(REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
@@ -206,6 +207,15 @@ endif()
 
 option(SQLITE3_SUPPORT "Activate SQLITE3 support" ON)
 
+option(USE_THIRDPARTY_SHARED_MUTEX [=[
+Forces the use of a Boost-based shared_mutex implementation
+instead of the framework one. Useful to cope with issues on
+framework implementations like misguided sanitizer reports.
+This implementation will be used by default on frameworks
+lacking the shared_mutex feature like those not fulfilling
+C++17.
+]=] OFF)
+
 ###############################################################################
 # SHM as Default transport
 ###############################################################################
@@ -402,13 +412,13 @@ if(BUILD_DOCUMENTATION)
 
         file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/readthedocs_custom_template.cmake [=[
 
-            file(DOWNLOAD "https://fast-dds.docs.eprosima.com/_/downloads/en/v${PROJECT_VERSION}/htmlzip/" "eprosima-fast-rtps.zip")
+            file(DOWNLOAD "https://fast-dds.docs.eprosima.com/_/downloads/en/v${PROJECT_VERSION}/htmlzip/" "./eprosima-fast-rtps.zip")
             # TODO: when windows ci CMake version surpasses 17 favor file() instead of UNZIP as in the next line
-            # file(ARCHIVE_EXTRACT INPUT "eprosima-fast-rtps.zip" DESTINATION  "${PROJECT_BINARY_DIR}/doc/")
-            execute_process(COMMAND "${UNZIP_EXE}" "eprosima-fast-rtps.zip" -d "${PROJECT_BINARY_DIR}/doc/")
+            # file(ARCHIVE_EXTRACT INPUT "./eprosima-fast-rtps.zip" DESTINATION  "${PROJECT_BINARY_DIR}/doc/")
+            execute_process(COMMAND "${UNZIP_EXE}" "./eprosima-fast-rtps.zip" -d "${PROJECT_BINARY_DIR}/doc/")
             file(REMOVE_RECURSE "${PROJECT_BINARY_DIR}/doc/manual")
             file(RENAME "${PROJECT_BINARY_DIR}/doc/eprosima-fast-rtps-v${PROJECT_VERSION}" "${PROJECT_BINARY_DIR}/doc/manual")
-            file(REMOVE  "eprosima-fast-rtps.zip")
+            file(REMOVE  "./eprosima-fast-rtps.zip")
 
             ]=])
 
diff -pruN 2.7.0+ds-2/debian/changelog 2.7.1+ds-1/debian/changelog
--- 2.7.0+ds-2/debian/changelog	2022-07-09 18:24:35.000000000 +0000
+++ 2.7.1+ds-1/debian/changelog	2022-07-30 18:40:50.000000000 +0000
@@ -1,3 +1,9 @@
+fastdds (2.7.1+ds-1) unstable; urgency=medium
+
+  * New upstream version 2.7.1+ds
+
+ -- Timo Röhling <roehling@debian.org>  Sat, 30 Jul 2022 20:40:50 +0200
+
 fastdds (2.7.0+ds-2) unstable; urgency=medium
 
   * Upload to unstable.
diff -pruN 2.7.0+ds-2/debian/patches/0001-Do-not-download-the-readthedocs-manual.patch 2.7.1+ds-1/debian/patches/0001-Do-not-download-the-readthedocs-manual.patch
--- 2.7.0+ds-2/debian/patches/0001-Do-not-download-the-readthedocs-manual.patch	2022-07-07 21:18:07.000000000 +0000
+++ 2.7.1+ds-1/debian/patches/0001-Do-not-download-the-readthedocs-manual.patch	2022-07-30 18:39:51.000000000 +0000
@@ -8,10 +8,10 @@ Forwarded: not-needed
  1 file changed, 42 deletions(-)
 
 diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 1205e93..7cc7308 100644
+index ec0e719..8b744f3 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
-@@ -354,15 +354,6 @@ if(BUILD_DOCUMENTATION)
+@@ -364,15 +364,6 @@ if(BUILD_DOCUMENTATION)
          set(DOXYFILE_MAKE make.bat)
      endif()
  
@@ -27,7 +27,7 @@ index 1205e93..7cc7308 100644
      # Target to create documentation directories
      add_custom_target(docdirs
          COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/doc
-@@ -397,37 +388,10 @@ if(BUILD_DOCUMENTATION)
+@@ -407,37 +398,10 @@ if(BUILD_DOCUMENTATION)
  
      configure_file(doc/README.html.in ${README_LOCATION}/README.html @ONLY IMMEDIATE)
  
@@ -36,13 +36,13 @@ index 1205e93..7cc7308 100644
 -
 -        file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/readthedocs_custom_template.cmake [=[
 -
--            file(DOWNLOAD "https://fast-dds.docs.eprosima.com/_/downloads/en/v${PROJECT_VERSION}/htmlzip/" "eprosima-fast-rtps.zip")
+-            file(DOWNLOAD "https://fast-dds.docs.eprosima.com/_/downloads/en/v${PROJECT_VERSION}/htmlzip/" "./eprosima-fast-rtps.zip")
 -            # TODO: when windows ci CMake version surpasses 17 favor file() instead of UNZIP as in the next line
--            # file(ARCHIVE_EXTRACT INPUT "eprosima-fast-rtps.zip" DESTINATION  "${PROJECT_BINARY_DIR}/doc/")
--            execute_process(COMMAND "${UNZIP_EXE}" "eprosima-fast-rtps.zip" -d "${PROJECT_BINARY_DIR}/doc/")
+-            # file(ARCHIVE_EXTRACT INPUT "./eprosima-fast-rtps.zip" DESTINATION  "${PROJECT_BINARY_DIR}/doc/")
+-            execute_process(COMMAND "${UNZIP_EXE}" "./eprosima-fast-rtps.zip" -d "${PROJECT_BINARY_DIR}/doc/")
 -            file(REMOVE_RECURSE "${PROJECT_BINARY_DIR}/doc/manual")
 -            file(RENAME "${PROJECT_BINARY_DIR}/doc/eprosima-fast-rtps-v${PROJECT_VERSION}" "${PROJECT_BINARY_DIR}/doc/manual")
--            file(REMOVE  "eprosima-fast-rtps.zip")
+-            file(REMOVE  "./eprosima-fast-rtps.zip")
 -
 -            ]=])
 -
@@ -65,7 +65,7 @@ index 1205e93..7cc7308 100644
  endif()
  
  ###############################################################################
-@@ -474,10 +438,4 @@ if(BUILD_DOCUMENTATION)
+@@ -484,10 +448,4 @@ if(BUILD_DOCUMENTATION)
          COMPONENT documentation
          )
  
diff -pruN 2.7.0+ds-2/debian/patches/0003-Fix-CMake-config-installation-path.patch 2.7.1+ds-1/debian/patches/0003-Fix-CMake-config-installation-path.patch
--- 2.7.0+ds-2/debian/patches/0003-Fix-CMake-config-installation-path.patch	2022-07-07 21:18:07.000000000 +0000
+++ 2.7.1+ds-1/debian/patches/0003-Fix-CMake-config-installation-path.patch	2022-07-30 18:39:51.000000000 +0000
@@ -8,7 +8,7 @@ Forwarded: not-needed
  1 file changed, 1 insertion(+), 5 deletions(-)
 
 diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
-index 675d055..a41e899 100644
+index 163358f..7b1f25f 100644
 --- a/src/cpp/CMakeLists.txt
 +++ b/src/cpp/CMakeLists.txt
 @@ -573,11 +573,7 @@ install(TARGETS ${PROJECT_NAME} eProsima_atomic
diff -pruN 2.7.0+ds-2/debian/patches/0005-Use-system-sqlite3.patch 2.7.1+ds-1/debian/patches/0005-Use-system-sqlite3.patch
--- 2.7.0+ds-2/debian/patches/0005-Use-system-sqlite3.patch	2022-07-07 21:18:07.000000000 +0000
+++ 2.7.1+ds-1/debian/patches/0005-Use-system-sqlite3.patch	2022-07-30 18:39:51.000000000 +0000
@@ -15,10 +15,10 @@ Forwarded: not-needed
  create mode 100644 cmake/modules/Findsqlite3.cmake
 
 diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 7cc7308..1f01e22 100644
+index 8b744f3..7f5844d 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
-@@ -166,6 +166,7 @@ eprosima_find_thirdparty(TinyXML2 tinyxml2)
+@@ -167,6 +167,7 @@ eprosima_find_thirdparty(TinyXML2 tinyxml2)
  find_package(foonathan_memory REQUIRED)
  message(STATUS "Found foonathan_memory: ${foonathan_memory_DIR}")
  find_package(ThirdpartyBoost REQUIRED)
@@ -39,7 +39,7 @@ index 0000000..2471bdb
 +
 +find_package_handle_standard_args(sqlite3 DEFAULT_MSG sqlite3_INCLUDE_DIRS sqlite3_LIBRARIES)
 diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
-index a41e899..00c382d 100644
+index 7b1f25f..16b804d 100644
 --- a/src/cpp/CMakeLists.txt
 +++ b/src/cpp/CMakeLists.txt
 @@ -327,7 +327,6 @@ endif()
diff -pruN 2.7.0+ds-2/debian/patches/0006-Use-system-nlohmann_json.patch 2.7.1+ds-1/debian/patches/0006-Use-system-nlohmann_json.patch
--- 2.7.0+ds-2/debian/patches/0006-Use-system-nlohmann_json.patch	2022-07-07 21:18:07.000000000 +0000
+++ 2.7.1+ds-1/debian/patches/0006-Use-system-nlohmann_json.patch	2022-07-30 18:39:51.000000000 +0000
@@ -23,10 +23,10 @@ Forwarded: not-needed
  16 files changed, 16 insertions(+), 15 deletions(-)
 
 diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 1f01e22..6af7ae2 100644
+index 7f5844d..336cc1c 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
-@@ -174,7 +174,7 @@ if(ANDROID)
+@@ -175,7 +175,7 @@ if(ANDROID)
      endif()
  endif()
  
@@ -36,7 +36,7 @@ index 1f01e22..6af7ae2 100644
  
  ###############################################################################
 diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
-index 00c382d..48613f5 100644
+index 16b804d..7223fa7 100644
 --- a/src/cpp/CMakeLists.txt
 +++ b/src/cpp/CMakeLists.txt
 @@ -441,6 +441,7 @@ target_link_libraries(${PROJECT_NAME} ${PRIVACY} fastcdr foonathan_memory
diff -pruN 2.7.0+ds-2/debian/patches/0007-Use-system-taocpp-pegtl.patch 2.7.1+ds-1/debian/patches/0007-Use-system-taocpp-pegtl.patch
--- 2.7.0+ds-2/debian/patches/0007-Use-system-taocpp-pegtl.patch	2022-07-07 21:18:07.000000000 +0000
+++ 2.7.1+ds-1/debian/patches/0007-Use-system-taocpp-pegtl.patch	2022-07-30 18:39:51.000000000 +0000
@@ -14,10 +14,10 @@ Subject: Use system taocpp-pegtl
  8 files changed, 10 insertions(+), 9 deletions(-)
 
 diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 6af7ae2..3bb2e83 100644
+index 336cc1c..7e87701 100644
 --- a/CMakeLists.txt
 +++ b/CMakeLists.txt
-@@ -176,6 +176,7 @@ endif()
+@@ -177,6 +177,7 @@ endif()
  
  find_package(nlohmann_json REQUIRED)
  include_directories(thirdparty/filewatch)
@@ -26,7 +26,7 @@ index 6af7ae2..3bb2e83 100644
  ###############################################################################
  # Options
 diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
-index 48613f5..e50b218 100644
+index 7223fa7..10c444f 100644
 --- a/src/cpp/CMakeLists.txt
 +++ b/src/cpp/CMakeLists.txt
 @@ -420,7 +420,6 @@ target_include_directories(${PROJECT_NAME} PUBLIC
@@ -87,7 +87,7 @@ index 7779743..3f45bdc 100644
  #include "DDSFilterField.hpp"
  #include "DDSFilterValue.hpp"
 diff --git a/test/unittest/dds/publisher/CMakeLists.txt b/test/unittest/dds/publisher/CMakeLists.txt
-index da31aa1..3e34ad1 100644
+index d786e0f..efeaae5 100644
 --- a/test/unittest/dds/publisher/CMakeLists.txt
 +++ b/test/unittest/dds/publisher/CMakeLists.txt
 @@ -304,10 +304,10 @@ target_compile_definitions(PublisherTests PRIVATE FASTRTPS_NO_LIB
@@ -115,10 +115,10 @@ index da31aa1..3e34ad1 100644
      ${TINYXML2_LIBRARY}
      $<$<BOOL:${LINK_SSL}>:OpenSSL::SSL$<SEMICOLON>OpenSSL::Crypto>
 diff --git a/test/unittest/dds/status/CMakeLists.txt b/test/unittest/dds/status/CMakeLists.txt
-index 2cb872f..3930bc4 100644
+index 626ef35..3376923 100644
 --- a/test/unittest/dds/status/CMakeLists.txt
 +++ b/test/unittest/dds/status/CMakeLists.txt
-@@ -175,12 +175,12 @@ target_include_directories(ListenerTests PRIVATE
+@@ -177,12 +177,12 @@ target_include_directories(ListenerTests PRIVATE
      ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include
      ${PROJECT_SOURCE_DIR}/src/cpp
      ${THIRDPARTY_BOOST_INCLUDE_DIR}
diff -pruN 2.7.0+ds-2/debian/patches/0009-Use-freshly-generated-snakeoil-certificates.patch 2.7.1+ds-1/debian/patches/0009-Use-freshly-generated-snakeoil-certificates.patch
--- 2.7.0+ds-2/debian/patches/0009-Use-freshly-generated-snakeoil-certificates.patch	2022-07-07 21:18:07.000000000 +0000
+++ 2.7.1+ds-1/debian/patches/0009-Use-freshly-generated-snakeoil-certificates.patch	2022-07-30 18:39:51.000000000 +0000
@@ -19,10 +19,10 @@ Forwarded: not-needed
  12 files changed, 37 insertions(+), 37 deletions(-)
 
 diff --git a/test/blackbox/CMakeLists.txt b/test/blackbox/CMakeLists.txt
-index cbf50eb..88e9b23 100644
+index 45932ec..e35695c 100644
 --- a/test/blackbox/CMakeLists.txt
 +++ b/test/blackbox/CMakeLists.txt
-@@ -359,7 +359,7 @@ if(FASTRTPS_API_TESTS)
+@@ -361,7 +361,7 @@ if(FASTRTPS_API_TESTS)
          )
         
      add_blackbox_gtest(BlackboxTests_FastRTPS SOURCES ${BLACKBOXTESTS_TEST_SOURCE}
@@ -31,7 +31,7 @@ index cbf50eb..88e9b23 100644
          "TOPIC_RANDOM_NUMBER=${TOPIC_RANDOM_NUMBER}"
          "W_UNICAST_PORT_RANDOM_NUMBER=${W_UNICAST_PORT_RANDOM_NUMBER}"
          "R_UNICAST_PORT_RANDOM_NUMBER=${R_UNICAST_PORT_RANDOM_NUMBER}"
-@@ -406,7 +406,7 @@ if(FASTDDS_PIM_API_TESTS)
+@@ -408,7 +408,7 @@ if(FASTDDS_PIM_API_TESTS)
          $<$<BOOL:${LibP11_FOUND}>:eProsima_p11>  # $<TARGET_NAME_IF_EXISTS:eProsima_p11>
          )
      add_blackbox_gtest(BlackboxTests_DDS_PIM SOURCES ${DDS_BLACKBOXTESTS_SOURCE}
@@ -182,7 +182,7 @@ index b54f935..b81c270 100644
  endif()
  
 diff --git a/test/unittest/dds/publisher/CMakeLists.txt b/test/unittest/dds/publisher/CMakeLists.txt
-index 3e34ad1..979a09e 100644
+index efeaae5..dd92e51 100644
 --- a/test/unittest/dds/publisher/CMakeLists.txt
 +++ b/test/unittest/dds/publisher/CMakeLists.txt
 @@ -354,4 +354,4 @@ if(MSVC OR MSVC_IDE)
diff -pruN 2.7.0+ds-2/debian/patches/0011-Do-not-import-fast-server-discovery-target.patch 2.7.1+ds-1/debian/patches/0011-Do-not-import-fast-server-discovery-target.patch
--- 2.7.0+ds-2/debian/patches/0011-Do-not-import-fast-server-discovery-target.patch	2022-07-07 21:18:07.000000000 +0000
+++ 2.7.1+ds-1/debian/patches/0011-Do-not-import-fast-server-discovery-target.patch	2022-07-30 18:39:51.000000000 +0000
@@ -7,7 +7,7 @@ Subject: Do not import fast-server-disco
  1 file changed, 5 deletions(-)
 
 diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt
-index e50b218..251167b 100644
+index 10c444f..dd6c9fc 100644
 --- a/src/cpp/CMakeLists.txt
 +++ b/src/cpp/CMakeLists.txt
 @@ -625,11 +625,6 @@ endif()
diff -pruN 2.7.0+ds-2/fastrtps.repos 2.7.1+ds-1/fastrtps.repos
--- 2.7.0+ds-2/fastrtps.repos	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/fastrtps.repos	2022-07-28 07:22:18.000000000 +0000
@@ -10,7 +10,7 @@ repositories:
     fastrtps:
         type: git
         url: https://github.com/eProsima/Fast-DDS.git
-        version: v2.7.0
+        version: v2.7.1
     fastddsgen:
         type: git
         url: https://github.com/eProsima/Fast-DDS-Gen.git
diff -pruN 2.7.0+ds-2/.github/workflows/thread-sanitizer.yaml 2.7.1+ds-1/.github/workflows/thread-sanitizer.yaml
--- 2.7.0+ds-2/.github/workflows/thread-sanitizer.yaml	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/.github/workflows/thread-sanitizer.yaml	2022-07-28 07:22:18.000000000 +0000
@@ -1,12 +1,23 @@
 name: Thread Sanitizer analysis
 on:
   workflow_dispatch:
+
   push:
     branches:
-      - 'feature/tsan/fixes'
+      - 'master'
+    paths-ignore:
+      - '**.md'
+      - '**.txt'
+      - '!**/CMakeLists.txt'
+
   pull_request:
     branches:
-      - 'feature/tsan/fixes'
+      - 'master'
+    paths-ignore:
+      - '**.md'
+      - '**.txt'
+      - '!**/CMakeLists.txt'
+
 env:
   TSAN_OPTIONS: second_deadlock_stack=1
   # ubuntu host doesn't have an environment SHELL value (docker and vm images does)???
@@ -19,6 +30,8 @@ defaults:
 jobs:
   ubuntu-sanitizer-run:
     name: Sanitizer Evaluation
+    if: ${{ !(contains(github.event.pull_request.labels.*.name, 'no-test') ||
+              contains(github.event.pull_request.labels.*.name, 'skip-ci')) }}
     runs-on: ubuntu-latest
     steps:
       - name: Download the sanitizers cmake module and apply some fixes
@@ -35,7 +48,7 @@ jobs:
       - name: Download googletest and make it sanitizer aware
         run: |
           cd ws
-          git clone https://github.com/google/googletest.git
+          git clone --branch release-1.11.0 https://github.com/google/googletest.git
           cd googletest
           git remote add efork https://github.com/MiguelBarro/googletest.git
           git fetch efork
@@ -46,7 +59,7 @@ jobs:
           cd ws
           cmake -DCMAKE_MODULE_PATH="$(pwd)/sanitizers-cmake/cmake" -DCMAKE_INSTALL_PREFIX="./install" `
                 -DBUILD_GMOCK=ON -DSANITIZE_THREAD=ON -DCMAKE_BUILD_TYPE=Debug `
-                -DCMAKE_VERBOSE_MAKEFILE=ON -B ./build/googletest ./googletest 
+                -DCMAKE_VERBOSE_MAKEFILE=ON -B ./build/googletest ./googletest
           cmake --build ./build/googletest --target install --verbose
 
       - name: Download Fast-CDR and make it sanitizer aware
@@ -63,7 +76,7 @@ jobs:
           cd ws
           cmake -DCMAKE_INSTALL_PREFIX="./install" -DCMAKE_PREFIX_PATH="./install" `
                 -DCMAKE_MODULE_PATH="$(pwd)/sanitizers-cmake/cmake" -DCMAKE_VERBOSE_MAKEFILE=ON `
-                -DSANITIZE_THREAD=ON -DCMAKE_BUILD_TYPE=Debug -B ./build/fastcdr ./Fast-CDR 
+                -DSANITIZE_THREAD=ON -DCMAKE_BUILD_TYPE=Debug -B ./build/fastcdr ./Fast-CDR
           cmake --build ./build/fastcdr --target install --verbose
 
       - name: Download foonathan/memory and make it sanitizer aware
@@ -95,7 +108,7 @@ jobs:
           git diff --name-only HEAD~1
           git remote add efork https://github.com/MiguelBarro/Fast-DDS.git
           git fetch efork
-          git merge --no-edit efork/bugfix/add_sanitizer_support | Out-Null
+          git merge --no-edit efork/bugfix/add_sanitizer_support
 
       - name: Build & install Fast-DDS
         run: |
@@ -107,7 +120,9 @@ jobs:
                 -DCMAKE_BUILD_TYPE=Debug -B ./build/fastdds ./Fast-DDS
           # Create a symlink to the reports folder
           $report_dir = gci -Path ./build/fastdds -Attributes D |
-            ? Name -like "$(Get-Date -Format 'MMMM-dd-yyyy')*" 
+            ? Name -like "$(Get-Date -Format 'MMMM-dd-yyyy')*"
+          $report_dir = Join-Path $report_dir tsan | gi
+          echo "report folder is: $report_dir"
           New-Item -ItemType SymbolicLink -Target $report_dir -Path ./build/fastdds/reports
           cmake --build ./build/fastdds --target install -j 2 --verbose
 
@@ -116,9 +131,11 @@ jobs:
           cd ws/build/fastdds
           ctest --timeout 30 -j 2 -V
           # ctest fails if sanitizer reports are present
-          $LASTEXITCODE=0 
+          $LASTEXITCODE=0
 
       - name: Process sanitizer reports
+        id: report_summary
+        continue-on-error: true
         run: |
           # Create a dir for the exports
           $exports = New-Item -ItemType Directory -Path ./ws/exports
@@ -127,7 +144,7 @@ jobs:
           # Install the report parser module
           Find-Module -Repository PSGallery -Name SanReportParser | Install-Module -Scope CurrentUser -Force
           # Parse the report files
-          $rp = Show-Tsan (gci) 
+          $rp = Show-Tsan (gci)
           # filter duplicates
           $rp = $rp | group md5hash | % { $_.group[0] }
           # Export raw data
@@ -135,8 +152,8 @@ jobs:
           # Group the reports by issue
           $g = $rp | group fuzzhash
           # Split up deadlocks and race reports
-          $gd = $rp | ? type -match dead | group fuzzhash 
-          $gr = $rp | ? type -match race | group fuzzhash 
+          $gd = $rp | ? type -match dead | group fuzzhash
+          $gr = $rp | ? type -match race | group fuzzhash
           # Simplified deadlock summary (only one representative report and tests associated)
           $sd = $gd | Sort-Object count -desc | select @{l="fuzzhash";e="name"}, count, `
               @{l="échantillon";e={$_.group[0].report}}, @{l="tests"; `
@@ -157,12 +174,26 @@ jobs:
           # Keep a file per issue
           $dir = New-Item -ItemType Directory -Path (Join-Path $exports reports)
           & {$sd; $sr} | % { $_.échantillon | Out-File (Join-Path $dir "$($_.fuzzhash).tsan") }
-          # Zip an artifact
-          popd
-          gci $exports | Compress-Archive -DestinationPath ./ws/tsan_reports.zip 
+          # Create a summary table
+          @{Type="Deadlock";Failed=$sd.count;Hashes=$sd.fuzzhash},
+          @{Type="Data race";Failed=$sr.count;Hashes=$sr.fuzzhash} |
+            % { $_.Summary = $_.Hashes | select -First 5  | Join-String -Separator ", "
+                if ($_.Hashes.count -gt 5 ) {
+                    $_.Summary += ", ..." }; $_ } |
+              % { [PSCustomObject]$_} |
+              New-MDTable -Columns ([ordered]@{Failed=$null;Type=$null;Summary=$null}) |
+              Out-File $Env:GITHUB_STEP_SUMMARY
+          # The step fails on new deadlocks
+          $LASTEXITCODE=$sd.count
 
       - name: Archive sanitation results
         uses: actions/upload-artifact@v3
         with:
-            name: sanitation-report
-            path: /home/runner/work/ws/tsan_reports.zip
+          name: sanitation-report
+          path: /home/runner/work/ws/exports/*
+
+      - name: Check on failures
+        if: ${{ steps.report_summary.outcome == 'failure' }}
+        run: |
+          Write-Host ${{ steps.report_summary.outcome }}
+          exit 1
diff -pruN 2.7.0+ds-2/include/fastdds/dds/domain/DomainParticipant.hpp 2.7.1+ds-1/include/fastdds/dds/domain/DomainParticipant.hpp
--- 2.7.0+ds-2/include/fastdds/dds/domain/DomainParticipant.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/domain/DomainParticipant.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -348,6 +348,7 @@ public:
      * @param a_multitopic MultiTopic to be deleted
      * @return RETCODE_BAD_PARAMETER if the topic passed is a nullptr, RETCODE_PRECONDITION_NOT_MET if the topic does not belong to
      * this participant or if it is referenced by any entity and RETCODE_OK if the Topic was deleted.
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t delete_multitopic(
             const MultiTopic* a_multitopic);
@@ -395,6 +396,7 @@ public:
      *
      * @param handle Identifier of the remote participant to ignore
      * @return RETURN_OK code if everything correct, error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t ignore_participant(
             const InstanceHandle_t& handle);
@@ -406,6 +408,7 @@ public:
      *
      * @param handle Identifier of the topic to ignore
      * @return RETURN_OK code if everything correct, error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t ignore_topic(
             const InstanceHandle_t& handle);
@@ -417,6 +420,7 @@ public:
      *
      * @param handle Identifier of the datawriter to ignore
      * @return RETURN_OK code if everything correct, error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t ignore_publication(
             const InstanceHandle_t& handle);
@@ -428,6 +432,7 @@ public:
      *
      * @param handle Identifier of the datareader to ignore
      * @return RETURN_OK code if everything correct, error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t ignore_subscription(
             const InstanceHandle_t& handle);
@@ -631,6 +636,7 @@ public:
      *
      * @param[out]  participant_handles Reference to the vector where discovered participants will be returned
      * @return RETCODE_OK if everything correct, error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_discovered_participants(
             std::vector<InstanceHandle_t>& participant_handles) const;
@@ -641,6 +647,7 @@ public:
      * @param[out]  participant_data Reference to the ParticipantBuiltinTopicData object to return the data
      * @param participant_handle InstanceHandle of DomainParticipant to retrieve the data from
      * @return RETCODE_OK if everything correct, PRECONDITION_NOT_MET if participant does not exist
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_discovered_participant_data(
             builtin::ParticipantBuiltinTopicData& participant_data,
@@ -651,6 +658,7 @@ public:
      *
      * @param[out]  topic_handles Reference to the vector where discovered topics will be returned
      * @return RETCODE_OK if everything correct, error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_discovered_topics(
             std::vector<InstanceHandle_t>& topic_handles) const;
@@ -661,6 +669,7 @@ public:
      * @param[out]  topic_data Reference to the TopicBuiltinTopicData object to return the data
      * @param topic_handle InstanceHandle of Topic to retrieve the data from
      * @return RETCODE_OK if everything correct, PRECONDITION_NOT_MET if topic does not exist
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_discovered_topic_data(
             builtin::TopicBuiltinTopicData& topic_data,
diff -pruN 2.7.0+ds-2/include/fastdds/dds/log/Log.hpp 2.7.1+ds-1/include/fastdds/dds/log/Log.hpp
--- 2.7.0+ds-2/include/fastdds/dds/log/Log.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/log/Log.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -115,7 +115,7 @@ public:
     //! Returns the logging engine to configuration defaults.
     RTPS_DllAPI static void Reset();
 
-    //! Waits until no more log info is available
+    //! Waits until all info logged up to the call time is consumed
     RTPS_DllAPI static void Flush();
 
     //! Stops the logging thread. It will re-launch on the next call to a successful log macro.
diff -pruN 2.7.0+ds-2/include/fastdds/dds/publisher/DataWriter.hpp 2.7.1+ds-1/include/fastdds/dds/publisher/DataWriter.hpp
--- 2.7.0+ds-2/include/fastdds/dds/publisher/DataWriter.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/publisher/DataWriter.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -514,7 +514,7 @@ public:
      * @param[out] subscription_data subscription data struct
      * @param subscription_handle InstanceHandle_t of the subscription
      * @return RETCODE_OK
-     *
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_matched_subscription_data(
             builtin::SubscriptionBuiltinTopicData& subscription_data,
@@ -525,6 +525,7 @@ public:
      *
      * @param[out] subscription_handles Vector where the InstanceHandle_t are returned
      * @return RETCODE_OK
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_matched_subscriptions(
             std::vector<InstanceHandle_t>& subscription_handles) const;
diff -pruN 2.7.0+ds-2/include/fastdds/dds/publisher/Publisher.hpp 2.7.1+ds-1/include/fastdds/dds/publisher/Publisher.hpp
--- 2.7.0+ds-2/include/fastdds/dds/publisher/Publisher.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/publisher/Publisher.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -213,6 +213,7 @@ public:
      * @brief Indicates to FastDDS that the contained DataWriters are about to be modified
      *
      * @return RETCODE_OK if successful, an error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t suspend_publications();
 
@@ -220,6 +221,7 @@ public:
      * @brief Indicates to FastDDS that the modifications to the DataWriters are complete.
      *
      * @return RETCODE_OK if successful, an error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t resume_publications();
 
@@ -227,6 +229,7 @@ public:
      * @brief Signals the beginning of a set of coherent cache changes using the Datawriters attached to the publisher
      *
      * @return RETCODE_OK if successful, an error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t begin_coherent_changes();
 
@@ -234,6 +237,7 @@ public:
      * @brief Signals the end of a set of coherent cache changes
      *
      * @return RETCODE_OK if successful, an error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t end_coherent_changes();
 
@@ -314,6 +318,7 @@ public:
      * @param[out] writer_qos
      * @param[in] topic_qos
      * @return RETCODE_OK if successful, an error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t copy_from_topic_qos(
             fastdds::dds::DataWriterQos& writer_qos,
diff -pruN 2.7.0+ds-2/include/fastdds/dds/subscriber/DataReader.hpp 2.7.1+ds-1/include/fastdds/dds/subscriber/DataReader.hpp
--- 2.7.0+ds-2/include/fastdds/dds/subscriber/DataReader.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/subscriber/DataReader.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -136,6 +136,7 @@ public:
      *
      * @param[in] max_wait Max blocking time for this operation.
      * @return RETCODE_OK if there is new unread message, ReturnCode_t::RETCODE_TIMEOUT if timeout
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t wait_for_historical_data(
             const fastrtps::Duration_t& max_wait) const;
@@ -771,6 +772,7 @@ public:
      * @param[in] handle
      *
      * @return Any of the standard return codes.
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_key_value(
             void* key_holder,
@@ -810,6 +812,16 @@ public:
     RTPS_DllAPI uint64_t get_unread_count() const;
 
     /**
+     * Get the number of samples pending to be read.
+     *
+     * @param mark_as_read  Whether the unread samples should be marked as read or not.
+     *
+     * @return the number of samples on the reader history that have never been read.
+     */
+    RTPS_DllAPI uint64_t get_unread_count(
+            bool mark_as_read) const;
+
+    /**
      * Get associated GUID.
      *
      * @return Associated GUID
@@ -970,7 +982,7 @@ public:
      * @param[out] publication_data publication data struct
      * @param publication_handle InstanceHandle_t of the publication
      * @return RETCODE_OK
-     *
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_matched_publication_data(
             builtin::PublicationBuiltinTopicData& publication_data,
@@ -981,6 +993,7 @@ public:
      *
      * @param[out] publication_handles Vector where the InstanceHandle_t are returned
      * @return RETCODE_OK
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_matched_publications(
             std::vector<InstanceHandle_t>& publication_handles) const;
@@ -1026,7 +1039,7 @@ public:
      * @return RETCODE_OK
      */
     RTPS_DllAPI ReturnCode_t delete_readcondition(
-            const ReadCondition* a_condition);
+            ReadCondition* a_condition);
 
     /**
      * @brief Getter for the Subscriber
diff -pruN 2.7.0+ds-2/include/fastdds/dds/subscriber/ReadCondition.hpp 2.7.1+ds-1/include/fastdds/dds/subscriber/ReadCondition.hpp
--- 2.7.0+ds-2/include/fastdds/dds/subscriber/ReadCondition.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/subscriber/ReadCondition.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -19,6 +19,8 @@
 #ifndef _FASTDDS_DDS_SUBSCRIBER_READCONDITION_HPP_
 #define _FASTDDS_DDS_SUBSCRIBER_READCONDITION_HPP_
 
+#include <cassert>
+
 #include <fastdds/dds/core/condition/Condition.hpp>
 #include <fastdds/dds/subscriber/InstanceState.hpp>
 #include <fastdds/dds/subscriber/SampleState.hpp>
@@ -31,7 +33,7 @@ namespace dds {
 
 namespace detail {
 
-struct ReadConditionImpl;
+class ReadConditionImpl;
 
 } // namespace detail
 
@@ -48,10 +50,11 @@ class DataReader;
  */
 class ReadCondition : public Condition
 {
+    friend class detail::ReadConditionImpl;
+
 public:
 
-    explicit ReadCondition(
-            DataReader* parent);
+    ReadCondition();
 
     ~ReadCondition() override;
 
@@ -71,7 +74,7 @@ public:
      * @brief Retrieves the trigger_value of the Condition
      * @return true if trigger_value is set to 'true', 'false' otherwise
      */
-    RTPS_DllAPI bool get_trigger_value() const override;
+    RTPS_DllAPI bool get_trigger_value() const noexcept override;
 
     /**
      * @brief Retrieves the DataReader associated with the ReadCondition.
@@ -80,38 +83,39 @@ public:
      *
      * @return pointer to the DataReader associated with this ReadCondition.
      */
-    RTPS_DllAPI DataReader* get_datareader() const;
+    RTPS_DllAPI DataReader* get_datareader() const noexcept;
 
     /**
      * @brief Retrieves the set of sample_states taken into account to determine the trigger_value of this condition.
      *
      * @return the sample_states specified when the ReadCondition was created.
      */
-    RTPS_DllAPI SampleStateMask get_sample_state_mask() const;
+    RTPS_DllAPI SampleStateMask get_sample_state_mask() const noexcept;
 
     /**
      * @brief Retrieves the set of view_states taken into account to determine the trigger_value of this condition.
      *
      * @return the view_states specified when the ReadCondition was created.
      */
-    RTPS_DllAPI ViewStateMask get_view_state_mask() const;
+    RTPS_DllAPI ViewStateMask get_view_state_mask() const noexcept;
 
     /**
      * @brief Retrieves the set of instance_states taken into account to determine the trigger_value of this condition.
      *
      * @return the instance_states specified when the ReadCondition was created.
      */
-    RTPS_DllAPI InstanceStateMask get_instance_state_mask() const;
+    RTPS_DllAPI InstanceStateMask get_instance_state_mask() const noexcept;
 
-    detail::ReadConditionImpl* get_impl() const
+    detail::ReadConditionImpl* get_impl() const noexcept
     {
+        assert((bool)impl_);
         return impl_.get();
     }
 
 protected:
 
     //! Class implementation
-    std::unique_ptr<detail::ReadConditionImpl> impl_;
+    std::shared_ptr<detail::ReadConditionImpl> impl_;
 
 };
 
diff -pruN 2.7.0+ds-2/include/fastdds/dds/subscriber/Subscriber.hpp 2.7.1+ds-1/include/fastdds/dds/subscriber/Subscriber.hpp
--- 2.7.0+ds-2/include/fastdds/dds/subscriber/Subscriber.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/subscriber/Subscriber.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -230,6 +230,7 @@ public:
      * @param view_states Vector of ViewStateKind
      * @param instance_states Vector of InstanceStateKind
      * @return RETCODE_OK
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t get_datareaders(
             std::vector<DataReader*>& readers,
@@ -249,6 +250,7 @@ public:
      * attached to the Subscriber.
      *
      * @return RETCODE_OK
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t begin_access();
 
@@ -257,6 +259,7 @@ public:
      * the Subscriber.
      *
      * @return RETCODE_OK
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI ReturnCode_t end_access();
 
@@ -353,6 +356,7 @@ public:
      * @param[in, out] reader_qos
      * @param[in] topic_qos
      * @return RETCODE_OK if successful, an error code otherwise
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     RTPS_DllAPI static ReturnCode_t copy_from_topic_qos(
             DataReaderQos& reader_qos,
diff -pruN 2.7.0+ds-2/include/fastdds/dds/topic/Topic.hpp 2.7.1+ds-1/include/fastdds/dds/topic/Topic.hpp
--- 2.7.0+ds-2/include/fastdds/dds/topic/Topic.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/dds/topic/Topic.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -89,6 +89,7 @@ public:
      *
      * @param status [out] Status to be retrieved.
      * @return RETCODE_OK
+     * @warning Not supported yet. Currently returns RETCODE_UNSUPPORTED
      */
     ReturnCode_t get_inconsistent_topic_status(
             InconsistentTopicStatus& status);
diff -pruN 2.7.0+ds-2/include/fastdds/rtps/history/History.h 2.7.1+ds-1/include/fastdds/rtps/history/History.h
--- 2.7.0+ds-2/include/fastdds/rtps/history/History.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/rtps/history/History.h	2022-07-28 07:22:18.000000000 +0000
@@ -253,7 +253,7 @@ public:
      * Get the mutex
      * @return Mutex
      */
-    RTPS_DllAPI inline RecursiveTimedMutex* getMutex()
+    RTPS_DllAPI inline RecursiveTimedMutex* getMutex() const
     {
         assert(mp_mutex != nullptr);
         return mp_mutex;
diff -pruN 2.7.0+ds-2/include/fastdds/rtps/history/ReaderHistory.h 2.7.1+ds-1/include/fastdds/rtps/history/ReaderHistory.h
--- 2.7.0+ds-2/include/fastdds/rtps/history/ReaderHistory.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/rtps/history/ReaderHistory.h	2022-07-28 07:22:18.000000000 +0000
@@ -221,10 +221,17 @@ protected:
         assert(nullptr != mp_mutex);
 
         std::lock_guard<RecursiveTimedMutex> guard(*mp_mutex);
-        std::vector<CacheChange_t*>::iterator new_end = std::remove_if(m_changes.begin(), m_changes.end(), pred);
-        while (new_end != m_changes.end())
+        std::vector<CacheChange_t*>::iterator chit = m_changes.begin();
+        while (chit != m_changes.end())
         {
-            new_end = remove_change_nts(new_end);
+            if (pred(*chit))
+            {
+                chit = remove_change_nts(chit);
+            }
+            else
+            {
+                ++chit;
+            }
         }
     }
 
diff -pruN 2.7.0+ds-2/include/fastdds/rtps/reader/RTPSReader.h 2.7.1+ds-1/include/fastdds/rtps/reader/RTPSReader.h
--- 2.7.0+ds-2/include/fastdds/rtps/reader/RTPSReader.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastdds/rtps/reader/RTPSReader.h	2022-07-28 07:22:18.000000000 +0000
@@ -238,6 +238,9 @@ public:
 
     RTPS_DllAPI uint64_t get_unread_count() const;
 
+    RTPS_DllAPI uint64_t get_unread_count(
+            bool mark_as_read);
+
     /**
      * @return True if the reader expects Inline QOS.
      */
diff -pruN 2.7.0+ds-2/include/fastrtps/config.h.in 2.7.1+ds-1/include/fastrtps/config.h.in
--- 2.7.0+ds-2/include/fastrtps/config.h.in	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastrtps/config.h.in	2022-07-28 07:22:18.000000000 +0000
@@ -62,6 +62,8 @@
 #define HAVE_SQLITE3 @HAVE_SQLITE3@
 #endif /* ifndef HAVE_SQLITE3 */
 
+// Using thirdparty shared_mutex
+#cmakedefine01 USE_THIRDPARTY_SHARED_MUTEX
 
 // TLS support
 #ifndef TLS_FOUND
diff -pruN 2.7.0+ds-2/include/fastrtps/utils/shared_mutex.hpp 2.7.1+ds-1/include/fastrtps/utils/shared_mutex.hpp
--- 2.7.0+ds-2/include/fastrtps/utils/shared_mutex.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastrtps/utils/shared_mutex.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -8,12 +8,23 @@
 #ifndef _UTILS_SHARED_MUTEX_HPP_
 #define _UTILS_SHARED_MUTEX_HPP_
 
+#ifndef USE_THIRDPARTY_SHARED_MUTEX
+#   if defined(_MSC_VER) && _MSVC_LANG < 202302L
+#       pragma message("warning: USE_THIRDPARTY_SHARED_MUTEX not defined. By default use framework version.")
+#   else
+#       warning "USE_THIRDPARTY_SHARED_MUTEX not defined. By default use framework version."
+#   endif // if defined(_MSC_VER) && _MSVC_LANG < 202302L
+#   define USE_THIRDPARTY_SHARED_MUTEX 0
+#endif // ifndef USE_THIRDPARTY_SHARED_MUTEX
+
 #if defined(__has_include) && __has_include(<version>)
 #   include <version>
 #endif // if defined(__has_include) && __has_include(<version>)
 
 // Detect if the share_mutex feature is available
 #if defined(__has_include) && __has_include(<version>) && !defined(__cpp_lib_shared_mutex) || \
+    /* allow users to ignore shared_mutex framework implementation */ \
+    (~USE_THIRDPARTY_SHARED_MUTEX + 1) || \
     /* deprecated procedure if the good one is not available*/ \
     ( !(defined(__has_include) && __has_include(<version>)) && \
     !(defined(HAVE_CXX17) && HAVE_CXX17) &&  __cplusplus < 201703 )
@@ -353,9 +364,8 @@ shared_lock<Mutex>::try_lock()
 
 namespace eprosima {
 
-using shared_mutex = std::shared_mutex;
-template< class Mutex >
-using shared_lock = std::shared_lock<Mutex>;
+using std::shared_mutex;
+using std::shared_lock;
 
 } //namespace eprosima
 
diff -pruN 2.7.0+ds-2/include/fastrtps/xmlparser/XMLEndpointParser.h 2.7.1+ds-1/include/fastrtps/xmlparser/XMLEndpointParser.h
--- 2.7.0+ds-2/include/fastrtps/xmlparser/XMLEndpointParser.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/include/fastrtps/xmlparser/XMLEndpointParser.h	2022-07-28 07:22:18.000000000 +0000
@@ -85,7 +85,8 @@ public:
     virtual ~XMLEndpointParser();
     /**
      * Load the XML file
-     * @param filename Name of the file to load and parse.
+     * @param filename Name or data of the file to load and parse.
+     * The string could contain a filename (file://) or the XML content directly (data://), filename assumed if neither
      * @return True if correct.
      */
     XMLP_ret loadXMLFile(
diff -pruN 2.7.0+ds-2/package.xml 2.7.1+ds-1/package.xml
--- 2.7.0+ds-2/package.xml	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/package.xml	2022-07-28 07:22:18.000000000 +0000
@@ -2,7 +2,7 @@
 <?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
 <package format="3">
   <name>fastrtps</name>
-  <version>2.7.0</version>
+  <version>2.7.1</version>
   <description>
      *eprosima Fast DDS* (formerly Fast RTPS) is a C++ implementation of the DDS (Data Distribution Service) standard of the OMG (Object Management Group). eProsima Fast DDS implements the RTPS (Real Time Publish Subscribe) protocol, which provides publisher-subscriber communications over unreliable transports such as UDP, as defined and maintained by the Object Management Group (OMG) consortium. RTPS is also the wire interoperability protocol defined for the Data Distribution Service (DDS) standard. *eProsima Fast DDS* expose an API to access directly the RTPS protocol, giving the user full access to the protocol internals.
   </description>
diff -pruN 2.7.0+ds-2/src/cpp/CMakeLists.txt 2.7.1+ds-1/src/cpp/CMakeLists.txt
--- 2.7.0+ds-2/src/cpp/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -565,10 +565,10 @@ endif()
 
 install(TARGETS ${PROJECT_NAME} eProsima_atomic
     EXPORT ${PROJECT_NAME}-${FASTDDS_LINKING}-targets
-    RUNTIME DESTINATION ${BIN_INSTALL_DIR}${MSVCARCH_DIR_EXTENSION}
-    LIBRARY DESTINATION ${LIB_INSTALL_DIR}${MSVCARCH_DIR_EXTENSION}
-    ARCHIVE DESTINATION ${LIB_INSTALL_DIR}${MSVCARCH_DIR_EXTENSION}
     COMPONENT libraries
+    RUNTIME DESTINATION "${BIN_INSTALL_DIR}${MSVCARCH_DIR_EXTENSION}"
+    LIBRARY DESTINATION "${LIB_INSTALL_DIR}${MSVCARCH_DIR_EXTENSION}"
+    ARCHIVE DESTINATION "${LIB_INSTALL_DIR}${MSVCARCH_DIR_EXTENSION}"
     )
 
 export(TARGETS ${PROJECT_NAME} eProsima_atomic FILE ${PROJECT_BINARY_DIR}/cmake/config/${PROJECT_NAME}-${FASTDDS_LINKING}-targets.cmake)
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/core/policy/ParameterSerializer.hpp 2.7.1+ds-1/src/cpp/fastdds/core/policy/ParameterSerializer.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/core/policy/ParameterSerializer.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/core/policy/ParameterSerializer.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -672,7 +672,7 @@ inline bool ParameterSerializer<Paramete
     //Nproperties_ = num_properties;
 
     uint32_t length_diff = cdr_message->pos - pos_ref;
-    valid &= (parameter_length == length_diff);
+    valid &= (parameter_length >= length_diff);
     return valid;
 }
 
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/domain/DomainParticipantFactory.cpp 2.7.1+ds-1/src/cpp/fastdds/domain/DomainParticipantFactory.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/domain/DomainParticipantFactory.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/domain/DomainParticipantFactory.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -26,6 +26,7 @@
 #include <fastrtps/types/DynamicTypeBuilderFactory.h>
 #include <fastrtps/types/TypeObjectFactory.h>
 #include <fastrtps/xmlparser/XMLProfileManager.h>
+#include <fastrtps/xmlparser/XMLEndpointParser.h>
 
 #include <fastdds/domain/DomainParticipantImpl.hpp>
 #include <rtps/history/TopicPayloadPoolRegistry.hpp>
@@ -418,10 +419,13 @@ ReturnCode_t DomainParticipantFactory::l
 ReturnCode_t DomainParticipantFactory::check_xml_static_discovery(
         std::string& xml_file)
 {
-    // Not suported yet
-    (void)xml_file;
-
-    return ReturnCode_t::RETCODE_UNSUPPORTED;
+    eprosima::fastrtps::xmlparser::XMLEndpointParser parser;
+    if (XMLP_ret::XML_OK != parser.loadXMLFile(xml_file))
+    {
+        logError(DOMAIN, "Error parsing xml file");
+        return ReturnCode_t::RETCODE_ERROR;
+    }
+    return ReturnCode_t::RETCODE_OK;
 }
 
 ReturnCode_t DomainParticipantFactory::get_qos(
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/domain/DomainParticipantImpl.cpp 2.7.1+ds-1/src/cpp/fastdds/domain/DomainParticipantImpl.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/domain/DomainParticipantImpl.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/domain/DomainParticipantImpl.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -534,13 +534,13 @@ ReturnCode_t DomainParticipantImpl::dele
     {
         auto it = topics_.find(topic->get_name());
         assert(it != topics_.end() && "Topic found by handle but factory not found");
+        InstanceHandle_t handle = topic->get_instance_handle();
 
         TopicProxy* proxy = dynamic_cast<TopicProxy*>(topic->get_impl());
         assert(nullptr != proxy);
         auto ret_code = it->second->delete_topic(proxy);
         if (ReturnCode_t::RETCODE_OK == ret_code)
         {
-            InstanceHandle_t handle = topic->get_instance_handle();
             topics_by_handle_.erase(handle);
 
             if (it->second->can_be_deleted())
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/log/Log.cpp 2.7.1+ds-1/src/cpp/fastdds/log/Log.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/log/Log.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/log/Log.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -107,6 +107,7 @@ void Log::Reset()
     resources_.functions = true;
     resources_.verbosity = Log::Error;
     resources_.consumers.clear();
+
 #if STDOUTERR_LOG_CONSUMER
     resources_.consumers.emplace_back(new StdoutErrConsumer);
 #else
@@ -174,15 +175,16 @@ void Log::run()
             {
                 std::unique_lock<std::mutex> configGuard(resources_.config_mutex);
 
-                // This value is moved and not copied
-                Entry value_dequeue = resources_.logs.FrontAndPop();
-                if (preprocess(value_dequeue))
+                Log::Entry& entry = resources_.logs.Front();
+                if (preprocess(entry))
                 {
                     for (auto& consumer : resources_.consumers)
                     {
-                        consumer->Consume(value_dequeue);
+                        consumer->Consume(entry);
                     }
                 }
+                // This Pop() is also a barrier for Log::Flush wait condition
+                resources_.logs.Pop();
             }
         }
         guard.lock();
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/publisher/DataWriterImpl.cpp 2.7.1+ds-1/src/cpp/fastdds/publisher/DataWriterImpl.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/publisher/DataWriterImpl.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/publisher/DataWriterImpl.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -1213,12 +1213,16 @@ void DataWriterImpl::InnerDataWriterList
         fastrtps::rtps::RTPSWriter* /*writer*/,
         const fastrtps::LivelinessLostStatus& status)
 {
+    data_writer_->update_liveliness_lost_status(status);
     StatusMask notify_status = StatusMask::liveliness_lost();
     DataWriterListener* listener = data_writer_->get_listener_for(notify_status);
     if (listener != nullptr)
     {
-        listener->on_liveliness_lost(
-            data_writer_->user_datawriter_, status);
+        LivelinessLostStatus callback_status;
+        if (ReturnCode_t::RETCODE_OK == data_writer_->get_liveliness_lost_status(callback_status))
+        {
+            listener->on_liveliness_lost(data_writer_->user_datawriter_, callback_status);
+        }
     }
     data_writer_->user_datawriter_->get_statuscondition().get_impl()->set_status(notify_status, true);
 }
@@ -1481,10 +1485,8 @@ ReturnCode_t DataWriterImpl::get_livelin
     {
         std::unique_lock<RecursiveTimedMutex> lock(writer_->getMutex());
 
-        status.total_count = writer_->liveliness_lost_status_.total_count;
-        status.total_count_change = writer_->liveliness_lost_status_.total_count_change;
-
-        writer_->liveliness_lost_status_.total_count_change = 0u;
+        status = liveliness_lost_status_;
+        liveliness_lost_status_.total_count_change = 0u;
     }
 
     user_datawriter_->get_statuscondition().get_impl()->set_status(StatusMask::liveliness_lost(), false);
@@ -1566,6 +1568,14 @@ OfferedIncompatibleQosStatus& DataWriter
     return offered_incompatible_qos_status_;
 }
 
+LivelinessLostStatus& DataWriterImpl::update_liveliness_lost_status(
+        const fastrtps::LivelinessLostStatus& liveliness_lost_status)
+{
+    liveliness_lost_status_.total_count = liveliness_lost_status.total_count;
+    liveliness_lost_status_.total_count_change += liveliness_lost_status.total_count_change;
+    return liveliness_lost_status_;
+}
+
 void DataWriterImpl::set_qos(
         DataWriterQos& to,
         const DataWriterQos& from,
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/publisher/DataWriterImpl.hpp 2.7.1+ds-1/src/cpp/fastdds/publisher/DataWriterImpl.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/publisher/DataWriterImpl.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/publisher/DataWriterImpl.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -466,7 +466,10 @@ protected:
     PublicationMatchedStatus publication_matched_status_;
 
     //! The offered deadline missed status
-    fastrtps::OfferedDeadlineMissedStatus deadline_missed_status_;
+    OfferedDeadlineMissedStatus deadline_missed_status_;
+
+    //! The liveliness lost status
+    LivelinessLostStatus liveliness_lost_status_;
 
     //! The offered incompatible qos status
     OfferedIncompatibleQosStatus offered_incompatible_qos_status_;
@@ -598,6 +601,15 @@ protected:
     OfferedIncompatibleQosStatus& update_offered_incompatible_qos(
             PolicyMask incompatible_policies);
 
+    /*!
+     * @brief Updates liveliness lost status.
+     *
+     * @param[in] liveliness_lost_status Liveliness lost status coming from RTPS layer.
+     * @return Current liveliness lost status.
+     */
+    LivelinessLostStatus& update_liveliness_lost_status(
+            const fastrtps::LivelinessLostStatus& liveliness_lost_status);
+
     /**
      * Returns the most appropriate listener to handle the callback for the given status,
      * or nullptr if there is no appropriate listener.
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReader.cpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReader.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReader.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReader.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -95,11 +95,18 @@ ReturnCode_t DataReader::read_w_conditio
         int32_t max_samples,
         ReadCondition* a_condition)
 {
-    static_cast<void> (data_values);
-    static_cast<void> (sample_infos);
-    static_cast<void> (max_samples);
-    static_cast<void> (a_condition);
-    return ReturnCode_t::RETCODE_UNSUPPORTED;
+    if ( nullptr == a_condition )
+    {
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+    return read(
+        data_values,
+        sample_infos,
+        max_samples,
+        a_condition->get_sample_state_mask(),
+        a_condition->get_view_state_mask(),
+        a_condition->get_instance_state_mask());
 }
 
 ReturnCode_t DataReader::read_instance(
@@ -135,12 +142,19 @@ ReturnCode_t DataReader::read_next_insta
         const InstanceHandle_t& previous_handle,
         ReadCondition* a_condition)
 {
-    static_cast<void> (data_values);
-    static_cast<void> (sample_infos);
-    static_cast<void> (max_samples);
-    static_cast<void> (previous_handle);
-    static_cast<void> (a_condition);
-    return ReturnCode_t::RETCODE_UNSUPPORTED;
+    if ( nullptr == a_condition )
+    {
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+    return read_next_instance(
+        data_values,
+        sample_infos,
+        max_samples,
+        previous_handle,
+        a_condition->get_sample_state_mask(),
+        a_condition->get_view_state_mask(),
+        a_condition->get_instance_state_mask());
 }
 
 ReturnCode_t DataReader::take(
@@ -160,11 +174,18 @@ ReturnCode_t DataReader::take_w_conditio
         int32_t max_samples,
         ReadCondition* a_condition)
 {
-    static_cast<void> (data_values);
-    static_cast<void> (sample_infos);
-    static_cast<void> (max_samples);
-    static_cast<void> (a_condition);
-    return ReturnCode_t::RETCODE_UNSUPPORTED;
+    if ( nullptr == a_condition )
+    {
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+    return take(
+        data_values,
+        sample_infos,
+        max_samples,
+        a_condition->get_sample_state_mask(),
+        a_condition->get_view_state_mask(),
+        a_condition->get_instance_state_mask());
 }
 
 ReturnCode_t DataReader::take_instance(
@@ -200,12 +221,19 @@ ReturnCode_t DataReader::take_next_insta
         const InstanceHandle_t& previous_handle,
         ReadCondition* a_condition)
 {
-    static_cast<void> (data_values);
-    static_cast<void> (sample_infos);
-    static_cast<void> (max_samples);
-    static_cast<void> (previous_handle);
-    static_cast<void> (a_condition);
-    return ReturnCode_t::RETCODE_UNSUPPORTED;
+    if ( nullptr == a_condition )
+    {
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+    return take_next_instance(
+        data_values,
+        sample_infos,
+        max_samples,
+        previous_handle,
+        a_condition->get_sample_state_mask(),
+        a_condition->get_view_state_mask(),
+        a_condition->get_instance_state_mask());
 }
 
 ReturnCode_t DataReader::return_loan(
@@ -252,7 +280,13 @@ ReturnCode_t DataReader::get_first_untak
 
 uint64_t DataReader::get_unread_count() const
 {
-    return impl_->get_unread_count();
+    return impl_->get_unread_count(false);
+}
+
+uint64_t DataReader::get_unread_count(
+        bool mark_as_read) const
+{
+    return impl_->get_unread_count(mark_as_read);
 }
 
 const GUID_t& DataReader::guid()
@@ -384,14 +418,7 @@ ReadCondition* DataReader::create_readco
         ViewStateMask view_states,
         InstanceStateMask instance_states)
 {
-    logWarning(DATA_READER, "create_readcondition method not implemented");
-    static_cast<void> (sample_states);
-    static_cast<void> (view_states);
-    static_cast<void> (instance_states);
-    return nullptr;
-    /*
-       return impl_->create_readcondition(sample_states, view_states, instance_states);
-     */
+    return impl_->create_readcondition(sample_states, view_states, instance_states);
 }
 
 QueryCondition* DataReader::create_querycondition(
@@ -414,13 +441,9 @@ QueryCondition* DataReader::create_query
 }
 
 ReturnCode_t DataReader::delete_readcondition(
-        const ReadCondition* a_condition)
+        ReadCondition* a_condition)
 {
-    static_cast<void> (a_condition);
-    return ReturnCode_t::RETCODE_UNSUPPORTED;
-    /*
-       return impl_->delete_readcondition(a_condition);
-     */
+    return impl_->delete_readcondition(a_condition);
 }
 
 ReturnCode_t DataReader::delete_contained_entities()
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReaderImpl/ReadTakeCommand.hpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReaderImpl/ReadTakeCommand.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReaderImpl/ReadTakeCommand.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReaderImpl/ReadTakeCommand.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -77,13 +77,13 @@ struct ReadTakeCommand
         , remaining_samples_(max_samples)
         , states_(states)
         , instance_(instance)
-        , handle_(instance.first)
+        , handle_(instance->first)
         , single_instance_(single_instance)
     {
         assert(0 <= remaining_samples_);
 
         current_slot_ = data_values_.length();
-        finished_ = nullptr == instance.second;
+        finished_ = false;
     }
 
     ~ReadTakeCommand()
@@ -108,8 +108,8 @@ struct ReadTakeCommand
         // Traverse changes on current instance
         bool ret_val = false;
         LoanableCollection::size_type first_slot = current_slot_;
-        auto it = instance_.second->cache_changes.begin();
-        while (!finished_ && it != instance_.second->cache_changes.end())
+        auto it = instance_->second->cache_changes.begin();
+        while (!finished_ && it != instance_->second->cache_changes.end())
         {
             CacheChange_t* change = *it;
             SampleStateKind check;
@@ -145,6 +145,7 @@ struct ReadTakeCommand
                     // Add sample and info to collections
                     ReturnCode_t previous_return_value = return_value_;
                     bool added = add_sample(*it, remove_change);
+                    history_.change_was_processed_nts(change, added);
                     reader_->end_sample_access_nts(change, wp, added);
 
                     // Check if the payload is dirty
@@ -180,7 +181,7 @@ struct ReadTakeCommand
 
         if (current_slot_ > first_slot)
         {
-            instance_.second->view_state = ViewStateKind::NOT_NEW_VIEW_STATE;
+            history_.instance_viewed_nts(instance_->second);
             ret_val = true;
 
             // complete sample infos
@@ -279,8 +280,8 @@ private:
     bool is_current_instance_valid()
     {
         // Check instance_state against states_.instance_states and view_state against states_.view_states
-        auto instance_state = instance_.second->instance_state;
-        auto view_state = instance_.second->view_state;
+        auto instance_state = instance_->second->instance_state;
+        auto view_state = instance_->second->view_state;
         return (0 != (states_.instance_states & instance_state)) && (0 != (states_.view_states & view_state));
     }
 
@@ -293,7 +294,7 @@ private:
             return false;
         }
 
-        auto result = history_.lookup_instance(handle_, false);
+        auto result = history_.next_available_instance_nts(handle_, instance_);
         if (!result.first)
         {
             finished_ = true;
@@ -301,7 +302,7 @@ private:
         }
 
         instance_ = result.second;
-        handle_ = instance_.first;
+        handle_ = instance_->first;
         return true;
     }
 
@@ -376,7 +377,7 @@ private:
         }
 
         SampleInfo& info = sample_infos_[current_slot_];
-        generate_info(info, *instance_.second, item);
+        generate_info(info, *instance_->second, item);
     }
 
     bool check_datasharing_validity(
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReaderImpl.cpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReaderImpl.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReaderImpl.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReaderImpl.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -16,9 +16,17 @@
  * @file DataReaderImpl.cpp
  */
 
+#include <memory>
+#include <stdexcept>
+
+#if defined(__has_include) && __has_include(<version>)
+#   include <version>
+#endif // if defined(__has_include) && __has_include(<version>)
+
 #include <fastrtps/config.h>
 
 #include <fastdds/subscriber/DataReaderImpl.hpp>
+#include <fastdds/subscriber/ReadConditionImpl.hpp>
 
 #include <fastdds/dds/core/StackAllocatedSequence.hpp>
 #include <fastdds/dds/domain/DomainParticipant.hpp>
@@ -53,10 +61,14 @@
 #include <rtps/history/TopicPayloadPoolRegistry.hpp>
 #include <rtps/participant/RTPSParticipantImpl.h>
 
-using namespace eprosima::fastrtps;
+using eprosima::fastrtps::RecursiveTimedMutex;
+using eprosima::fastrtps::c_TimeInfinite;
+
 using namespace eprosima::fastrtps::rtps;
 using namespace std::chrono;
 
+using eprosima::fastrtps::types::ReturnCode_t;
+
 namespace eprosima {
 namespace fastdds {
 namespace dds {
@@ -109,7 +121,7 @@ DataReaderImpl::DataReaderImpl(
     endpoint_attributes.topicKind = type_->m_isGetKeyDefined ? WITH_KEY : NO_KEY;
     endpoint_attributes.setEntityID(qos_.endpoint().entity_id);
     endpoint_attributes.setUserDefinedID(qos_.endpoint().user_defined_id);
-    fastrtps::rtps::RTPSParticipantImpl::preprocess_endpoint_attributes<READER, 0x04, 0x07>(
+    RTPSParticipantImpl::preprocess_endpoint_attributes<READER, 0x04, 0x07>(
         EntityId_t::unknown(), subscriber_->get_participant_impl()->id_counter(), endpoint_attributes, guid_.entityId);
     guid_.guidPrefix = subscriber_->get_participant_impl()->guid().guidPrefix;
 }
@@ -118,7 +130,7 @@ ReturnCode_t DataReaderImpl::enable()
 {
     assert(reader_ == nullptr);
 
-    fastrtps::rtps::ReaderAttributes att;
+    ReaderAttributes att;
 
     att.endpoint.durabilityKind = qos_.durability().durabilityKind();
     att.endpoint.endpointKind = READER;
@@ -245,7 +257,7 @@ ReturnCode_t DataReaderImpl::enable()
         }
     }
 
-    eprosima::fastdds::rtps::ContentFilterProperty* filter_property = nullptr;
+    rtps::ContentFilterProperty* filter_property = nullptr;
     if (nullptr != content_topic && !content_topic->filter_property.filter_expression.empty())
     {
         filter_property = &content_topic->filter_property;
@@ -294,6 +306,9 @@ void DataReaderImpl::stop()
 
 DataReaderImpl::~DataReaderImpl()
 {
+    // assert there are no pending conditions
+    assert(read_conditions_.empty());
+
     // Disable the datareader to prevent receiving data in the middle of deleting it
     disable();
 
@@ -302,11 +317,27 @@ DataReaderImpl::~DataReaderImpl()
     delete user_datareader_;
 }
 
-bool DataReaderImpl::can_be_deleted() const
+bool DataReaderImpl::can_be_deleted(
+        bool recursive) const
 {
     if (reader_ != nullptr)
     {
-        std::lock_guard<RecursiveTimedMutex> lock(reader_->getMutex());
+        std::lock_guard<RecursiveTimedMutex> _(reader_->getMutex());
+
+        // According with the standard
+        // delete_datareader() should fail with outstanding ReadConditions
+        // delete_contained_entities() should not
+        if ( !recursive )
+        {
+            std::lock_guard<std::recursive_mutex> __(get_conditions_mutex());
+
+            if (!read_conditions_.empty())
+            {
+                logWarning(DATA_READER, "DataReader " << guid() << " has ReadConditions not yet deleted");
+                return false;
+            }
+        }
+
         return !loan_manager_.has_outstanding_loans();
     }
 
@@ -314,7 +345,7 @@ bool DataReaderImpl::can_be_deleted() co
 }
 
 bool DataReaderImpl::wait_for_unread_message(
-        const fastrtps::Duration_t& timeout)
+        const Duration_t& timeout)
 {
     return reader_ ? reader_->wait_for_unread_cache(timeout) : false;
 }
@@ -476,10 +507,17 @@ ReturnCode_t DataReaderImpl::read_or_tak
 
     set_read_communication_status(false);
 
-    auto it = history_.lookup_instance(handle, exact_instance);
+    auto it = history_.lookup_available_instance(handle, exact_instance);
     if (!it.first)
     {
-        return exact_instance ? ReturnCode_t::RETCODE_BAD_PARAMETER : ReturnCode_t::RETCODE_NO_DATA;
+        if (exact_instance && !history_.is_instance_present(handle))
+        {
+            return ReturnCode_t::RETCODE_BAD_PARAMETER;
+        }
+        else
+        {
+            return ReturnCode_t::RETCODE_NO_DATA;
+        }
     }
 
     code = prepare_loan(data_values, sample_infos, max_samples);
@@ -488,12 +526,15 @@ ReturnCode_t DataReaderImpl::read_or_tak
         return code;
     }
 
-    detail::StateFilter states{ sample_states, view_states, instance_states };
+    detail::StateFilter states = { sample_states, view_states, instance_states };
     detail::ReadTakeCommand cmd(*this, data_values, sample_infos, max_samples, states, it.second, single_instance);
     while (!cmd.is_finished())
     {
         cmd.add_instance(should_take);
     }
+
+    try_notify_read_conditions();
+
     return cmd.return_value();
 }
 
@@ -656,7 +697,7 @@ ReturnCode_t DataReaderImpl::read_or_tak
 
     set_read_communication_status(false);
 
-    auto it = history_.lookup_instance(HANDLE_NIL, false);
+    auto it = history_.lookup_available_instance(HANDLE_NIL, false);
     if (!it.first)
     {
         return ReturnCode_t::RETCODE_NO_DATA;
@@ -678,6 +719,9 @@ ReturnCode_t DataReaderImpl::read_or_tak
     {
         *info = sample_infos[0];
     }
+
+    try_notify_read_conditions();
+
     return code;
 }
 
@@ -710,9 +754,15 @@ ReturnCode_t DataReaderImpl::get_first_u
     return ReturnCode_t::RETCODE_NO_DATA;
 }
 
-uint64_t DataReaderImpl::get_unread_count() const
+uint64_t DataReaderImpl::get_unread_count(
+        bool mark_as_read)
 {
-    return reader_ ? reader_->get_unread_count() : 0;
+    uint64_t ret_val = reader_ ? history_.get_unread_count(mark_as_read) : 0;
+    if (mark_as_read)
+    {
+        try_notify_read_conditions();
+    }
+    return ret_val;
 }
 
 const GUID_t& DataReaderImpl::guid() const
@@ -734,7 +784,7 @@ void DataReaderImpl::update_rtps_reader_
 {
     if (reader_)
     {
-        eprosima::fastdds::rtps::ContentFilterProperty* filter_property = nullptr;
+        rtps::ContentFilterProperty* filter_property = nullptr;
         auto content_topic = dynamic_cast<ContentFilteredTopicImpl*>(topic_->get_impl());
         if (nullptr != content_topic && !content_topic->filter_property.filter_expression.empty())
         {
@@ -813,11 +863,16 @@ const DataReaderQos& DataReaderImpl::get
     return qos_;
 }
 
-void DataReaderImpl::InnerDataReaderListener::onNewCacheChangeAdded(
+void DataReaderImpl::InnerDataReaderListener::on_data_available(
         RTPSReader* /*reader*/,
-        const CacheChange_t* const change_in)
+        const GUID_t& writer_guid,
+        const SequenceNumber_t& first_sequence,
+        const SequenceNumber_t& last_sequence,
+        bool& should_notify_individual_changes)
 {
-    if (data_reader_->on_new_cache_change_added(change_in))
+    should_notify_individual_changes = false;
+
+    if (data_reader_->on_data_available(writer_guid, first_sequence, last_sequence))
     {
         auto user_reader = data_reader_->user_datareader_;
 
@@ -851,7 +906,7 @@ void DataReaderImpl::InnerDataReaderList
 
 void DataReaderImpl::InnerDataReaderListener::on_liveliness_changed(
         RTPSReader* /*reader*/,
-        const fastrtps::LivelinessChangedStatus& status)
+        const LivelinessChangedStatus& status)
 {
     data_reader_->update_liveliness_status(status);
     StatusMask notify_status = StatusMask::liveliness_changed();
@@ -869,7 +924,7 @@ void DataReaderImpl::InnerDataReaderList
 
 void DataReaderImpl::InnerDataReaderListener::on_requested_incompatible_qos(
         RTPSReader* /*reader*/,
-        fastdds::dds::PolicyMask qos)
+        PolicyMask qos)
 {
     data_reader_->update_requested_incompatible_qos(qos);
     StatusMask notify_status = StatusMask::requested_incompatible_qos();
@@ -922,11 +977,32 @@ void DataReaderImpl::InnerDataReaderList
     data_reader_->user_datareader_->get_statuscondition().get_impl()->set_status(notify_status, true);
 }
 
-bool DataReaderImpl::on_new_cache_change_added(
-        const CacheChange_t* const change)
+bool DataReaderImpl::on_data_available(
+        const GUID_t& writer_guid,
+        const SequenceNumber_t& first_sequence,
+        const SequenceNumber_t& last_sequence)
 {
+    bool ret_val = false;
+
     std::lock_guard<RecursiveTimedMutex> guard(reader_->getMutex());
+    for (auto seq = first_sequence; seq <= last_sequence; ++seq)
+    {
+        CacheChange_t* change = nullptr;
 
+        if (history_.get_change(seq, writer_guid, &change))
+        {
+            ret_val |= on_new_cache_change_added(change);
+        }
+    }
+
+    try_notify_read_conditions();
+
+    return ret_val;
+}
+
+bool DataReaderImpl::on_new_cache_change_added(
+        const CacheChange_t* const change)
+{
     if (qos_.deadline().period != c_TimeInfinite)
     {
         if (!history_.set_next_deadline(
@@ -1005,6 +1081,7 @@ void DataReaderImpl::update_subscription
     if (count_change < 0)
     {
         history_.writer_not_alive(iHandle2GUID(status.last_publication_handle));
+        try_notify_read_conditions();
     }
 
     StatusMask notify_status = StatusMask::subscription_matched();
@@ -1124,6 +1201,8 @@ bool DataReaderImpl::lifespan_expired()
         // The earliest change has expired
         history_.remove_change_sub(earliest_change);
 
+        try_notify_read_conditions();
+
         // Set the timer for the next change if there is one
         if (!history_.get_earliest_change(&earliest_change))
         {
@@ -1276,7 +1355,7 @@ RequestedIncompatibleQosStatus& DataRead
 {
     ++requested_incompatible_qos_status_.total_count;
     ++requested_incompatible_qos_status_.total_count_change;
-    for (fastrtps::rtps::octet id = 1; id < NEXT_QOS_POLICY_ID; ++id)
+    for (octet id = 1; id < NEXT_QOS_POLICY_ID; ++id)
     {
         if (incompatible_policies.test(id))
         {
@@ -1288,11 +1367,12 @@ RequestedIncompatibleQosStatus& DataRead
 }
 
 LivelinessChangedStatus& DataReaderImpl::update_liveliness_status(
-        const fastrtps::LivelinessChangedStatus& status)
+        const LivelinessChangedStatus& status)
 {
     if (0 < status.not_alive_count_change)
     {
         history_.writer_not_alive(iHandle2GUID(status.last_publication_handle));
+        try_notify_read_conditions();
     }
 
     liveliness_changed_status_.alive_count = status.alive_count;
@@ -1689,7 +1769,21 @@ ReturnCode_t DataReaderImpl::get_listeni
 
 ReturnCode_t DataReaderImpl::delete_contained_entities()
 {
-    // Until Query Conditions are implemented, there are no contained entities to destroy, so return OK.
+    std::lock_guard<std::recursive_mutex> _(get_conditions_mutex());
+
+    // Check pending ReadConditions
+    for (detail::ReadConditionImpl* impl : read_conditions_)
+    {
+        // should be alive
+        auto keep_alive = impl->shared_from_this();
+        assert((bool)keep_alive);
+        // free ReadConditions
+        impl->detach_all_conditions();
+    }
+
+    // release the colection
+    read_conditions_.clear();
+
     return ReturnCode_t::RETCODE_OK;
 }
 
@@ -1707,8 +1801,7 @@ InstanceHandle_t DataReaderImpl::lookup_
     {
         if (type_->getKey(const_cast<void*>(instance), &handle, false))
         {
-            auto it = history_.lookup_instance(handle, true);
-            if (!it.first)
+            if (!history_.is_instance_present(handle))
             {
                 handle = HANDLE_NIL;
             }
@@ -1728,6 +1821,189 @@ const SampleRejectedStatus& DataReaderIm
     return sample_rejected_status_;
 }
 
-} /* namespace dds */
-} /* namespace fastdds */
-} /* namespace eprosima */
+bool DataReaderImpl::ReadConditionOrder::operator ()(
+        const detail::ReadConditionImpl* lhs,
+        const detail::ReadConditionImpl* rhs) const
+{
+    return less(lhs->get_sample_state_mask(), lhs->get_view_state_mask(), lhs->get_instance_state_mask(),
+                   rhs->get_sample_state_mask(), rhs->get_view_state_mask(), rhs->get_instance_state_mask());
+}
+
+bool DataReaderImpl::ReadConditionOrder::operator ()(
+        const detail::ReadConditionImpl* lhs,
+        const detail::StateFilter& rhs) const
+{
+    return less(lhs->get_sample_state_mask(), lhs->get_view_state_mask(), lhs->get_instance_state_mask(),
+                   rhs.sample_states, rhs.view_states, rhs.instance_states);
+}
+
+bool DataReaderImpl::ReadConditionOrder::operator ()(
+        const detail::StateFilter& lhs,
+        const detail::ReadConditionImpl* rhs) const
+{
+    return less(lhs.sample_states, lhs.view_states, lhs.instance_states,
+                   rhs->get_sample_state_mask(), rhs->get_view_state_mask(), rhs->get_instance_state_mask());
+}
+
+std::recursive_mutex& DataReaderImpl::get_conditions_mutex() const noexcept
+{
+    return conditions_mutex_;
+}
+
+ReadCondition* DataReaderImpl::create_readcondition(
+        SampleStateMask sample_states,
+        ViewStateMask view_states,
+        InstanceStateMask instance_states) noexcept
+{
+    // Check the mask set up makes sense
+    if ( sample_states == 0 && view_states == 0 && instance_states == 0 )
+    {
+        return nullptr;
+    }
+
+    std::lock_guard<std::recursive_mutex> _(get_conditions_mutex());
+
+    // Check if there is an associated ReadConditionImpl object already
+    detail::StateFilter key = {sample_states, view_states, instance_states};
+
+#   ifdef __cpp_lib_generic_associative_lookup
+    // c++14
+    auto it = read_conditions_.find(key);
+#   else
+    // TODO: remove this when C++14 is enforced
+    ReadConditionOrder sort;
+    auto it = lower_bound(read_conditions_.begin(), read_conditions_.end(), key, sort);
+    if (it != read_conditions_.end() &&
+            (sort(*it, key) || sort(key, *it)))
+    {
+        it = read_conditions_.end();
+    }
+#   endif // ifdef __cpp_lib_generic_associative_lookup
+
+    std::shared_ptr<detail::ReadConditionImpl> impl;
+
+    if (it != read_conditions_.end())
+    {
+        // already there
+        impl = (*it)->shared_from_this();
+    }
+    else
+    {
+        // create a new one
+        impl = std::make_shared<detail::ReadConditionImpl>(*this, key);
+        // Add the implementation object to the collection
+        read_conditions_.insert(impl.get());
+    }
+
+    // Now create the ReadCondition and associate it with the implementation
+    ReadCondition* cond = new ReadCondition();
+    auto ret_code = impl->attach_condition(cond);
+
+    // attach cannot fail in this scenario
+    assert(!!ret_code);
+    (void)ret_code;
+
+    return cond;
+}
+
+ReturnCode_t DataReaderImpl::delete_readcondition(
+        ReadCondition* a_condition) noexcept
+{
+    if ( nullptr == a_condition )
+    {
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+    detail::ReadConditionImpl* impl = a_condition->get_impl();
+
+    if ( nullptr == impl )
+    {
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+    std::lock_guard<std::recursive_mutex> _(get_conditions_mutex());
+
+    // Check if there is an associated ReadConditionImpl object already
+    auto it = read_conditions_.find(impl);
+
+    if ( it == read_conditions_.end())
+    {
+        // The ReadCondition is unknown to this DataReader
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+#   ifdef __cpp_lib_enable_shared_from_this
+    std::weak_ptr<detail::ReadConditionImpl> wp = impl->weak_from_this();
+#   else
+    // remove when C++17 is enforced
+    auto wp = std::weak_ptr<detail::ReadConditionImpl>(impl->shared_from_this());
+#   endif // ifdef __cpp_lib_enable_shared_from_this
+
+    // Detach from the implementation object
+    auto ret_code = impl->detach_condition(a_condition);
+
+    if (!!ret_code)
+    {
+        // delete the condition
+        delete a_condition;
+
+        // check if we must remove the implementation object
+        if (wp.expired())
+        {
+            read_conditions_.erase(it);
+        }
+    }
+
+    return ret_code;
+
+}
+
+const eprosima::fastdds::dds::detail::StateFilter& DataReaderImpl::get_last_mask_state() const
+{
+    if (nullptr == reader_)
+    {
+        throw std::runtime_error("The DataReader has not yet been enabled.");
+    }
+
+    std::lock_guard<RecursiveTimedMutex> _(reader_->getMutex());
+    return last_mask_state_;
+}
+
+void DataReaderImpl::try_notify_read_conditions() noexcept
+{
+    // If disabled ignore always
+    if (nullptr == reader_)
+    {
+        return;
+    }
+
+    // Update and check the mask change requires notification
+    {
+        std::lock_guard<RecursiveTimedMutex> _(reader_->getMutex());
+
+        auto old_mask = last_mask_state_;
+        last_mask_state_ = history_.get_mask_status();
+
+        bool notify = last_mask_state_.sample_states & ~old_mask.sample_states ||
+                last_mask_state_.view_states & ~old_mask.view_states ||
+                last_mask_state_.instance_states & ~old_mask.instance_states;
+
+        if (!notify)
+        {
+            return;
+        }
+    }
+
+    // traverse the conditions notifying
+    std::lock_guard<std::recursive_mutex> _(get_conditions_mutex());
+
+    for (detail::ReadConditionImpl* impl : read_conditions_)
+    {
+        impl->notify();
+    }
+}
+
+}  // namespace dds
+}  // namespace fastdds
+}  // namespace eprosima
+
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReaderImpl.hpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReaderImpl.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/DataReaderImpl.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/DataReaderImpl.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -21,13 +21,16 @@
 #define _FASTRTPS_DATAREADERIMPL_HPP_
 #ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
 
+#include <mutex>
+
 #include <fastdds/dds/core/LoanableCollection.hpp>
 #include <fastdds/dds/core/LoanableSequence.hpp>
 #include <fastdds/dds/core/status/StatusMask.hpp>
-#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>
 #include <fastdds/dds/subscriber/DataReaderListener.hpp>
 #include <fastdds/dds/subscriber/SampleInfo.hpp>
+#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>
 #include <fastdds/dds/topic/TypeSupport.hpp>
+#include <fastdds/dds/subscriber/ReadCondition.hpp>
 
 #include <fastdds/rtps/attributes/ReaderAttributes.h>
 #include <fastdds/rtps/common/LocatorList.hpp>
@@ -42,13 +45,12 @@
 #include <fastdds/subscriber/DataReaderImpl/DataReaderLoanManager.hpp>
 #include <fastdds/subscriber/DataReaderImpl/SampleInfoPool.hpp>
 #include <fastdds/subscriber/DataReaderImpl/SampleLoanManager.hpp>
+#include <fastdds/subscriber/DataReaderImpl/StateFilter.hpp>
 #include <fastdds/subscriber/SubscriberImpl.hpp>
 #include <rtps/history/ITopicPayloadPool.h>
 
 #include <fastdds/subscriber/history/DataReaderHistory.hpp>
 
-using eprosima::fastrtps::types::ReturnCode_t;
-
 namespace eprosima {
 namespace fastrtps {
 namespace rtps {
@@ -72,6 +74,7 @@ using SampleInfoSeq = LoanableSequence<S
 namespace detail {
 
 struct ReadTakeCommand;
+class ReadConditionImpl;
 
 } // namespace detail
 
@@ -82,6 +85,7 @@ struct ReadTakeCommand;
 class DataReaderImpl
 {
     friend struct detail::ReadTakeCommand;
+    friend class detail::ReadConditionImpl;
 
 protected:
 
@@ -106,7 +110,13 @@ public:
 
     virtual ReturnCode_t enable();
 
-    bool can_be_deleted() const;
+    /**
+     * Method to check if a DataReader can be deleted
+     * @param recursive == true if is used from delete_contained_entities otherwise delete_datareader
+     * @return true if can be deleted according to the standard rules
+     */
+    bool can_be_deleted(
+            bool recursive = true) const;
 
     /**
      * Method to block the current thread until an unread message is available
@@ -196,9 +206,14 @@ public:
             SampleInfo* info);
 
     /**
-     * @return the number of samples pending to be read.
+     * Get the number of samples pending to be read.
+     *
+     * @param mark_as_read  Whether the unread samples should be marked as read or not.
+     *
+     * @return the number of samples on the reader history that have never been read.
      */
-    uint64_t get_unread_count() const;
+    uint64_t get_unread_count(
+            bool mark_as_read);
 
     /**
      * Get associated GUID
@@ -331,6 +346,20 @@ public:
     InstanceHandle_t lookup_instance(
             const void* instance) const;
 
+    ReadCondition* create_readcondition(
+            SampleStateMask sample_states,
+            ViewStateMask view_states,
+            InstanceStateMask instance_states) noexcept;
+
+    ReturnCode_t delete_readcondition(
+            ReadCondition* a_condition) noexcept;
+
+    const detail::StateFilter& get_last_mask_state() const;
+
+    void try_notify_read_conditions() noexcept;
+
+    std::recursive_mutex& get_conditions_mutex() const noexcept;
+
 protected:
 
     //!Subscriber
@@ -372,9 +401,12 @@ protected:
                 fastrtps::rtps::RTPSReader* reader,
                 const SubscriptionMatchedStatus& info) override;
 
-        void onNewCacheChangeAdded(
+        void on_data_available(
                 fastrtps::rtps::RTPSReader* reader,
-                const fastrtps::rtps::CacheChange_t* const change) override;
+                const fastrtps::rtps::GUID_t& writer_guid,
+                const fastrtps::rtps::SequenceNumber_t& first_sequence,
+                const fastrtps::rtps::SequenceNumber_t& last_sequence,
+                bool& should_notify_individual_changes) override;
 
         void on_liveliness_changed(
                 fastrtps::rtps::RTPSReader* reader,
@@ -437,6 +469,52 @@ protected:
     detail::SampleInfoPool sample_info_pool_;
     detail::DataReaderLoanManager loan_manager_;
 
+    /**
+     * Mutex to protect ReadCondition collection
+     * is required because the RTPSReader mutex is only available when the object is enabled
+     * @note use get_conditions_mutex() instead of directly referencing it
+     * @note lock get_conditions_mutex() after lock reader_->getMutex() to avoid ABBAs because
+     *       try_notify_read_conditions() will be called from the callbacks with the reader
+     *       mutex locked
+     */
+    mutable std::recursive_mutex conditions_mutex_;
+
+    // Order for the ReadCondition collection
+    struct ReadConditionOrder
+    {
+        using is_transparent = void;
+
+        bool operator ()(
+                const detail::ReadConditionImpl* lhs,
+                const detail::ReadConditionImpl* rhs) const;
+        bool operator ()(
+                const detail::ReadConditionImpl* lhs,
+                const detail::StateFilter& rhs) const;
+        bool operator ()(
+                const detail::StateFilter& lhs,
+                const detail::ReadConditionImpl* rhs) const;
+
+        template<class S, class V, class I>
+        static inline bool less(
+                S&& s1,
+                V&& v1,
+                I&& i1,
+                S&& s2,
+                V&& v2,
+                I&& i2)
+        {
+            return s1 < s2 || (s1 == s2 && (v1 < v2 || (v1 == v2 && i1 < i2)));
+        }
+
+    };
+
+    // ReadConditions collection
+    std::set<detail::ReadConditionImpl*, ReadConditionOrder> read_conditions_;
+
+    // State of the History mask last time it was queried
+    // protected with the RTPSReader mutex
+    detail::StateFilter last_mask_state_ {};
+
     ReturnCode_t check_collection_preconditions_and_calc_max_samples(
             LoanableCollection& data_values,
             SampleInfoSeq& sample_infos,
@@ -470,6 +548,11 @@ protected:
     void update_subscription_matched_status(
             const SubscriptionMatchedStatus& status);
 
+    bool on_data_available(
+            const fastrtps::rtps::GUID_t& writer_guid,
+            const fastrtps::rtps::SequenceNumber_t& first_sequence,
+            const fastrtps::rtps::SequenceNumber_t& last_sequence);
+
     /**
      * @brief A method called when a new cache change is added
      * @param change The cache change that has been added
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderHistoryCounters.hpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderHistoryCounters.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderHistoryCounters.hpp	1970-01-01 00:00:00.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderHistoryCounters.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -0,0 +1,55 @@
+// Copyright 2022 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 DataReaderHistoryCounters.hpp
+ */
+
+#ifndef _FASTDDS_SUBSCRIBER_HISTORY_DATAREADERHISTORYCOUNTERS_HPP_
+#define _FASTDDS_SUBSCRIBER_HISTORY_DATAREADERHISTORYCOUNTERS_HPP_
+
+#include <cstdint>
+
+namespace eprosima {
+namespace fastdds {
+namespace dds {
+namespace detail {
+
+/// Book-keeping information for a DataReaderHistory
+struct DataReaderHistoryCounters
+{
+    /// Total number of read samples accesible from the history
+    uint64_t samples_read = 0;
+    /// Total number of unread samples accesible from the history
+    uint64_t samples_unread = 0;
+
+    /// Total number of instances with NEW_VIEW_STATE
+    uint64_t instances_new = 0;
+    /// Total number of instances with NOT_NEW_VIEW_STATE
+    uint64_t instances_not_new = 0;
+
+    /// Total number of instances with ALIVE_INSTANCE_STATE
+    uint64_t instances_alive = 0;
+    /// Total number of instances with NOT_ALIVE_DISPOSED_INSTANCE_STATE
+    uint64_t instances_disposed = 0;
+    /// Total number of instances with NOT_ALIVE_NO_WRITERS_INSTANCE_STATE
+    uint64_t instances_no_writers = 0;
+};
+
+} /* namespace detail */
+} /* namespace dds */
+} /* namespace fastdds */
+} /* namespace eprosima */
+
+#endif  // _FASTDDS_SUBSCRIBER_HISTORY_DATAREADERHISTORYCOUNTERS_HPP_
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -17,6 +17,7 @@
  */
 
 #include <limits>
+#include <memory>
 #include <mutex>
 
 #include "DataReaderHistory.hpp"
@@ -28,14 +29,13 @@
 #include <fastdds/rtps/reader/RTPSReader.h>
 
 #include <fastdds/subscriber/DataReaderImpl/ReadTakeCommand.hpp>
+
+#include <rtps/common/ChangeComparison.hpp>
 #include <rtps/reader/WriterProxy.h>
 #include <utils/collections/sorted_vector_insert.hpp>
 
-namespace eprosima {
-namespace fastdds {
-namespace dds {
-namespace detail {
-
+using namespace eprosima::fastdds::dds;
+using namespace eprosima::fastdds::dds::detail;
 using namespace eprosima::fastrtps::rtps;
 
 using eprosima::fastrtps::RecursiveTimedMutex;
@@ -98,8 +98,9 @@ DataReaderHistory::DataReaderHistory(
         key_changes_allocation_.initial = resource_limited_qos_.allocated_samples;
         key_changes_allocation_.maximum = resource_limited_qos_.max_samples;
 
-        keyed_changes_.emplace(c_InstanceHandle_Unknown,
-                DataReaderInstance{ key_changes_allocation_, key_writers_allocation_ });
+        instances_.emplace(c_InstanceHandle_Unknown,
+                std::make_shared<DataReaderInstance>(key_changes_allocation_, key_writers_allocation_));
+        data_available_instances_[c_InstanceHandle_Unknown] = instances_[c_InstanceHandle_Unknown];
     }
 
     using std::placeholders::_1;
@@ -199,7 +200,7 @@ bool DataReaderHistory::received_change(
     if ((0 == unknown_missing_changes_up_to) ||
             (m_changes.size() + unknown_missing_changes_up_to < static_cast<size_t>(resource_limited_qos_.max_samples)))
     {
-        std::lock_guard<RecursiveTimedMutex> guard(*mp_mutex);
+        std::lock_guard<RecursiveTimedMutex> guard(*getMutex());
         ret_value =  receive_fn_(a_change, unknown_missing_changes_up_to, rejection_reason);
     }
     else
@@ -225,11 +226,11 @@ bool DataReaderHistory::received_change_
     InstanceCollection::iterator vit;
     if (find_key(a_change->instanceHandle, vit))
     {
-        DataReaderInstance::ChangeCollection& instance_changes = vit->second.cache_changes;
+        DataReaderInstance::ChangeCollection& instance_changes = vit->second->cache_changes;
         size_t total_size = instance_changes.size() + unknown_missing_changes_up_to;
         if (total_size < static_cast<size_t>(resource_limited_qos_.max_samples_per_instance))
         {
-            ret_value =  add_received_change_with_key(a_change, vit->second, rejection_reason);
+            ret_value =  add_received_change_with_key(a_change, *vit->second, rejection_reason);
         }
         else
         {
@@ -261,7 +262,7 @@ bool DataReaderHistory::received_change_
     InstanceCollection::iterator vit;
     if (find_key(a_change->instanceHandle, vit))
     {
-        DataReaderInstance::ChangeCollection& instance_changes = vit->second.cache_changes;
+        DataReaderInstance::ChangeCollection& instance_changes = vit->second->cache_changes;
         if (instance_changes.size() < static_cast<size_t>(history_qos_.depth))
         {
             ret_value = true;
@@ -284,7 +285,7 @@ bool DataReaderHistory::received_change_
 
         if (ret_value)
         {
-            ret_value = add_received_change_with_key(a_change, vit->second, rejection_reason);
+            ret_value = add_received_change_with_key(a_change, *vit->second, rejection_reason);
         }
     }
     else
@@ -336,11 +337,8 @@ void DataReaderHistory::add_to_instance(
 {
     // ADD TO KEY VECTOR
     DataReaderCacheChange item = a_change;
-    eprosima::utilities::collections::sorted_vector_insert(instance.cache_changes, item,
-            [](const DataReaderCacheChange& lhs, const DataReaderCacheChange& rhs)
-            {
-                return lhs->sourceTimestamp < rhs->sourceTimestamp;
-            });
+    eprosima::utilities::collections::sorted_vector_insert(instance.cache_changes, item, rtps::history_order_cmp);
+    data_available_instances_[a_change->instanceHandle] = instances_[a_change->instanceHandle];
 
     logInfo(SUBSCRIBER, mp_reader->getGuid().entityId
             << ": Change " << a_change->sequenceNumber << " added from: "
@@ -350,22 +348,22 @@ void DataReaderHistory::add_to_instance(
 bool DataReaderHistory::get_first_untaken_info(
         SampleInfo& info)
 {
-    std::lock_guard<RecursiveTimedMutex> lock(*mp_mutex);
+    std::lock_guard<RecursiveTimedMutex> lock(*getMutex());
 
     CacheChange_t* change = nullptr;
     WriterProxy* wp = nullptr;
     if (mp_reader->nextUntakenCache(&change, &wp))
     {
-        auto it = keyed_changes_.find(change->instanceHandle);
-        assert(it != keyed_changes_.end());
-        auto& instance_changes = it->second.cache_changes;
+        auto it = data_available_instances_.find(change->instanceHandle);
+        assert(it != data_available_instances_.end());
+        auto& instance_changes = it->second->cache_changes;
         auto item =
                 std::find_if(instance_changes.cbegin(), instance_changes.cend(),
                         [change](const DataReaderCacheChange& v)
                         {
                             return v == change;
                         });
-        ReadTakeCommand::generate_info(info, it->second, *item);
+        ReadTakeCommand::generate_info(info, *(it->second), *item);
         mp_reader->change_read_by_user(change, wp, false);
         return true;
     }
@@ -378,27 +376,29 @@ bool DataReaderHistory::find_key(
         InstanceCollection::iterator& vit_out)
 {
     InstanceCollection::iterator vit;
-    vit = keyed_changes_.find(handle);
-    if (vit != keyed_changes_.end())
+    vit = instances_.find(handle);
+    if (vit != instances_.end())
     {
         vit_out = vit;
         return true;
     }
 
-    if (keyed_changes_.size() < static_cast<size_t>(resource_limited_qos_.max_instances))
+    if (instances_.size() < static_cast<size_t>(resource_limited_qos_.max_instances))
     {
-        vit_out = keyed_changes_.emplace(handle,
-                        DataReaderInstance{key_changes_allocation_, key_writers_allocation_}).first;
+        vit_out = instances_.emplace(handle,
+                        std::make_shared<DataReaderInstance>(key_changes_allocation_, key_writers_allocation_)).first;
         return true;
     }
 
-    for (vit = keyed_changes_.begin(); vit != keyed_changes_.end(); ++vit)
+    for (vit = instances_.begin(); vit != instances_.end(); ++vit)
     {
-        if (InstanceStateKind::ALIVE_INSTANCE_STATE != vit->second.instance_state)
+        if (InstanceStateKind::ALIVE_INSTANCE_STATE != vit->second->instance_state)
         {
-            keyed_changes_.erase(vit);
-            vit_out = keyed_changes_.emplace(handle,
-                            DataReaderInstance{ key_changes_allocation_, key_writers_allocation_ }).first;
+            data_available_instances_.erase(vit->first);
+            instances_.erase(vit);
+            vit_out = instances_.emplace(handle,
+                            std::make_shared<DataReaderInstance>(key_changes_allocation_,
+                            key_writers_allocation_)).first;
             return true;
         }
     }
@@ -411,6 +411,7 @@ void DataReaderHistory::writer_unmatched
         const GUID_t& writer_guid,
         const SequenceNumber_t& last_notified_seq)
 {
+    // Remove all future changes from the unmatched writer
     remove_changes_with_pred(
         [&writer_guid, &last_notified_seq](CacheChange_t* ch)
         {
@@ -427,18 +428,23 @@ bool DataReaderHistory::remove_change_su
         return false;
     }
 
-    std::lock_guard<RecursiveTimedMutex> guard(*mp_mutex);
+    std::lock_guard<RecursiveTimedMutex> guard(*getMutex());
     bool found = false;
     InstanceCollection::iterator vit;
     if (find_key(change->instanceHandle, vit))
     {
-        for (auto chit = vit->second.cache_changes.begin(); chit != vit->second.cache_changes.end(); ++chit)
+        for (auto chit = vit->second->cache_changes.begin(); chit != vit->second->cache_changes.end(); ++chit)
         {
             if ((*chit)->sequenceNumber == change->sequenceNumber &&
                     (*chit)->writerGUID == change->writerGUID)
             {
-                vit->second.cache_changes.erase(chit);
+                vit->second->cache_changes.erase(chit);
                 found = true;
+
+                if (change->isRead)
+                {
+                    --counters_.samples_read;
+                }
                 break;
             }
         }
@@ -451,6 +457,7 @@ bool DataReaderHistory::remove_change_su
     if (remove_change(change))
     {
         m_isHistoryFull = false;
+        counters_.samples_unread = mp_reader->get_unread_count();
         return true;
     }
 
@@ -467,19 +474,24 @@ bool DataReaderHistory::remove_change_su
         return false;
     }
 
-    std::lock_guard<RecursiveTimedMutex> guard(*mp_mutex);
+    std::lock_guard<RecursiveTimedMutex> guard(*getMutex());
     bool found = false;
     InstanceCollection::iterator vit;
     if (find_key(change->instanceHandle, vit))
     {
-        for (auto chit = vit->second.cache_changes.begin(); chit != vit->second.cache_changes.end(); ++chit)
+        for (auto chit = vit->second->cache_changes.begin(); chit != vit->second->cache_changes.end(); ++chit)
         {
             if ((*chit)->sequenceNumber == change->sequenceNumber &&
                     (*chit)->writerGUID == change->writerGUID)
             {
                 assert(it == chit);
-                it = vit->second.cache_changes.erase(chit);
+                it = vit->second->cache_changes.erase(chit);
                 found = true;
+
+                if (change->isRead)
+                {
+                    --counters_.samples_read;
+                }
                 break;
             }
         }
@@ -499,6 +511,7 @@ bool DataReaderHistory::remove_change_su
     m_isHistoryFull = false;
     ReaderHistory::remove_change_nts(chit);
 
+    counters_.samples_unread = mp_reader->get_unread_count();
     return true;
 }
 
@@ -511,14 +524,14 @@ bool DataReaderHistory::set_next_deadlin
         logError(SUBSCRIBER, "You need to create a Reader with this History before using it");
         return false;
     }
-    std::lock_guard<RecursiveTimedMutex> guard(*mp_mutex);
-    auto it = keyed_changes_.find(handle);
-    if (it == keyed_changes_.end())
+    std::lock_guard<RecursiveTimedMutex> guard(*getMutex());
+    auto it = instances_.find(handle);
+    if (it == instances_.end())
     {
         return false;
     }
 
-    it->second.next_deadline_us = next_deadline_us;
+    it->second->next_deadline_us = next_deadline_us;
     return true;
 }
 
@@ -531,80 +544,117 @@ bool DataReaderHistory::get_next_deadlin
         logError(SUBSCRIBER, "You need to create a Reader with this History before using it");
         return false;
     }
-    std::lock_guard<RecursiveTimedMutex> guard(*mp_mutex);
-    auto min = std::min_element(keyed_changes_.begin(),
-                    keyed_changes_.end(),
+    std::lock_guard<RecursiveTimedMutex> guard(*getMutex());
+    auto min = std::min_element(instances_.begin(),
+                    instances_.end(),
                     [](
-                        const std::pair<InstanceHandle_t, DataReaderInstance>& lhs,
-                        const std::pair<InstanceHandle_t, DataReaderInstance>& rhs)
+                        const InstanceCollection::value_type& lhs,
+                        const InstanceCollection::value_type& rhs)
                     {
-                        return lhs.second.next_deadline_us < rhs.second.next_deadline_us;
+                        return lhs.second->next_deadline_us < rhs.second->next_deadline_us;
                     });
     handle = min->first;
-    next_deadline_us = min->second.next_deadline_us;
+    next_deadline_us = min->second->next_deadline_us;
     return true;
 }
 
-std::pair<bool, DataReaderHistory::instance_info> DataReaderHistory::lookup_instance(
+uint64_t DataReaderHistory::get_unread_count(
+        bool mark_as_read)
+{
+    std::lock_guard<RecursiveTimedMutex> guard(*getMutex());
+    uint64_t ret_val = mp_reader->get_unread_count(mark_as_read);
+    assert(ret_val == counters_.samples_unread);
+    if (mark_as_read)
+    {
+        counters_.samples_read += ret_val;
+        counters_.samples_unread = 0;
+    }
+    return ret_val;
+}
+
+bool DataReaderHistory::is_instance_present(
+        const InstanceHandle_t& handle) const
+{
+    return has_keys_ && instances_.find(handle) != instances_.end();
+}
+
+std::pair<bool, DataReaderHistory::instance_info> DataReaderHistory::lookup_available_instance(
         const InstanceHandle_t& handle,
-        bool exact) const
+        bool exact)
 {
+    InstanceCollection::iterator it = data_available_instances_.end();
+
     if (!has_keys_)
     {
-        if (handle.isDefined())
+        // NO_KEY topics can only return the fictitious instance.
+        // Execution can only get here for two reasons:
+        // - Looking for a specific instance (exact = true)
+        // - Looking for the next instance to the ficticious one (exact = false)
+        // In both cases, no instance should be returned
+        if (!handle.isDefined() && !exact)
         {
-            // NO_KEY topics can only return the ficticious instance.
-            // Execution can only get here for two reasons:
-            // - Looking for a specific instance (exact = true)
-            // - Looking for the next instance to the ficticious one (exact = false)
-            // In both cases, no instance should be returned
-            return { false, {InstanceHandle_t(), nullptr} };
+            // Looking for the first instance, return the ficticious one containing all changes
+            it = data_available_instances_.begin();
         }
-
+    }
+    else
+    {
         if (exact)
         {
-            // Looking for HANDLE_NIL, nothing to return
-            return { false, {InstanceHandle_t(), nullptr} };
+            // Looking for a specific instance on a topic with key
+            it = data_available_instances_.find(handle);
+        }
+        else
+        {
+            if (!handle.isDefined())
+            {
+                // Looking for the first instance on a topic with key
+                it = data_available_instances_.begin();
+            }
+            else
+            {
+                // Looking for an instance with a handle greater than the one on the input
+                auto comp = [](const InstanceHandle_t& h, const InstanceCollection::value_type& it)
+                        {
+                            return h < it.first;
+                        };
+                it = std::upper_bound(data_available_instances_.begin(), data_available_instances_.end(), handle, comp);
+            }
         }
-
-        // Looking for the first instance, return the ficticious one containing all changes
-        InstanceHandle_t tmp;
-        tmp.value[0] = 1;
-        return { true, {tmp, const_cast<DataReaderInstance*>(&keyed_changes_.begin()->second)} };
     }
 
-    InstanceCollection::const_iterator it;
+    return { it != data_available_instances_.end(), it };
+}
 
-    if (exact)
+std::pair<bool, DataReaderHistory::instance_info> DataReaderHistory::next_available_instance_nts(
+        const InstanceHandle_t& handle,
+        const DataReaderHistory::instance_info& current_info)
+{
+    if (current_info == data_available_instances_.end())
     {
-        it = keyed_changes_.find(handle);
+        return { false, current_info };
     }
-    else
+    instance_info it = current_info;
+    if (it->first == handle)
     {
-        auto comp = [](const InstanceHandle_t& h, const std::pair<InstanceHandle_t, DataReaderInstance>& it)
-                {
-                    return h < it.first;
-                };
-        it = std::upper_bound(keyed_changes_.begin(), keyed_changes_.end(), handle, comp);
+        ++it;
     }
 
-    if (it != keyed_changes_.end())
-    {
-        return { true, {it->first, const_cast<DataReaderInstance*>(&(it->second))} };
-    }
-    return { false, {InstanceHandle_t(), nullptr} };
+    return { it != data_available_instances_.end(), it };
 }
 
 void DataReaderHistory::check_and_remove_instance(
         DataReaderHistory::instance_info& instance_info)
 {
-    DataReaderInstance* instance = instance_info.second;
-    if (instance->cache_changes.empty() &&
-            (InstanceStateKind::ALIVE_INSTANCE_STATE != instance->instance_state) &&
-            instance_info.first.isDefined())
+    if (instance_info->second->cache_changes.empty())
     {
-        keyed_changes_.erase(instance_info.first);
-        instance_info.second = nullptr;
+        if ((InstanceStateKind::ALIVE_INSTANCE_STATE != instance_info->second->instance_state) &&
+                instance_info->first.isDefined())
+        {
+            instances_.erase(instance_info->first);
+        }
+
+        instance_info = data_available_instances_.erase(instance_info);
     }
 }
 
@@ -619,23 +669,28 @@ ReaderHistory::iterator DataReaderHistor
         if (!has_keys_ || p_sample->is_fully_assembled())
         {
             // clean any references to this CacheChange in the key state collection
-            auto it = keyed_changes_.find(p_sample->instanceHandle);
+            auto it = instances_.find(p_sample->instanceHandle);
 
             // if keyed and in history must be in the map
             // There is a case when the sample could not be in the keyed map. The first received fragment of a
             // fragmented sample is stored in the history, and when it is completed it is stored in the keyed map.
             // But it can occur it is rejected when the sample is completed and removed without being stored in the
             // keyed map.
-            if (it != keyed_changes_.end())
+            if (it != instances_.end())
             {
-                auto& c = it->second.cache_changes;
-                c.erase(std::remove(c.begin(), c.end(), p_sample), c.end());
+                it->second->cache_changes.remove(p_sample);
+                if (p_sample->isRead)
+                {
+                    --counters_.samples_read;
+                }
             }
         }
     }
 
     // call the base class
-    return ReaderHistory::remove_change_nts(removal, release);
+    auto ret_val = ReaderHistory::remove_change_nts(removal, release);
+    counters_.samples_unread = mp_reader->get_unread_count();
+    return ret_val;
 }
 
 bool DataReaderHistory::completed_change(
@@ -662,7 +717,7 @@ bool DataReaderHistory::completed_change
             if (find_key(change->instanceHandle, vit))
             {
                 ret_value = !change->instanceHandle.isDefined() ||
-                        complete_fn_(change, vit->second, unknown_missing_changes_up_to, rejection_reason);
+                        complete_fn_(change, *vit->second, unknown_missing_changes_up_to, rejection_reason);
             }
             else
             {
@@ -733,28 +788,65 @@ bool DataReaderHistory::completed_change
     return ret_value;
 }
 
+void DataReaderHistory::change_was_processed_nts(
+        CacheChange_t* const change,
+        bool is_going_to_be_mark_as_read)
+{
+    if (!change->isRead && is_going_to_be_mark_as_read)
+    {
+        ++counters_.samples_read;
+        --counters_.samples_unread;
+    }
+}
+
+void DataReaderHistory::instance_viewed_nts(
+        const InstanceCollection::mapped_type& instance)
+{
+    if (ViewStateKind::NEW_VIEW_STATE == instance->view_state)
+    {
+        instance->view_state = ViewStateKind::NOT_NEW_VIEW_STATE;
+        --counters_.instances_new;
+        ++counters_.instances_not_new;
+    }
+}
+
 void DataReaderHistory::update_instance_nts(
         CacheChange_t* const change)
 {
     InstanceCollection::iterator vit;
-    vit = keyed_changes_.find(change->instanceHandle);
+    vit = instances_.find(change->instanceHandle);
 
-    assert(vit != keyed_changes_.end());
-    vit->second.update_state(change->kind, change->writerGUID);
-    change->reader_info.disposed_generation_count = vit->second.disposed_generation_count;
-    change->reader_info.no_writers_generation_count = vit->second.no_writers_generation_count;
+    assert(vit != instances_.end());
+    assert(false == change->isRead);
+    ++counters_.samples_unread;
+    vit->second->update_state(counters_, change->kind, change->writerGUID);
+    change->reader_info.disposed_generation_count = vit->second->disposed_generation_count;
+    change->reader_info.no_writers_generation_count = vit->second->no_writers_generation_count;
 }
 
 void DataReaderHistory::writer_not_alive(
-        const fastrtps::rtps::GUID_t& writer_guid)
+        const GUID_t& writer_guid)
 {
-    for (auto& it : keyed_changes_)
+    for (auto& it : instances_)
     {
-        it.second.writer_removed(writer_guid);
+        it.second->writer_removed(counters_, writer_guid);
     }
 }
 
-} // namespace detail
-} // namsepace dds
-} // namespace fastdds
-} // namsepace eprosima
+StateFilter DataReaderHistory::get_mask_status() const noexcept
+{
+    std::lock_guard<RecursiveTimedMutex> guard(*getMutex());
+
+    return {
+        static_cast<SampleStateMask>(
+            (counters_.samples_read ? READ_SAMPLE_STATE : 0) |
+            (counters_.samples_unread ? NOT_READ_SAMPLE_STATE : 0)),
+        static_cast<ViewStateMask>(
+            (counters_.instances_not_new ? NOT_NEW_VIEW_STATE : 0) |
+            (counters_.instances_new ? NEW_VIEW_STATE : 0)),
+        static_cast<InstanceStateMask>(
+            (counters_.instances_alive ? ALIVE_INSTANCE_STATE : 0) |
+            (counters_.instances_disposed ? NOT_ALIVE_DISPOSED_INSTANCE_STATE : 0) |
+            (counters_.instances_no_writers ? NOT_ALIVE_NO_WRITERS_INSTANCE_STATE : 0))
+    };
+}
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderHistory.hpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderHistory.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderHistory.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderHistory.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -22,6 +22,7 @@
 #include <chrono>
 #include <functional>
 #include <map>
+#include <memory>
 #include <utility>
 
 #include <fastdds/dds/core/policy/QosPolicies.hpp>
@@ -39,9 +40,12 @@
 #include <fastdds/rtps/history/ReaderHistory.h>
 #include <fastdds/rtps/resources/ResourceManagement.h>
 
+#include <fastdds/subscriber/DataReaderImpl/StateFilter.hpp>
+
 #include <fastrtps/utils/fixed_size_string.hpp>
 #include <fastrtps/utils/collections/ResourceLimitedContainerConfig.hpp>
 
+#include "DataReaderHistoryCounters.hpp"
 #include "DataReaderInstance.hpp"
 
 namespace eprosima {
@@ -62,10 +66,13 @@ public:
     using GUID_t = eprosima::fastrtps::rtps::GUID_t;
     using SequenceNumber_t = eprosima::fastrtps::rtps::SequenceNumber_t;
 
-    using instance_info = std::pair<InstanceHandle_t, DataReaderInstance*>;
+    using InstanceCollection = std::map<InstanceHandle_t, std::shared_ptr<DataReaderInstance>>;
+    using instance_info = InstanceCollection::iterator;
 
     /**
-     * Constructor. Requires information about the DataReader.
+     * Constructor.
+     * Requires information about the DataReader.
+     *
      * @param type  Type information. Needed to know if the type is keyed, as long as the maximum serialized size.
      * @param topic Topic description. Topic and type name are used on debug messages.
      * @param qos   DataReaderQoS policy. History related limits are taken from here.
@@ -79,9 +86,11 @@ public:
 
     /**
      * Remove a specific change from the history.
-     * No Thread Safe
+     * No Thread Safe.
+     *
      * @param removal iterator to the CacheChange_t to remove.
      * @param release defaults to true and hints if the CacheChange_t should return to the pool
+     *
      * @return iterator to the next CacheChange_t or end iterator.
      */
     iterator remove_change_nts(
@@ -109,23 +118,31 @@ public:
             bool& will_never_be_accepted) const override;
 
     /**
-     * Called when a change is received by the Subscriber. Will add the change to the history.
+     * Called when a change is received by the RTPS reader.
+     * Will add the change to the history.
+     *
      * @pre Change should not be already present in the history.
+     *
      * @param[in] change The received change
      * @param unknown_missing_changes_up_to Number of missing changes before this one
-     * @return
+     *
+     * @return Whether the operation succeeded.
      */
     bool received_change(
             CacheChange_t* change,
             size_t unknown_missing_changes_up_to) override;
 
-    /*!
-     * Called when a change is received by the Subscriber. Will add the change to the history.
+    /**
+     * Called when a change is received by the RTPS reader.
+     * Will add the change to the history.
+     *
      * @pre Change should not be already present in the history.
+     *
      * @param[in] change The received change
      * @param[in] unknown_missing_changes_up_to Number of missing changes before this one
      * @param[out] rejection_reason In case of been rejected the sample, it will contain the reason of the rejection.
-     * @return
+     *
+     * @return Whether the operation succeeded.
      */
     bool received_change(
             CacheChange_t* change,
@@ -133,22 +150,29 @@ public:
             SampleRejectedStatusKind& rejection_reason) override;
 
     /**
-     * Called when a fragmented change is received completely by the Subscriber. Will find its instance and store it.
+     * Called when a fragmented change is received completely by the RTPS reader.
+     * Will find its instance and store it.
+     *
      * @pre Change should be already present in the history.
+     *
      * @param[in] change The received change
-     * @param[in] unknown_missing_changes_up_to Number of missing changes before this one
-     * @return
+     *
+     * @return Whether the operation succeeded.
      */
     bool completed_change(
             CacheChange_t* change) override;
 
-    /*!
-     * Called when a fragmented change is received completely by the Subscriber. Will find its instance and store it.
+    /**
+     * Called when a fragmented change is received completely by the RTPS reader.
+     * Will find its instance and store it.
+     *
      * @pre Change should be already present in the history.
+     *
      * @param[in] change The received change
      * @param[in] unknown_missing_changes_up_to Number of missing changes before this one
      * @param[out] rejection_reason In case of been rejected the sample, it will contain the reason of the rejection.
-     * @return
+     *
+     * @return Whether the operation succeeded.
      */
     bool completed_change(
             CacheChange_t* change,
@@ -157,24 +181,30 @@ public:
 
     /**
      * @brief Returns information about the first untaken sample.
+     *
      * @param [out] info SampleInfo structure to store first untaken sample information.
-     * @return true if sample info was returned. false if there is no sample to take.
+     *
+     * @return true if sample info was returned, false if there is no sample to take.
      */
     bool get_first_untaken_info(
             SampleInfo& info);
 
     /**
-     * This method is called to remove a change from the SubscriberHistory.
+     * This method is called to remove a change from the DataReaderHistory.
+     *
      * @param change Pointer to the CacheChange_t.
+     *
      * @return True if removed.
      */
     bool remove_change_sub(
             CacheChange_t* change);
 
     /**
-     * This method is called to remove a change from the SubscriberHistory.
+     * This method is called to remove a change from the DataReaderHistory.
+     *
      * @param [in]     change Pointer to the CacheChange_t.
      * @param [in,out] it     Iterator pointing to change on input. Will point to next valid change on output.
+     *
      * @return True if removed.
      */
     bool remove_change_sub(
@@ -195,9 +225,11 @@ public:
             const SequenceNumber_t& last_notified_seq) override;
 
     /**
-     * @brief A method to set the next deadline for the given instance
+     * @brief A method to set the next deadline for the given instance.
+     *
      * @param handle The handle to the instance
      * @param next_deadline_us The time point when the deadline will occur
+     *
      * @return True if the deadline was set correctly
      */
     bool set_next_deadline(
@@ -205,9 +237,11 @@ public:
             const std::chrono::steady_clock::time_point& next_deadline_us);
 
     /**
-     * @brief A method to get the next instance handle that will miss the deadline and the time when the deadline will occur
+     * @brief A method to get the next instance handle that will miss the deadline and the time when the deadline will occur.
+     *
      * @param handle The handle to the instance
      * @param next_deadline_us The time point when the instance will miss the deadline
+     *
      * @return True if the deadline was retrieved successfully
      */
     bool get_next_deadline(
@@ -215,22 +249,77 @@ public:
             std::chrono::steady_clock::time_point& next_deadline_us);
 
     /**
-     * @brief Get the list of changes corresponding to an instance handle.
+     * Get the number of samples pending to be read.
+     *
+     * @param mark_as_read  Whether the unread samples should be marked as read or not.
+     *
+     * @return the number of samples on the reader history that have never been read.
+     */
+    uint64_t get_unread_count(
+            bool mark_as_read);
+
+    /**
+     * @brief Check whether an instance handle is present in the history.
+     *
+     * @param handle The handle of the instance to check.
+     *
+     * @return true when the topic has keys and the handle corresponds to an instance present in the history.
+     * @return false otherwise.
+     */
+    bool is_instance_present(
+            const InstanceHandle_t& handle) const;
+
+    /**
+     * @brief Get an iterator to an instance with available data.
+     *
      * @param handle The handle to the instance.
      * @param exact  Indicates if the handle should match exactly (true) or if the first instance greater than the
      *               input handle should be returned.
+     *
      * @return A pair where:
      *         - @c first is a boolean indicating if an instance was found
-     *         - @c second is a pair where:
-     *           - @c first is the handle of the returned instance
-     *           - @c second is a pointer to a DataReaderInstance that holds information about the returned instance
+     *         - @c second is an iterator to the data available instances collection
      *
      * @remarks When used on a NO_KEY topic, an instance will only be returned when called with
      *          `handle = HANDLE_NIL` and `exact = false`.
      */
-    std::pair<bool, instance_info> lookup_instance(
+    std::pair<bool, instance_info> lookup_available_instance(
             const InstanceHandle_t& handle,
-            bool exact) const;
+            bool exact);
+
+    /**
+     * @brief Given an instance advance the iterator to the next instance with available data.
+     *
+     * @param handle        The handle of the instance returned by a previous call to lookup_available_instance or
+     *                      next_available_instance_nts.
+     * @param current_info  The iterator to be advanced.
+     *
+     * @return A pair where:
+     *         - @c first is a boolean indicating if another instance with available data is present
+     *         - @c second is an iterator pointing to the next instance with available data
+     */
+    std::pair<bool, instance_info> next_available_instance_nts(
+            const InstanceHandle_t& handle,
+            const instance_info& current_info);
+
+    /**
+     * This method is meant to be called just before calling @c end_sample_access_nts on the RTPS reader.
+     * It will update the internal counters of unread and read samples.
+     *
+     * @param change                       Pointer to the cache change that has been processed.
+     * @param is_going_to_be_mark_as_read  Whether the change is going to be marked as read.
+     */
+    void change_was_processed_nts(
+            CacheChange_t* const change,
+            bool is_going_to_be_mark_as_read);
+
+    /**
+     * Mark that a DataReaderInstance has been viewed.
+     *
+     * @param instance        Instance on which the view state should be modified.
+     */
+    void instance_viewed_nts(
+            const InstanceCollection::mapped_type& instance);
 
     void update_instance_nts(
             CacheChange_t* const change);
@@ -241,16 +330,18 @@ public:
     void check_and_remove_instance(
             instance_info& instance_info);
 
-private:
+    StateFilter get_mask_status() const noexcept;
 
-    using InstanceCollection = std::map<InstanceHandle_t, DataReaderInstance>;
+private:
 
     //!Resource limits for allocating the array of changes per instance
     eprosima::fastrtps::ResourceLimitedContainerConfig key_changes_allocation_;
     //!Resource limits for allocating the array of alive writers per instance
     eprosima::fastrtps::ResourceLimitedContainerConfig key_writers_allocation_;
-    //!Map where keys are instance handles and values vectors of cache changes
-    InstanceCollection keyed_changes_;
+    //!Collection of DataReaderInstance objects accessible by their handle
+    InstanceCollection instances_;
+    //!Collection of DataReaderInstance objects with available data, accessible by their handle
+    InstanceCollection data_available_instances_;
     //!HistoryQosPolicy values.
     HistoryQosPolicy history_qos_;
     //!ResourceLimitsQosPolicy values.
@@ -274,6 +365,9 @@ private:
     /// Function processing a completed fragmented change
     std::function<bool(CacheChange_t*, DataReaderInstance&, size_t, SampleRejectedStatusKind&)> complete_fn_;
 
+    /// Book-keeping counters for ReadCondition support
+    DataReaderHistoryCounters counters_;
+
     /**
      * @brief Method that finds a key in m_keyedChanges or tries to add it if not found
      * @param a_change The change to get the key from
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderInstance.hpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderInstance.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/history/DataReaderInstance.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/history/DataReaderInstance.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -28,6 +28,7 @@
 #include <fastrtps/utils/collections/ResourceLimitedVector.hpp>
 
 #include "DataReaderCacheChange.hpp"
+#include "DataReaderHistoryCounters.hpp"
 
 namespace eprosima {
 namespace fastdds {
@@ -67,29 +68,39 @@ struct DataReaderInstance
     }
 
     bool update_state(
+            DataReaderHistoryCounters& counters,
             const fastrtps::rtps::ChangeKind_t change_kind,
             const fastrtps::rtps::GUID_t& writer_guid,
             const uint32_t ownership_strength = 0)
     {
         bool ret_val = false;
 
+        if (!has_been_accounted)
+        {
+            has_been_accounted = true;
+            assert(ViewStateKind::NEW_VIEW_STATE == view_state);
+            ++counters.instances_new;
+            assert(InstanceStateKind::ALIVE_INSTANCE_STATE == instance_state);
+            ++counters.instances_alive;
+        }
+
         switch (change_kind)
         {
             case fastrtps::rtps::ALIVE:
-                ret_val = writer_alive(writer_guid, ownership_strength);
+                ret_val = writer_alive(counters, writer_guid, ownership_strength);
                 break;
 
             case fastrtps::rtps::NOT_ALIVE_DISPOSED:
-                ret_val = writer_dispose(writer_guid, ownership_strength);
+                ret_val = writer_dispose(counters, writer_guid, ownership_strength);
                 break;
 
             case fastrtps::rtps::NOT_ALIVE_DISPOSED_UNREGISTERED:
-                ret_val = writer_dispose(writer_guid, ownership_strength);
-                ret_val |= writer_unregister(writer_guid);
+                ret_val = writer_dispose(counters, writer_guid, ownership_strength);
+                ret_val |= writer_unregister(counters, writer_guid);
                 break;
 
             case fastrtps::rtps::NOT_ALIVE_UNREGISTERED:
-                ret_val = writer_unregister(writer_guid);
+                ret_val = writer_unregister(counters, writer_guid);
                 break;
 
             default:
@@ -101,14 +112,19 @@ struct DataReaderInstance
     }
 
     bool writer_removed(
+            DataReaderHistoryCounters& counters,
             const fastrtps::rtps::GUID_t& writer_guid)
     {
-        return writer_unregister(writer_guid);
+        return writer_unregister(counters, writer_guid);
     }
 
 private:
 
+    //! Whether this instance has ever been included in the history counters
+    bool has_been_accounted = false;
+
     bool writer_alive(
+            DataReaderHistoryCounters& counters,
             const fastrtps::rtps::GUID_t& writer_guid,
             const uint32_t ownership_strength)
     {
@@ -121,6 +137,8 @@ private:
 
             if (InstanceStateKind::NOT_ALIVE_DISPOSED_INSTANCE_STATE == instance_state)
             {
+                counters_update(counters.instances_disposed, counters.instances_alive, counters, true);
+
                 ++disposed_generation_count;
                 alive_writers.clear();
                 view_state = ViewStateKind::NEW_VIEW_STATE;
@@ -128,6 +146,8 @@ private:
             }
             else if (InstanceStateKind::NOT_ALIVE_NO_WRITERS_INSTANCE_STATE == instance_state)
             {
+                counters_update(counters.instances_no_writers, counters.instances_alive, counters, true);
+
                 ++no_writers_generation_count;
                 alive_writers.clear();
                 view_state = ViewStateKind::NEW_VIEW_STATE;
@@ -142,6 +162,7 @@ private:
     }
 
     bool writer_dispose(
+            DataReaderHistoryCounters& counters,
             const fastrtps::rtps::GUID_t& writer_guid,
             const uint32_t ownership_strength)
     {
@@ -157,6 +178,7 @@ private:
             {
                 ret_val = true;
                 instance_state = InstanceStateKind::NOT_ALIVE_DISPOSED_INSTANCE_STATE;
+                counters_update(counters.instances_alive, counters.instances_disposed, counters, false);
             }
         }
 
@@ -164,6 +186,7 @@ private:
     }
 
     bool writer_unregister(
+            DataReaderHistoryCounters& counters,
             const fastrtps::rtps::GUID_t& writer_guid)
     {
         bool ret_val = false;
@@ -183,6 +206,7 @@ private:
         {
             ret_val = true;
             instance_state = InstanceStateKind::NOT_ALIVE_NO_WRITERS_INSTANCE_STATE;
+            counters_update(counters.instances_alive, counters.instances_no_writers, counters, false);
         }
 
         return ret_val;
@@ -206,6 +230,21 @@ private:
         }
     }
 
+    void counters_update(
+            uint64_t& decremented_counter,
+            uint64_t& incremented_counter,
+            DataReaderHistoryCounters& counters,
+            bool set_as_new_view_state)
+    {
+        --decremented_counter;
+        ++incremented_counter;
+        if (set_as_new_view_state && (ViewStateKind::NEW_VIEW_STATE != view_state))
+        {
+            ++counters.instances_new;
+            --counters.instances_not_new;
+        }
+    }
+
 };
 
 } /* namespace detail */
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/ReadCondition.cpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/ReadCondition.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/ReadCondition.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/ReadCondition.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -16,28 +16,11 @@
  * @file ReadCondition.cpp
  */
 
-#include <fastdds/dds/subscriber/ReadCondition.hpp>
-#include <fastdds/dds/subscriber/InstanceState.hpp>
-#include <fastdds/dds/subscriber/SampleState.hpp>
-#include <fastdds/dds/subscriber/ViewState.hpp>
+#include <fastdds/subscriber/ReadConditionImpl.hpp>
 
-namespace eprosima {
-namespace fastdds {
-namespace dds {
+using namespace eprosima::fastdds::dds;
 
-namespace detail {
-
-struct ReadConditionImpl
-{
-};
-
-}  // namespace detail
-
-
-ReadCondition::ReadCondition(
-        DataReader* /*parent*/)
-    : Condition()
-    , impl_(new detail::ReadConditionImpl())
+ReadCondition::ReadCondition()
 {
 }
 
@@ -45,31 +28,32 @@ ReadCondition::~ReadCondition()
 {
 }
 
-bool ReadCondition::get_trigger_value() const
+bool ReadCondition::get_trigger_value() const noexcept
 {
-    return false;
+    assert((bool)impl_);
+    return impl_->get_trigger_value();
 }
 
-DataReader* ReadCondition::get_datareader() const
+DataReader* ReadCondition::get_datareader() const noexcept
 {
-    return nullptr;
+    assert((bool)impl_);
+    return impl_->get_datareader();
 }
 
-SampleStateMask ReadCondition::get_sample_state_mask() const
+SampleStateMask ReadCondition::get_sample_state_mask() const noexcept
 {
-    return ANY_SAMPLE_STATE;
+    assert((bool)impl_);
+    return impl_->get_sample_state_mask();
 }
 
-ViewStateMask ReadCondition::get_view_state_mask() const
+ViewStateMask ReadCondition::get_view_state_mask() const noexcept
 {
-    return ANY_VIEW_STATE;
+    assert((bool)impl_);
+    return impl_->get_view_state_mask();
 }
 
-InstanceStateMask ReadCondition::get_instance_state_mask() const
+InstanceStateMask ReadCondition::get_instance_state_mask() const noexcept
 {
-    return ANY_INSTANCE_STATE;
+    assert((bool)impl_);
+    return impl_->get_instance_state_mask();
 }
-
-} // namespace dds
-} // namespace fastdds
-} // namespace eprosima
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/ReadConditionImpl.hpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/ReadConditionImpl.hpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/ReadConditionImpl.hpp	1970-01-01 00:00:00.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/ReadConditionImpl.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -0,0 +1,233 @@
+// Copyright 2022 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 ReadConditionImpl.hpp
+ */
+
+#include <algorithm>
+#include <forward_list>
+#include <memory>
+#include <mutex>
+
+#include <fastdds/core/condition/ConditionNotifier.hpp>
+#include <fastdds/dds/subscriber/InstanceState.hpp>
+#include <fastdds/dds/subscriber/ReadCondition.hpp>
+#include <fastdds/dds/subscriber/SampleState.hpp>
+#include <fastdds/dds/subscriber/ViewState.hpp>
+#include <fastdds/subscriber/DataReaderImpl.hpp>
+#include <fastdds/subscriber/DataReaderImpl/StateFilter.hpp>
+
+#ifndef _FASTDDS_READCONDITIONIMPL_HPP_
+#define _FASTDDS_READCONDITIONIMPL_HPP_
+#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
+
+namespace eprosima {
+namespace fastdds {
+namespace dds {
+namespace detail {
+
+using fastrtps::types::ReturnCode_t;
+
+class ReadConditionImpl : public std::enable_shared_from_this<ReadConditionImpl>
+{
+    DataReaderImpl& data_reader_;
+    const StateFilter state_;
+    std::recursive_mutex& mutex_;
+    std::forward_list<const ReadCondition*> conditions_;
+
+    using length = std::forward_list<const ReadCondition*>::difference_type;
+
+public:
+
+    ReadConditionImpl(
+            DataReaderImpl& data_reader,
+            const StateFilter& state)
+        : data_reader_(data_reader)
+        , state_(state)
+        , mutex_(data_reader.get_conditions_mutex())
+    {
+    }
+
+    ~ReadConditionImpl()
+    {
+        // On destruction no ReadCondition should be associated
+        assert(conditions_.empty());
+    }
+
+    /**
+     * Detach all ReadConditions from this object.
+     */
+    void detach_all_conditions() noexcept
+    {
+        std::lock_guard<std::recursive_mutex> _(mutex_);
+
+        if (conditions_.empty())
+        {
+            return;
+        }
+
+        auto keep_alive_in_stack = shared_from_this();
+
+        for (const ReadCondition* cond : conditions_)
+        {
+            delete cond;
+        }
+
+        conditions_.clear();
+    }
+
+    bool get_trigger_value(
+            const StateFilter& state) const noexcept
+    {
+        return state.sample_states & state_.sample_states &&
+               state.view_states & state_.view_states &&
+               state.instance_states & state_.instance_states;
+    }
+
+    bool get_trigger_value() const noexcept
+    {
+        try
+        {
+            return get_trigger_value(data_reader_.get_last_mask_state());
+        }
+        catch (std::runtime_error& e)
+        {
+            // DataReader not enabled yet
+            logWarning(READCONDITION, e.what());
+            return false;
+        }
+    }
+
+    DataReader* get_datareader() const noexcept
+    {
+        return data_reader_.user_datareader_;
+    }
+
+    const SampleStateMask& get_sample_state_mask() const noexcept
+    {
+        return state_.sample_states;
+    }
+
+    const ViewStateMask& get_view_state_mask() const noexcept
+    {
+        return state_.view_states;
+    }
+
+    const InstanceStateMask& get_instance_state_mask() const noexcept
+    {
+        return state_.instance_states;
+    }
+
+    /**
+     * Attach a new ReadCondition to this object.
+     * @param [in] pRC reader to attach
+     * @return RETCODE_OK on success
+     */
+    ReturnCode_t attach_condition(
+            ReadCondition* pRC)
+    {
+        using namespace std;
+
+        lock_guard<recursive_mutex> _(mutex_);
+
+        auto it = conditions_.begin();
+        auto pit = conditions_.before_begin();
+
+        while (it != conditions_.end())
+        {
+            if (*it < pRC)
+            {
+                pit = it++;
+            }
+            else if ( *it == pRC )
+            {
+                // already there
+                return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        // insert
+        conditions_.insert_after(pit, pRC);
+
+        // associate
+        pRC->impl_ = shared_from_this();
+
+        return ReturnCode_t::RETCODE_OK;
+    }
+
+    /**
+     * Detach a ReadCondition from this object.
+     * @param [in] pRC reader to detach
+     * @return RETCODE_OK on success
+     */
+    ReturnCode_t detach_condition(
+            ReadCondition* pRC) noexcept
+    {
+        using namespace std;
+
+        lock_guard<recursive_mutex> _(mutex_);
+
+        auto it = conditions_.begin();
+        auto pit = conditions_.before_begin();
+
+        while (it != conditions_.end())
+        {
+            if (*it < pRC)
+            {
+                pit = it++;
+            }
+            else if ( *it == pRC )
+            {
+                conditions_.erase_after(pit);
+
+                return ReturnCode_t::RETCODE_OK;
+            }
+            else
+            {
+                break;
+            }
+        }
+
+        return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
+    }
+
+    /**
+     * Notify all the associated ReadConditions
+     */
+    void notify() const noexcept
+    {
+        std::lock_guard<std::recursive_mutex> _(mutex_);
+
+        for (auto cond : conditions_)
+        {
+            auto pN = cond->get_notifier();
+            assert(nullptr != pN);
+            pN->notify();
+        }
+    }
+
+};
+
+} // namespace detail
+} // namespace dds
+} // namespace fastdds
+} // namespace eprosima
+
+#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
+#endif /* _FASTDDS_READCONDITIONIMPL_HPP_ */
diff -pruN 2.7.0+ds-2/src/cpp/fastdds/subscriber/SubscriberImpl.cpp 2.7.1+ds-1/src/cpp/fastdds/subscriber/SubscriberImpl.cpp
--- 2.7.0+ds-2/src/cpp/fastdds/subscriber/SubscriberImpl.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastdds/subscriber/SubscriberImpl.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -309,7 +309,7 @@ ReturnCode_t SubscriberImpl::delete_data
         {
             //First extract the reader from the maps to free the mutex
             DataReaderImpl* reader_impl = *dr_it;
-            if (!reader_impl->can_be_deleted())
+            if (!reader_impl->can_be_deleted(false))
             {
                 return ReturnCode_t::RETCODE_PRECONDITION_NOT_MET;
             }
diff -pruN 2.7.0+ds-2/src/cpp/fastrtps_deprecated/subscriber/SubscriberHistory.cpp 2.7.1+ds-1/src/cpp/fastrtps_deprecated/subscriber/SubscriberHistory.cpp
--- 2.7.0+ds-2/src/cpp/fastrtps_deprecated/subscriber/SubscriberHistory.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/fastrtps_deprecated/subscriber/SubscriberHistory.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -28,6 +28,8 @@
 #include <fastdds/rtps/reader/RTPSReader.h>
 
 #include <fastrtps_deprecated/subscriber/SubscriberImpl.h>
+
+#include <rtps/common/ChangeComparison.hpp>
 #include <rtps/reader/WriterProxy.h>
 #include <utils/collections/sorted_vector_insert.hpp>
 
@@ -348,10 +350,7 @@ bool SubscriberHistory::add_received_cha
 
         //ADD TO KEY VECTOR
         eprosima::utilities::collections::sorted_vector_insert(instance_changes, a_change,
-                [](const CacheChange_t* lhs, const CacheChange_t* rhs)
-                {
-                    return lhs->sourceTimestamp < rhs->sourceTimestamp;
-                });
+                fastdds::rtps::history_order_cmp);
 
         logInfo(SUBSCRIBER, mp_reader->getGuid().entityId
                 << ": Change " << a_change->sequenceNumber << " added from: "
@@ -745,10 +744,7 @@ bool SubscriberHistory::completed_change
             {
                 //ADD TO KEY VECTOR
                 eprosima::utilities::collections::sorted_vector_insert(instance_changes, a_change,
-                        [](const CacheChange_t* lhs, const CacheChange_t* rhs)
-                        {
-                            return lhs->sourceTimestamp < rhs->sourceTimestamp;
-                        });
+                        fastdds::rtps::history_order_cmp);
                 ret_value = true;
 
                 logInfo(SUBSCRIBER, mp_reader->getGuid().entityId
@@ -804,10 +800,7 @@ bool SubscriberHistory::completed_change
             {
                 //ADD TO KEY VECTOR
                 eprosima::utilities::collections::sorted_vector_insert(instance_changes, a_change,
-                        [](const CacheChange_t* lhs, const CacheChange_t* rhs)
-                        {
-                            return lhs->sourceTimestamp < rhs->sourceTimestamp;
-                        });
+                        fastdds::rtps::history_order_cmp);
                 ret_value = true;
 
                 logInfo(SUBSCRIBER, mp_reader->getGuid().entityId
diff -pruN 2.7.0+ds-2/src/cpp/rtps/builtin/data/WriterProxyData.cpp 2.7.1+ds-1/src/cpp/rtps/builtin/data/WriterProxyData.cpp
--- 2.7.0+ds-2/src/cpp/rtps/builtin/data/WriterProxyData.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/builtin/data/WriterProxyData.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -1023,6 +1023,10 @@ bool WriterProxyData::readFromCDRMessage
 
 void WriterProxyData::clear()
 {
+#if HAVE_SECURITY
+    security_attributes_ = 0UL;
+    plugin_security_attributes_ = 0UL;
+#endif // if HAVE_SECURITY
     m_guid = c_Guid_Unknown;
     remote_locators_.unicast.clear();
     remote_locators_.multicast.clear();
diff -pruN 2.7.0+ds-2/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp 2.7.1+ds-1/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp
--- 2.7.0+ds-2/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -571,16 +571,17 @@ bool EDP::unpairWriterProxy(
 #endif // if HAVE_SECURITY
 
                     //MATCHED AND ADDED CORRECTLY:
-                    if (r.getListener() != nullptr)
+                    ReaderListener* listener = nullptr;
+                    if (nullptr != (listener = r.getListener()))
                     {
                         MatchingInfo info;
                         info.status = REMOVED_MATCHING;
                         info.remoteEndpointGuid = writer_guid;
-                        r.getListener()->onReaderMatched(&r, info);
+                        listener->onReaderMatched(&r, info);
 
                         const SubscriptionMatchedStatus& sub_info =
                         update_subscription_matched_status(reader_guid, writer_guid, -1);
-                        r.getListener()->onReaderMatched(&r, sub_info);
+                        listener->onReaderMatched(&r, sub_info);
                     }
                 }
 
@@ -609,16 +610,17 @@ bool EDP::unpairReaderProxy(
                     participant_guid, reader_guid);
 #endif // if HAVE_SECURITY
                     //MATCHED AND ADDED CORRECTLY:
-                    if (w.getListener() != nullptr)
+                    WriterListener* listener = nullptr;
+                    if (nullptr != (listener = w.getListener()))
                     {
                         MatchingInfo info;
                         info.status = REMOVED_MATCHING;
                         info.remoteEndpointGuid = reader_guid;
-                        w.getListener()->onWriterMatched(&w, info);
+                        listener->onWriterMatched(&w, info);
 
                         const PublicationMatchedStatus& pub_info =
                         update_publication_matched_status(reader_guid, writer_guid, -1);
-                        w.getListener()->onWriterMatched(&w, pub_info);
+                        listener->onWriterMatched(&w, pub_info);
                     }
                 }
 
diff -pruN 2.7.0+ds-2/src/cpp/rtps/common/ChangeComparison.hpp 2.7.1+ds-1/src/cpp/rtps/common/ChangeComparison.hpp
--- 2.7.0+ds-2/src/cpp/rtps/common/ChangeComparison.hpp	1970-01-01 00:00:00.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/common/ChangeComparison.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -0,0 +1,41 @@
+// Copyright 2022 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 ChangeComparison.hpp
+ */
+
+#ifndef _RTPS_COMMON_CHANGECOMPARISON_HPP
+#define _RTPS_COMMON_CHANGECOMPARISON_HPP
+
+#include <fastdds/rtps/common/CacheChange.h>
+
+namespace eprosima {
+namespace fastdds {
+namespace rtps {
+
+inline bool history_order_cmp(
+        const eprosima::fastrtps::rtps::CacheChange_t* lhs,
+        const eprosima::fastrtps::rtps::CacheChange_t* rhs)
+{
+    return lhs->writerGUID == rhs->writerGUID ?
+           lhs->sequenceNumber < rhs->sequenceNumber :
+           lhs->sourceTimestamp < rhs->sourceTimestamp;
+}
+
+} /* namespace rtps */
+} /* namespace fastdds */
+} /* namespace eprosima */
+
+#endif  // _RTPS_COMMON_CHANGECOMPARISON_HPP
diff -pruN 2.7.0+ds-2/src/cpp/rtps/history/CacheChangePool.cpp 2.7.1+ds-1/src/cpp/rtps/history/CacheChangePool.cpp
--- 2.7.0+ds-2/src/cpp/rtps/history/CacheChangePool.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/history/CacheChangePool.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -106,6 +106,7 @@ void CacheChangePool::return_cache_to_po
     ch->setFragmentSize(0);
     ch->inline_qos.pos = 0;
     ch->inline_qos.length = 0;
+    assert(free_caches_.end() == std::find(free_caches_.begin(), free_caches_.end(), ch));
     free_caches_.push_back(ch);
 }
 
diff -pruN 2.7.0+ds-2/src/cpp/rtps/history/ReaderHistory.cpp 2.7.1+ds-1/src/cpp/rtps/history/ReaderHistory.cpp
--- 2.7.0+ds-2/src/cpp/rtps/history/ReaderHistory.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/history/ReaderHistory.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -24,6 +24,7 @@
 #include <fastdds/rtps/reader/RTPSReader.h>
 #include <fastdds/rtps/reader/ReaderListener.h>
 
+#include <rtps/common/ChangeComparison.hpp>
 #include <utils/collections/sorted_vector_insert.hpp>
 
 #include <mutex>
@@ -103,11 +104,7 @@ bool ReaderHistory::add_change(
         logError(RTPS_READER_HISTORY, "The Writer GUID_t must be defined");
     }
 
-    eprosima::utilities::collections::sorted_vector_insert(m_changes, a_change,
-            [](const CacheChange_t* lhs, const CacheChange_t* rhs)
-            {
-                return lhs->sourceTimestamp < rhs->sourceTimestamp;
-            });
+    eprosima::utilities::collections::sorted_vector_insert(m_changes, a_change, fastdds::rtps::history_order_cmp);
     logInfo(RTPS_READER_HISTORY,
             "Change " << a_change->sequenceNumber << " added with " << a_change->serializedPayload.length << " bytes");
 
diff -pruN 2.7.0+ds-2/src/cpp/rtps/participant/RTPSParticipantImpl.h 2.7.1+ds-1/src/cpp/rtps/participant/RTPSParticipantImpl.h
--- 2.7.0+ds-2/src/cpp/rtps/participant/RTPSParticipantImpl.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/participant/RTPSParticipantImpl.h	2022-07-28 07:22:18.000000000 +0000
@@ -28,9 +28,6 @@
 #include <mutex>
 #include <sys/types.h>
 
-#include <fastrtps/utils/Semaphore.h>
-#include <fastrtps/utils/shared_mutex.hpp>
-
 #if defined(_WIN32)
 #include <process.h>
 #else
@@ -68,6 +65,9 @@
 #include <rtps/security/SecurityManager.h>
 #endif // if HAVE_SECURITY
 
+#include <fastrtps/utils/Semaphore.h>
+#include <fastrtps/utils/shared_mutex.hpp>
+
 namespace eprosima {
 
 namespace fastdds {
diff -pruN 2.7.0+ds-2/src/cpp/rtps/reader/RTPSReader.cpp 2.7.1+ds-1/src/cpp/rtps/reader/RTPSReader.cpp
--- 2.7.0+ds-2/src/cpp/rtps/reader/RTPSReader.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/reader/RTPSReader.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -367,6 +367,29 @@ uint64_t RTPSReader::get_unread_count()
     return total_unread_;
 }
 
+uint64_t RTPSReader::get_unread_count(
+        bool mark_as_read)
+{
+    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
+    uint64_t ret_val = total_unread_;
+
+    if (mark_as_read)
+    {
+        for (auto it = mp_history->changesBegin(); 0 < total_unread_ && it != mp_history->changesEnd(); ++it)
+        {
+            CacheChange_t* change = *it;
+            if (!change->isRead && get_last_notified(change->writerGUID) >= change->sequenceNumber)
+            {
+                change->isRead = true;
+                assert(0 < total_unread_);
+                --total_unread_;
+            }
+        }
+        assert(0 == total_unread_);
+    }
+    return ret_val;
+}
+
 bool RTPSReader::is_datasharing_compatible_with(
         const WriterProxyData& wdata)
 {
diff -pruN 2.7.0+ds-2/src/cpp/rtps/reader/StatefulReader.cpp 2.7.1+ds-1/src/cpp/rtps/reader/StatefulReader.cpp
--- 2.7.0+ds-2/src/cpp/rtps/reader/StatefulReader.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/reader/StatefulReader.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -540,7 +540,9 @@ bool StatefulReader::processDataMsg(
             CacheChange_t* change_to_add = nullptr;
             if (!change_pool_->reserve_cache(change_to_add))
             {
-                logError(RTPS_MSG_IN, IDSTRING "Problem reserving CacheChange in reader: " << m_guid);
+                logWarning(RTPS_MSG_IN,
+                        IDSTRING "Reached the maximum number of samples allowed by this reader's QoS. Rejecting change for reader: " <<
+                        m_guid );
                 return false;
             }
 
@@ -929,7 +931,21 @@ bool StatefulReader::change_removed_by_h
                 {
                     --total_unread_;
                 }
+            }
+
+            WriterProxy* proxy = wp;
+
+            if (nullptr == proxy)
+            {
+                if (!findWriterProxy(a_change->writerGUID, &proxy))
+                {
+                    return false;
+                }
+            }
 
+            if (nullptr != proxy)
+            {
+                send_ack_if_datasharing(this, mp_history, proxy, a_change->sequenceNumber);
             }
         }
         else
@@ -1000,9 +1016,17 @@ bool StatefulReader::change_received(
                         // initialized using this SequenceNumber_t. Note that on a SERVER the own DATA(p) may be in any
                         // position within the WriterHistory preventing effective data exchange.
                         update_last_notified(a_change->writerGUID, SequenceNumber_t(0, 1));
-                        if (getListener() != nullptr)
+                        auto listener = getListener();
+                        if (listener != nullptr)
                         {
-                            getListener()->onNewCacheChangeAdded((RTPSReader*)this, a_change);
+                            bool notify_single = false;
+                            auto guid = a_change->writerGUID;
+                            auto seq = a_change->sequenceNumber;
+                            listener->on_data_available(this, guid, seq, seq, notify_single);
+                            if (notify_single)
+                            {
+                                listener->onNewCacheChangeAdded(this, a_change);
+                            }
                         }
 
                         return true;
@@ -1081,38 +1105,67 @@ bool StatefulReader::change_received(
 void StatefulReader::NotifyChanges(
         WriterProxy* prox)
 {
+    CacheChange_t* aux_ch = nullptr;
     GUID_t proxGUID = prox->guid();
-    update_last_notified(proxGUID, prox->available_changes_max());
-    SequenceNumber_t nextChangeToNotify = prox->next_cache_change_to_be_notified();
+    SequenceNumber_t max_seq = prox->available_changes_max();
+    SequenceNumber_t first_seq = prox->next_cache_change_to_be_notified();
+
+    bool new_data_available = false;
 
-    while (nextChangeToNotify != SequenceNumber_t::unknown())
+    // Update state before notifying
+    update_last_notified(proxGUID, max_seq);
+    History::const_iterator it = mp_history->changesBegin();
+    SequenceNumber_t next_seq = first_seq;
+    while (next_seq != c_SequenceNumber_Unknown &&
+            mp_history->changesEnd() != (it = mp_history->get_change_nts(next_seq, proxGUID, &aux_ch, it)) &&
+            (*it)->sequenceNumber <= max_seq)
     {
-        CacheChange_t* ch_to_give = nullptr;
+        aux_ch = *it;
+        assert(false == aux_ch->isRead);
+        new_data_available = true;
+        ++total_unread_;
+        on_data_notify(proxGUID, aux_ch->sourceTimestamp);
 
-        if (mp_history->get_change(nextChangeToNotify, proxGUID, &ch_to_give))
+        ++it;
+        do
         {
-            if (!ch_to_give->isRead)
-            {
-                ++total_unread_;
+            next_seq = prox->next_cache_change_to_be_notified();
+        } while (next_seq != c_SequenceNumber_Unknown && next_seq <= aux_ch->sequenceNumber);
+    }
+    // Ensure correct state of proxy when max_seq is not present in history
+    while (c_SequenceNumber_Unknown != prox->next_cache_change_to_be_notified())
+    {
+    }
 
-                on_data_notify(ch_to_give->writerGUID, ch_to_give->sourceTimestamp);
+    // Notify listener if new data is available
+    auto listener = getListener();
+    if (new_data_available && (nullptr != listener))
+    {
+        bool notify_individual = false;
+        listener->on_data_available(this, proxGUID, first_seq, max_seq, notify_individual);
 
-                if (getListener() != nullptr)
-                {
-                    getListener()->onNewCacheChangeAdded((RTPSReader*)this, ch_to_give);
-                }
+        if (notify_individual)
+        {
+            it = mp_history->changesBegin();
+            next_seq = first_seq;
+            while (next_seq <= max_seq &&
+                    mp_history->changesEnd() != (it = mp_history->get_change_nts(next_seq, proxGUID, &aux_ch, it)) &&
+                    (*it)->sequenceNumber <= max_seq)
+            {
+                aux_ch = *it;
+                next_seq = aux_ch->sequenceNumber + 1;
+                listener->onNewCacheChangeAdded(this, aux_ch);
 
-                new_notification_cv_.notify_all();
+                // Reset the iterator to the beginning, since it may be invalidated inside the callback
+                it = mp_history->changesBegin();
             }
         }
+    }
 
-        // Search again the WriterProxy because could be removed after the unlock.
-        if (!findWriterProxy(proxGUID, &prox))
-        {
-            break;
-        }
-
-        nextChangeToNotify = prox->next_cache_change_to_be_notified();
+    // Notify in case someone is waiting for unread messages
+    if (new_data_available)
+    {
+        new_notification_cv_.notify_all();
     }
 }
 
diff -pruN 2.7.0+ds-2/src/cpp/rtps/reader/StatelessReader.cpp 2.7.1+ds-1/src/cpp/rtps/reader/StatelessReader.cpp
--- 2.7.0+ds-2/src/cpp/rtps/reader/StatelessReader.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/reader/StatelessReader.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -265,29 +265,37 @@ bool StatelessReader::change_received(
         if (mp_history->received_change(change, 0))
         {
             auto payload_length = change->serializedPayload.length;
+            auto guid = change->writerGUID;
+            auto seq = change->sequenceNumber;
 
             Time_t::now(change->reader_info.receptionTimestamp);
             SequenceNumber_t previous_seq = update_last_notified(change->writerGUID, change->sequenceNumber);
             ++total_unread_;
 
-            on_data_notify(change->writerGUID, change->sourceTimestamp);
+            on_data_notify(guid, change->sourceTimestamp);
 
-            if (getListener() != nullptr)
+            auto listener = getListener();
+            if (listener != nullptr)
             {
                 if (SequenceNumber_t{0, 0} != previous_seq)
                 {
-                    assert(previous_seq < change->sequenceNumber);
-                    uint64_t tmp = (change->sequenceNumber - previous_seq).to64long() - 1;
+                    assert(previous_seq < seq);
+                    uint64_t tmp = (seq - previous_seq).to64long() - 1;
                     int32_t lost_samples = tmp > static_cast<uint64_t>(std::numeric_limits<int32_t>::max()) ?
                             std::numeric_limits<int32_t>::max() : static_cast<int32_t>(tmp);
                     if (0 < lost_samples) // There are lost samples.
                     {
-                        getListener()->on_sample_lost(this, lost_samples);
+                        listener->on_sample_lost(this, lost_samples);
                     }
                 }
 
-                // WARNING! This method could destroy the change
-                getListener()->onNewCacheChangeAdded(this, change);
+                // WARNING! These methods could destroy the change
+                bool notify_single = false;
+                listener->on_data_available(this, guid, seq, seq, notify_single);
+                if (notify_single)
+                {
+                    listener->onNewCacheChangeAdded(this, change);
+                }
             }
 
             new_notification_cv_.notify_all();
@@ -462,7 +470,9 @@ bool StatelessReader::processDataMsg(
             CacheChange_t* change_to_add = nullptr;
             if (!change_pool_->reserve_cache(change_to_add))
             {
-                logError(RTPS_MSG_IN, IDSTRING "Problem reserving CacheChange in reader: " << m_guid);
+                logWarning(RTPS_MSG_IN,
+                        IDSTRING "Reached the maximum number of samples allowed by this reader's QoS. Rejecting change for reader: " <<
+                        m_guid );
                 return false;
             }
 
diff -pruN 2.7.0+ds-2/src/cpp/rtps/reader/WriterProxy.cpp 2.7.1+ds-1/src/cpp/rtps/reader/WriterProxy.cpp
--- 2.7.0+ds-2/src/cpp/rtps/reader/WriterProxy.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/reader/WriterProxy.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -99,8 +99,7 @@ WriterProxy::WriterProxy(
             };
     auto acknack_lambda = [this]() -> bool
             {
-                perform_initial_ack_nack();
-                return false;
+                return perform_initial_ack_nack();
             };
 
     heartbeat_response_ = new TimedEvent(event_manager, heartbeat_lambda, 0);
@@ -465,23 +464,34 @@ SequenceNumber_t WriterProxy::next_cache
     return SequenceNumber_t::unknown();
 }
 
-void WriterProxy::perform_initial_ack_nack()
+bool WriterProxy::perform_initial_ack_nack()
 {
-    // Send initial NACK.
-    SequenceNumberSet_t sns(SequenceNumber_t(0, 0));
-    if (is_on_same_process_)
+    bool ret_value = false;
+
+    if (!is_datasharing_writer_)
     {
-        RTPSWriter* writer = RTPSDomainImpl::find_local_writer(guid());
-        if (writer)
+        // Send initial NACK.
+        SequenceNumberSet_t sns(SequenceNumber_t(0, 0));
+        if (is_on_same_process_)
         {
-            bool tmp;
-            writer->process_acknack(guid(), reader_->getGuid(), 1, SequenceNumberSet_t(), false, tmp);
+            RTPSWriter* writer = RTPSDomainImpl::find_local_writer(guid());
+            if (writer)
+            {
+                bool tmp;
+                writer->process_acknack(guid(), reader_->getGuid(), 1, SequenceNumberSet_t(), false, tmp);
+            }
+        }
+        else
+        {
+            if (0 == last_heartbeat_count_)
+            {
+                reader_->send_acknack(this, sns, this, false);
+                ret_value = true;
+            }
         }
     }
-    else
-    {
-        reader_->send_acknack(this, sns, this, false);
-    }
+
+    return ret_value;
 }
 
 void WriterProxy::perform_heartbeat_response()
diff -pruN 2.7.0+ds-2/src/cpp/rtps/reader/WriterProxy.h 2.7.1+ds-1/src/cpp/rtps/reader/WriterProxy.h
--- 2.7.0+ds-2/src/cpp/rtps/reader/WriterProxy.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/reader/WriterProxy.h	2022-07-28 07:22:18.000000000 +0000
@@ -234,7 +234,7 @@ public:
     /**
      * Sends a preemptive acknack to the writer represented by this proxy.
      */
-    void perform_initial_ack_nack();
+    bool perform_initial_ack_nack();
 
     /**
      * Sends the necessary acknac and nackfrag messages to answer the last received heartbeat message.
diff -pruN 2.7.0+ds-2/src/cpp/rtps/writer/LivelinessManager.cpp 2.7.1+ds-1/src/cpp/rtps/writer/LivelinessManager.cpp
--- 2.7.0+ds-2/src/cpp/rtps/writer/LivelinessManager.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/writer/LivelinessManager.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -33,7 +33,7 @@ LivelinessManager::LivelinessManager(
 
 LivelinessManager::~LivelinessManager()
 {
-    std::unique_lock<std::mutex> lock(mutex_);
+    std::lock_guard<std::mutex> _(mutex_);
     timer_owner_ = nullptr;
     timer_.cancel_timer();
 }
@@ -52,12 +52,11 @@ bool LivelinessManager::add_writer(
     {
         // collection guard
         std::lock_guard<shared_mutex> _(col_mutex_);
+        // writers_ elements guard
+        std::lock_guard<std::mutex> __(mutex_);
 
         for (LivelinessData& writer : writers_)
         {
-            // writers_ elements guard
-            std::lock_guard<std::mutex> __(mutex_);
-
             if (writer.guid == guid &&
                     writer.kind == kind &&
                     writer.lease_duration == lease_duration)
@@ -101,11 +100,11 @@ bool LivelinessManager::remove_writer(
     {
         // collection guard
         std::lock_guard<shared_mutex> _(col_mutex_);
+        // writers_ elements guard
+        std::lock_guard<std::mutex> __(mutex_);
 
-        removed = writers_.remove_if([guid, kind, lease_duration, &status, this](LivelinessData& writer)
+        removed = writers_.remove_if([guid, kind, lease_duration, &status](LivelinessData& writer)
                         {
-                            // writers_ elements guard
-                            std::lock_guard<std::mutex> _(mutex_);
                             status = writer.status;
                             return writer.guid == guid &&
                             writer.kind == kind &&
@@ -288,20 +287,18 @@ bool LivelinessManager::assert_livelines
 
 bool LivelinessManager::calculate_next()
 {
-    timer_owner_ = nullptr;
+    // Keep this lock order to prevent ABBA deadlocks
+    shared_lock<shared_mutex> _(col_mutex_);
+    std::lock_guard<std::mutex> __(mutex_);
 
+    bool any_alive = false;
     steady_clock::time_point min_time = steady_clock::now() + nanoseconds(c_TimeInfinite.to_ns());
 
-    bool any_alive = false;
+    timer_owner_ = nullptr;
 
     // collection guard
-    shared_lock<shared_mutex> _(col_mutex_);
-
     for (LivelinessData& writer : writers_)
     {
-        // writers_ elements guard
-        std::lock_guard<std::mutex> __(mutex_);
-
         if (writer.status == LivelinessData::WriterStatus::ALIVE)
         {
             if (writer.time < min_time)
@@ -362,12 +359,12 @@ bool LivelinessManager::timer_expired()
 bool LivelinessManager::is_any_alive(
         LivelinessQosPolicyKind kind)
 {
+    // Keep this lock order to prevent ABBA deadlocks
     shared_lock<shared_mutex> _(col_mutex_);
+    std::lock_guard<std::mutex> __(mutex_);
 
     for (const auto& writer : writers_)
     {
-        std::unique_lock<std::mutex> lock(mutex_);
-
         if (writer.kind == kind && writer.status == LivelinessData::WriterStatus::ALIVE)
         {
             return true;
diff -pruN 2.7.0+ds-2/src/cpp/rtps/writer/StatefulWriter.cpp 2.7.1+ds-1/src/cpp/rtps/writer/StatefulWriter.cpp
--- 2.7.0+ds-2/src/cpp/rtps/writer/StatefulWriter.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/writer/StatefulWriter.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -1341,7 +1341,7 @@ bool StatefulWriter::is_acked_by_all(
 {
     assert(mp_history->next_sequence_number() > seq);
     return (seq < next_all_acked_notify_sequence_) ||
-           !for_matched_readers(matched_local_readers_, matched_remote_readers_,
+           !for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
                    [seq](const ReaderProxy* reader)
                    {
                        return !(reader->change_is_acked(seq));
@@ -1911,6 +1911,7 @@ bool StatefulWriter::process_acknack(
                                         {
                                             // Send heartbeat if requested
                                             send_heartbeat_to_nts(*remote_reader, false, true);
+                                            periodic_hb_event_->restart_timer();
                                         }
                                     }
 
diff -pruN 2.7.0+ds-2/src/cpp/rtps/xmlparser/XMLEndpointParser.cpp 2.7.1+ds-1/src/cpp/rtps/xmlparser/XMLEndpointParser.cpp
--- 2.7.0+ds-2/src/cpp/rtps/xmlparser/XMLEndpointParser.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/src/cpp/rtps/xmlparser/XMLEndpointParser.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -64,15 +64,28 @@ XMLEndpointParser::~XMLEndpointParser()
 XMLP_ret XMLEndpointParser::loadXMLFile(
         std::string& filename)
 {
-    logInfo(RTPS_EDP, "File: " << filename);
-
     tinyxml2::XMLDocument doc;
-    doc.LoadFile(filename.c_str());
-    tinyxml2::XMLError eResult = doc.LoadFile(filename.c_str());
+    tinyxml2::XMLError eResult;
+
+    if (0 == filename.rfind("data://", 0))
+    {
+        logInfo(RTPS_EDP, filename);
+        eResult = doc.Parse(filename.c_str() + 7, filename.size() - 7);
+    }
+    else if (0 == filename.rfind("file://", 0))
+    {
+        logInfo(RTPS_EDP, filename);
+        eResult = doc.LoadFile(filename.substr(7).c_str());
+    }
+    else
+    {
+        logInfo(RTPS_EDP, "FileName: " << filename);
+        eResult = doc.LoadFile(filename.c_str());
+    }
 
     if (tinyxml2::XML_SUCCESS != eResult)
     {
-        logError(RTPS_EDP, filename << " bad file (bad path?)");
+        logError(RTPS_EDP, filename << " bad file");
         return XMLP_ret::XML_ERROR;
     }
 
@@ -83,7 +96,6 @@ XMLP_ret XMLEndpointParser::loadXMLFile(
         return XMLP_ret::XML_ERROR;
     }
 
-
     tinyxml2::XMLElement* xml_RTPSParticipant = root->FirstChildElement();
 
     while (xml_RTPSParticipant != nullptr)
diff -pruN 2.7.0+ds-2/test/blackbox/api/dds-pim/PubSubReader.hpp 2.7.1+ds-1/test/blackbox/api/dds-pim/PubSubReader.hpp
--- 2.7.0+ds-2/test/blackbox/api/dds-pim/PubSubReader.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/blackbox/api/dds-pim/PubSubReader.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -352,6 +352,11 @@ public:
         return *datareader_;
     }
 
+    eprosima::fastdds::dds::Subscriber& get_native_subscriber() const
+    {
+        return *subscriber_;
+    }
+
     void init()
     {
         ASSERT_FALSE(initialized_);
diff -pruN 2.7.0+ds-2/test/blackbox/api/dds-pim/PubSubWriter.hpp 2.7.1+ds-1/test/blackbox/api/dds-pim/PubSubWriter.hpp
--- 2.7.0+ds-2/test/blackbox/api/dds-pim/PubSubWriter.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/blackbox/api/dds-pim/PubSubWriter.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -691,8 +691,13 @@ public:
     bool waitForAllAcked(
             const std::chrono::duration<_Rep, _Period>& max_wait)
     {
+        auto nsecs = std::chrono::duration_cast<std::chrono::nanoseconds>(max_wait);
+        auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
+        nsecs -= secs;
+        eprosima::fastrtps::Duration_t timeout {static_cast<int32_t>(secs.count()),
+                                                static_cast<uint32_t>(nsecs.count())};
         return (ReturnCode_t::RETCODE_OK ==
-               datawriter_->wait_for_acknowledgments(eprosima::fastrtps::Time_t((int32_t)max_wait.count(), 0)));
+               datawriter_->wait_for_acknowledgments(timeout));
     }
 
     template<class _Rep,
@@ -703,9 +708,13 @@ public:
             const eprosima::fastrtps::rtps::InstanceHandle_t& instance_handle,
             const std::chrono::duration<_Rep, _Period>& max_wait)
     {
+        auto nsecs = std::chrono::duration_cast<std::chrono::nanoseconds>(max_wait);
+        auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
+        nsecs -= secs;
+        eprosima::fastrtps::Duration_t timeout {static_cast<int32_t>(secs.count()),
+                                                static_cast<uint32_t>(nsecs.count())};
         return (ReturnCode_t::RETCODE_OK ==
-               datawriter_->wait_for_acknowledgments(data, instance_handle,
-               eprosima::fastrtps::Time_t(static_cast<int32_t>(max_wait.count()), 0)));
+               datawriter_->wait_for_acknowledgments(data, instance_handle, timeout));
     }
 
     void block_until_discover_topic(
diff -pruN 2.7.0+ds-2/test/blackbox/api/fastrtps_deprecated/PubSubWriter.hpp 2.7.1+ds-1/test/blackbox/api/fastrtps_deprecated/PubSubWriter.hpp
--- 2.7.0+ds-2/test/blackbox/api/fastrtps_deprecated/PubSubWriter.hpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/blackbox/api/fastrtps_deprecated/PubSubWriter.hpp	2022-07-28 07:22:18.000000000 +0000
@@ -576,7 +576,12 @@ public:
     bool waitForAllAcked(
             const std::chrono::duration<_Rep, _Period>& max_wait)
     {
-        return publisher_->wait_for_all_acked(eprosima::fastrtps::Time_t((int32_t)max_wait.count(), 0));
+        auto nsecs = std::chrono::duration_cast<std::chrono::nanoseconds>(max_wait);
+        auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs);
+        nsecs -= secs;
+        eprosima::fastrtps::Duration_t timeout {static_cast<int32_t>(secs.count()),
+                                                static_cast<uint32_t>(nsecs.count())};
+        return publisher_->wait_for_all_acked(timeout);
     }
 
     void block_until_discover_topic(
diff -pruN 2.7.0+ds-2/test/blackbox/CMakeLists.txt 2.7.1+ds-1/test/blackbox/CMakeLists.txt
--- 2.7.0+ds-2/test/blackbox/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/blackbox/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -160,15 +160,15 @@ macro(add_blackbox_gtest)
 
         # add filtering statement if required
         if(GTEST_IGNORE)
-            set(command "${command} --gtest_filter=${GTEST_IGNORE}")
+            set(gtest_filter "--gtest_filter=${GTEST_IGNORE}")
         endif()
 
-        add_test(NAME ${test} COMMAND ${command})
+        add_test(NAME ${test} COMMAND ${command} ${gtest_filter})
 
         # Add environment
         if(WIN32)
             set(WIN_PATH "$ENV{PATH}")
-            get_target_property(LINK_LIBRARIES_ ${command} LINK_LIBRARIES)
+            get_target_property(LINK_LIBRARIES_ ${test} LINK_LIBRARIES)
             if(NOT "${LINK_LIBRARIES_}" STREQUAL "LINK_LIBRARIES_-NOTFOUND")
                 foreach(LIBRARY_LINKED ${LINK_LIBRARIES_})
                     if(TARGET ${LIBRARY_LINKED})
@@ -189,6 +189,8 @@ macro(add_blackbox_gtest)
 
         # Add labels
         set_property(TEST ${test} PROPERTY LABELS "${GTEST_LABELS}")
+
+        unset(gtest_filter)
     endif()
 endmacro()
 
diff -pruN 2.7.0+ds-2/test/blackbox/common/DDSBlackboxTestsDataSharing.cpp 2.7.1+ds-1/test/blackbox/common/DDSBlackboxTestsDataSharing.cpp
--- 2.7.0+ds-2/test/blackbox/common/DDSBlackboxTestsDataSharing.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/blackbox/common/DDSBlackboxTestsDataSharing.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -54,6 +54,7 @@ TEST(DDSDataSharing, BasicCommunication)
 
     reader.history_depth(100)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".").loan_sample_validation()
             .reliability(BEST_EFFORT_RELIABILITY_QOS).init();
 
@@ -61,6 +62,7 @@ TEST(DDSDataSharing, BasicCommunication)
 
     writer.history_depth(100)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".")
             .reliability(BEST_EFFORT_RELIABILITY_QOS).init();
 
@@ -109,6 +111,7 @@ TEST(DDSDataSharing, TransientReader)
 
     writer.history_depth(writer_history_depth)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".")
             .reliability(BEST_EFFORT_RELIABILITY_QOS).init();
 
@@ -130,6 +133,7 @@ TEST(DDSDataSharing, TransientReader)
 
     reader.history_depth(writer_sent_data)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".")
             .reliability(BEST_EFFORT_RELIABILITY_QOS)
             .durability_kind(TRANSIENT_LOCAL_DURABILITY_QOS).init();
@@ -172,6 +176,7 @@ TEST(DDSDataSharing, BestEffortDirtyPayl
 
     writer.history_depth(writer_history_depth)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".")
             .reliability(BEST_EFFORT_RELIABILITY_QOS)
             .resource_limits_extra_samples(1).init();
@@ -180,6 +185,7 @@ TEST(DDSDataSharing, BestEffortDirtyPayl
 
     read_reader.history_depth(writer_sent_data)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".")
             .reliability(BEST_EFFORT_RELIABILITY_QOS).init();
 
@@ -232,6 +238,7 @@ TEST(DDSDataSharing, ReliableDirtyPayloa
 
     writer.history_depth(writer_history_depth)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".")
             .reliability(RELIABLE_RELIABILITY_QOS)
             .resource_limits_extra_samples(1).init();
@@ -240,6 +247,7 @@ TEST(DDSDataSharing, ReliableDirtyPayloa
 
     read_reader.history_depth(writer_sent_data)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_on(".")
             .reliability(RELIABLE_RELIABILITY_QOS).init();
 
@@ -657,6 +665,7 @@ TEST(DDSDataSharing, DataSharingDefaultD
 
     reader.history_depth(100)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_auto()
             .reliability(BEST_EFFORT_RELIABILITY_QOS).init();
 
@@ -664,6 +673,7 @@ TEST(DDSDataSharing, DataSharingDefaultD
 
     writer.history_depth(100)
             .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
             .datasharing_auto()
             .reliability(BEST_EFFORT_RELIABILITY_QOS).init();
 
@@ -684,3 +694,213 @@ TEST(DDSDataSharing, DataSharingDefaultD
     // Block reader until reception finished or timeout.
     reader.block_for_all();
 }
+
+/*!
+ * @test Regression test for bug #15176.
+ */
+TEST(DDSDataSharing, acknack_reception_when_change_removed_by_history)
+{
+    PubSubReader<FixedSizedPubSubType> reader(TEST_TOPIC_NAME);
+    PubSubWriter<FixedSizedPubSubType> writer(TEST_TOPIC_NAME);
+
+    // Disable transports to ensure we are using datasharing
+    auto testTransport = std::make_shared<test_UDPv4TransportDescriptor>();
+    testTransport->dropDataMessagesPercentage = 100;
+
+    writer.history_depth(100)
+            .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
+            .datasharing_on(".")
+            .reliability(RELIABLE_RELIABILITY_QOS)
+            .lifespan_period({5, 0})
+            .init();
+
+    ASSERT_TRUE(writer.isInitialized());
+
+    reader.history_depth(100)
+            .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
+            .datasharing_on(".")
+            .reliability(RELIABLE_RELIABILITY_QOS)
+            .durability_kind(TRANSIENT_LOCAL_DURABILITY_QOS)
+            .lifespan_period({0, 10})
+            .init();
+
+    ASSERT_TRUE(reader.isInitialized());
+
+    // Because its volatile the durability
+    // Wait for discovery.
+    writer.wait_discovery();
+    reader.wait_discovery();
+
+    // Check that the shared files are created on the correct directory
+    ASSERT_TRUE(check_shared_file(".", reader.datareader_guid()));
+    ASSERT_TRUE(check_shared_file(".", writer.datawriter_guid()));
+
+    auto data = default_fixed_sized_data_generator(10);
+
+    // Send data
+    writer.send(data);
+    // In this test all data should be sent.
+    ASSERT_TRUE(data.empty());
+
+    auto now = std::chrono::steady_clock::now();
+    writer.waitForAllAcked(std::chrono::milliseconds(10000));
+    ASSERT_LT(std::chrono::steady_clock::now() - now, std::chrono::milliseconds(5000));
+
+    // Destroy reader and writer and see if there are dangling files
+    reader.destroy();
+    writer.destroy();
+
+    // Check that the shared files are created on the correct directory
+    ASSERT_FALSE(check_shared_file(".", reader.datareader_guid()));
+    ASSERT_FALSE(check_shared_file(".", writer.datawriter_guid()));
+}
+
+/*!
+ * @test Regression test for bug #15176. Corner case using `get_unread_count(true)`.
+ */
+TEST(DDSDataSharing, acknack_reception_when_get_unread_count_and_change_removed_by_history)
+{
+    PubSubReader<FixedSizedPubSubType> reader(TEST_TOPIC_NAME);
+    PubSubWriter<FixedSizedPubSubType> writer(TEST_TOPIC_NAME);
+
+    // Disable transports to ensure we are using datasharing
+    auto testTransport = std::make_shared<test_UDPv4TransportDescriptor>();
+    testTransport->dropDataMessagesPercentage = 100;
+
+    writer.history_depth(100)
+            .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
+            .datasharing_on(".")
+            .reliability(RELIABLE_RELIABILITY_QOS)
+            .init();
+
+    ASSERT_TRUE(writer.isInitialized());
+
+    reader.history_depth(100)
+            .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
+            .datasharing_on(".")
+            .loan_sample_validation()
+            .reliability(RELIABLE_RELIABILITY_QOS)
+            .durability_kind(TRANSIENT_LOCAL_DURABILITY_QOS)
+            .init();
+
+    ASSERT_TRUE(reader.isInitialized());
+
+    // Because its volatile the durability
+    // Wait for discovery.
+    writer.wait_discovery();
+    reader.wait_discovery();
+
+    // Check that the shared files are created on the correct directory
+    ASSERT_TRUE(check_shared_file(".", reader.datareader_guid()));
+    ASSERT_TRUE(check_shared_file(".", writer.datawriter_guid()));
+
+    auto data = default_fixed_sized_data_generator(2);
+    auto data_recv = data;
+
+    // Send data
+    writer.send_sample(data.front());
+    data.pop_front();
+
+    // Wait to arrive data.
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    auto& native_reader = reader.get_native_reader();
+    ASSERT_EQ(1u, native_reader.get_unread_count(true));
+
+    writer.send_sample(data.front());
+
+    // Wait to arrive data.
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    reader.startReception(data_recv);
+    reader.block_for_all();
+    auto now = std::chrono::steady_clock::now();
+    writer.waitForAllAcked(std::chrono::milliseconds(10000));
+    ASSERT_LT(std::chrono::steady_clock::now() - now, std::chrono::milliseconds(5000));
+
+    // Destroy reader and writer and see if there are dangling files
+    reader.destroy();
+    writer.destroy();
+
+    // Check that the shared files are created on the correct directory
+    ASSERT_FALSE(check_shared_file(".", reader.datareader_guid()));
+    ASSERT_FALSE(check_shared_file(".", writer.datawriter_guid()));
+}
+
+/*!
+ * @test Regression test for bug #15176. Corner case using `get_unread_count(true)`.
+ */
+TEST(DDSDataSharing, acknack_reception_when_get_unread_count)
+{
+    PubSubReader<FixedSizedPubSubType> reader(TEST_TOPIC_NAME);
+    PubSubWriter<FixedSizedPubSubType> writer(TEST_TOPIC_NAME);
+
+    // Disable transports to ensure we are using datasharing
+    auto testTransport = std::make_shared<test_UDPv4TransportDescriptor>();
+    testTransport->dropDataMessagesPercentage = 100;
+
+    writer.history_depth(100)
+            .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
+            .datasharing_on(".")
+            .reliability(RELIABLE_RELIABILITY_QOS)
+            .init();
+
+    ASSERT_TRUE(writer.isInitialized());
+
+    reader.history_depth(100)
+            .add_user_transport_to_pparams(testTransport)
+            .disable_builtin_transport()
+            .datasharing_on(".")
+            .loan_sample_validation()
+            .reliability(RELIABLE_RELIABILITY_QOS)
+            .durability_kind(TRANSIENT_LOCAL_DURABILITY_QOS)
+            .init();
+
+    ASSERT_TRUE(reader.isInitialized());
+
+    // Because its volatile the durability
+    // Wait for discovery.
+    writer.wait_discovery();
+    reader.wait_discovery();
+
+    // Check that the shared files are created on the correct directory
+    ASSERT_TRUE(check_shared_file(".", reader.datareader_guid()));
+    ASSERT_TRUE(check_shared_file(".", writer.datawriter_guid()));
+
+    auto data = default_fixed_sized_data_generator(10);
+    auto data_recv = data;
+
+    // Send data
+    writer.send(data);
+    // In this test all data should be sent.
+    ASSERT_TRUE(data.empty());
+
+    // Wait to arrive data.
+    std::this_thread::sleep_for(std::chrono::milliseconds(500));
+
+    auto& native_reader = reader.get_native_reader();
+    ASSERT_EQ(10u, native_reader.get_unread_count(true));
+
+    auto now = std::chrono::steady_clock::now();
+    writer.waitForAllAcked(std::chrono::milliseconds(2000));
+    ASSERT_GE(std::chrono::steady_clock::now() - now, std::chrono::milliseconds(1900));
+
+    reader.startReception(data_recv);
+    reader.block_for_all();
+    now = std::chrono::steady_clock::now();
+    writer.waitForAllAcked(std::chrono::milliseconds(2000));
+    ASSERT_LT(std::chrono::steady_clock::now() - now, std::chrono::milliseconds(1900));
+
+    // Destroy reader and writer and see if there are dangling files
+    reader.destroy();
+    writer.destroy();
+
+    // Check that the shared files are created on the correct directory
+    ASSERT_FALSE(check_shared_file(".", reader.datareader_guid()));
+    ASSERT_FALSE(check_shared_file(".", writer.datawriter_guid()));
+}
diff -pruN 2.7.0+ds-2/test/blackbox/common/DDSBlackboxTestsDiscovery.cpp 2.7.1+ds-1/test/blackbox/common/DDSBlackboxTestsDiscovery.cpp
--- 2.7.0+ds-2/test/blackbox/common/DDSBlackboxTestsDiscovery.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/blackbox/common/DDSBlackboxTestsDiscovery.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -569,12 +569,847 @@ TEST(DDSDiscovery, ParticipantProxyPhysi
 }
 
 /**
- * This test checks the unsupported DomainParticipantFactory->check_xml_static_discovery
- * method and checks it returns RETCODE_UNSUPPORTED
+ * This test checks the missing file case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
  */
-TEST(DDSDiscovery, CheckUnsupportedXmlStaticDiscoveryFile)
+TEST(DDSDiscovery, CheckMissingFileXmlStaticDiscoveryFile)
 {
-    std::string file = "Unsupported.xml";
+    std::string file = "MissingFile.xml";
     DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
-    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_UNSUPPORTED);
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the correct data case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_OK
+ */
+TEST(DDSDiscovery, CheckCorrectXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_OK);
+}
+
+/**
+ * This test checks the incorrect <staticdiscovery> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectStaticdiscoveryXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscoveryBROKEN>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect <participant> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectParticipantXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participantBROKEN>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect <reader> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</readerBROKEN>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect reader <userId> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderUserIDXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userIdBROKEN>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+/**
+ * This test checks the incorrect reader <entityID> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderEntityIDXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityIDBROKEN>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect reader <topicName> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderTopicNameXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicNameBROKEN>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect data case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderTopicDataTypeXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataTypeBROKEN>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect reader <topicKind> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderTopicKindXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKindBROKEN>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect reader <partitionQos> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderPartitionQosXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQosBROKEN>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect reader <reliabilityQos> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderReliabilityQosXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQosBROKEN>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect reader <durabilityQos> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderDurabilityQosXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQosBROKEN>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect reader <multicastLocator> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectReaderMulticastLocatorXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" BROKEN/>" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect <writer> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writerBROKEN>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <userId> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterUserIDXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userIdBROKEN>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <entityID> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterEntityIDXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityIDBROKEN>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <topicName> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterTopicNameXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicNameBROKEN>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <topicDataType> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterTopicDataTypeXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataTypeBROKEN>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <topicKind> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterTopicKindXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKindBROKEN>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <partitionQos> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterPartitionQosXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQosBROKEN>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <reliabilityQos> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterReliabilityQosXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQosBROKEN>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
+}
+
+/**
+ * This test checks the incorrect writer <durabilityQos> case of DomainParticipantFactory->check_xml_static_discovery
+ * method and checks it returns RETCODE_ERROR
+ */
+TEST(DDSDiscovery, CheckIncorrectWriterDurabilityQosXmlStaticDiscoveryFile)
+{
+    std::string file = "data://<?xml version=\"1.0\" encoding=\"utf-8\"?>" \
+            "<staticdiscovery>" \
+            "<participant>" \
+            "<name>SPMDEETISS10_DefaultPartition</name>" \
+            "<reader>" \
+            "<userId>11</userId>" \
+            "<entityID>11</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQos>" \
+            "<multicastLocator address=\"239.255.0.1\" port=\"7401\" />" \
+            "</reader>" \
+            "<writer>" \
+            "<userId>12</userId>" \
+            "<entityID>12</entityID>" \
+            "<topicName>topic1</topicName>" \
+            "<topicDataType>Topic1</topicDataType>" \
+            "<topicKind>WITH_KEY</topicKind>" \
+            "<partitionQos>DefaultPartition</partitionQos>" \
+            "<reliabilityQos>RELIABLE_RELIABILITY_QOS</reliabilityQos>" \
+            "<durabilityQos>TRANSIENT_LOCAL_DURABILITY_QOS</durabilityQosBROKEN>" \
+            "</writer>" \
+            "</participant>" \
+            "</staticdiscovery>";
+
+    DomainParticipantFactory* factory = DomainParticipantFactory::get_instance();
+    ASSERT_EQ(factory->check_xml_static_discovery(file), ReturnCode_t::RETCODE_ERROR);
 }
diff -pruN 2.7.0+ds-2/test/mock/rtps/ReaderHistory/fastdds/rtps/history/ReaderHistory.h 2.7.1+ds-1/test/mock/rtps/ReaderHistory/fastdds/rtps/history/ReaderHistory.h
--- 2.7.0+ds-2/test/mock/rtps/ReaderHistory/fastdds/rtps/history/ReaderHistory.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/mock/rtps/ReaderHistory/fastdds/rtps/history/ReaderHistory.h	2022-07-28 07:22:18.000000000 +0000
@@ -58,6 +58,11 @@ public:
 
     MOCK_METHOD0(getHistorySize, size_t());
 
+    MOCK_METHOD3(get_change, bool(
+            const SequenceNumber_t& seq,
+            const GUID_t& guid,
+            CacheChange_t** change));
+
     MOCK_METHOD1(get_earliest_change, bool(
             CacheChange_t** change));
 
@@ -121,7 +126,7 @@ public:
         return ret;
     }
 
-    inline RecursiveTimedMutex* getMutex()
+    inline RecursiveTimedMutex* getMutex() const
     {
         return mp_mutex;
     }
diff -pruN 2.7.0+ds-2/test/mock/rtps/RTPSDomain/fastdds/rtps/RTPSDomain.h 2.7.1+ds-1/test/mock/rtps/RTPSDomain/fastdds/rtps/RTPSDomain.h
--- 2.7.0+ds-2/test/mock/rtps/RTPSDomain/fastdds/rtps/RTPSDomain.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/mock/rtps/RTPSDomain/fastdds/rtps/RTPSDomain.h	2022-07-28 07:22:18.000000000 +0000
@@ -109,9 +109,10 @@ public:
     static RTPSReader* createRTPSReader(
             RTPSParticipant*,
             ReaderAttributes&,
-            ReaderHistory*,
+            ReaderHistory* history,
             ReaderListener* listen = nullptr)
     {
+        reader_->setHistory(history);
         reader_->setListener(listen);
         return reader_;
     }
@@ -120,9 +121,10 @@ public:
             RTPSParticipant*,
             ReaderAttributes&,
             const std::shared_ptr<IPayloadPool>&,
-            ReaderHistory*,
+            ReaderHistory* history,
             ReaderListener* listen = nullptr)
     {
+        reader_->setHistory(history);
         reader_->setListener(listen);
         return reader_;
     }
@@ -132,9 +134,10 @@ public:
             const EntityId_t&,
             ReaderAttributes&,
             const std::shared_ptr<IPayloadPool>&,
-            ReaderHistory*,
+            ReaderHistory* history,
             ReaderListener* listen = nullptr)
     {
+        reader_->setHistory(history);
         reader_->setListener(listen);
         return reader_;
     }
diff -pruN 2.7.0+ds-2/test/mock/rtps/RTPSReader/fastdds/rtps/reader/RTPSReader.h 2.7.1+ds-1/test/mock/rtps/RTPSReader/fastdds/rtps/reader/RTPSReader.h
--- 2.7.0+ds-2/test/mock/rtps/RTPSReader/fastdds/rtps/reader/RTPSReader.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/mock/rtps/RTPSReader/fastdds/rtps/reader/RTPSReader.h	2022-07-28 07:22:18.000000000 +0000
@@ -115,6 +115,8 @@ public:
 
     MOCK_METHOD0(get_unread_count, uint64_t());
 
+    MOCK_METHOD1(get_unread_count, uint64_t(bool));
+
     MOCK_METHOD1(set_content_filter, void (eprosima::fastdds::rtps::IReaderDataFilter* filter));
 
     // *INDENT-ON*
@@ -180,6 +182,14 @@ public:
         return true;
     }
 
+    void setHistory(
+            ReaderHistory* history)
+    {
+        history->mp_reader = this;
+        history->mp_mutex = &mp_mutex;
+        history_ = history;
+    }
+
     ReaderHistory* getHistory()
     {
         getHistory_mock();
diff -pruN 2.7.0+ds-2/test/mock/rtps/WriterHistory/fastdds/rtps/history/WriterHistory.h 2.7.1+ds-1/test/mock/rtps/WriterHistory/fastdds/rtps/history/WriterHistory.h
--- 2.7.0+ds-2/test/mock/rtps/WriterHistory/fastdds/rtps/history/WriterHistory.h	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/mock/rtps/WriterHistory/fastdds/rtps/history/WriterHistory.h	2022-07-28 07:22:18.000000000 +0000
@@ -164,7 +164,7 @@ public:
         return m_changes.rend();
     }
 
-    RecursiveTimedMutex* getMutex()
+    RecursiveTimedMutex* getMutex() const
     {
         return mp_mutex;
     }
diff -pruN 2.7.0+ds-2/test/mock/rtps/XMLEndPointParser/fastrtps/xmlparser/XMLEndpointParser.h 2.7.1+ds-1/test/mock/rtps/XMLEndPointParser/fastrtps/xmlparser/XMLEndpointParser.h
--- 2.7.0+ds-2/test/mock/rtps/XMLEndPointParser/fastrtps/xmlparser/XMLEndpointParser.h	1970-01-01 00:00:00.000000000 +0000
+++ 2.7.1+ds-1/test/mock/rtps/XMLEndPointParser/fastrtps/xmlparser/XMLEndpointParser.h	2022-07-28 07:22:18.000000000 +0000
@@ -0,0 +1,69 @@
+// Copyright 2016 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 XMLEndpointParser.h
+ *
+ */
+
+#ifndef XMLENDPOINTPARSER_H_
+#define XMLENDPOINTPARSER_H_
+#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
+
+
+
+namespace eprosima {
+namespace fastrtps {
+namespace xmlparser {
+
+
+
+/**
+ * Class XMLEndpointParser used to parse the XML file that contains information about remote endpoints.
+ * @ingroup DISCVOERYMODULE
+ */
+class XMLEndpointParser
+{
+public:
+
+    XMLEndpointParser()
+    {
+    }
+
+    virtual ~XMLEndpointParser()
+    {
+    }
+
+    /**
+     * Load the XML file
+     * @param filename Name of the file to load and parse.
+     * @return True if correct.
+     */
+    XMLP_ret loadXMLFile(
+            std::string&)
+    {
+        return XMLP_ret::XML_OK;
+    }
+
+private:
+
+};
+
+
+} /* xmlparser */
+} /* namespace */
+} /* namespace eprosima */
+
+#endif // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
+#endif /* XMLENDPOINTPARSER_H_ */
diff -pruN 2.7.0+ds-2/test/unittest/dds/publisher/CMakeLists.txt 2.7.1+ds-1/test/unittest/dds/publisher/CMakeLists.txt
--- 2.7.0+ds-2/test/unittest/dds/publisher/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/dds/publisher/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -65,15 +65,14 @@ set(DATAWRITERTESTS_SOURCE DataWriterTes
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/StatusCondition.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/StatusConditionImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/WaitSetImpl.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/QosPolicyUtils.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/ParameterList.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/QosPolicyUtils.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipant.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipantImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipantFactory.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipantImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/qos/DomainParticipantQos.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/FileConsumer.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/OStreamConsumer.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutConsumer.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutErrConsumer.cpp
@@ -86,11 +85,12 @@ set(DATAWRITERTESTS_SOURCE DataWriterTes
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/WriterQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/DataReader.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/DataReaderImpl.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/ReadCondition.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/Subscriber.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/SubscriberImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/DataReaderQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/ReaderQos.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/Subscriber.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/SubscriberImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/SubscriberQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/ContentFilteredTopic.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/ContentFilteredTopicImpl.cpp
@@ -100,16 +100,20 @@ set(DATAWRITERTESTS_SOURCE DataWriterTes
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TypeSupport.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/qos/TopicQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastrtps_deprecated/subscriber/SubscriberHistory.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingListener.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingNotification.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingPayloadPool.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/RTPSDomain.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/PropertyPolicy.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/BuiltinProtocols.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/ParticipantProxyData.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/ReaderProxyData.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/WriterProxyData.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/backup/SharedBackupFunctions.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryDataBase.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantsAckStatus.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantInfo.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantsAckStatus.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoverySharedInfo.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/backup/SharedBackupFunctions.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDPClient.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDPServer.cpp
@@ -118,21 +122,18 @@ set(DATAWRITERTESTS_SOURCE DataWriterTes
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDPSimpleListeners.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDPStatic.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/DirectMessageSender.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/ServerAttributes.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/PDP.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/PDPClient.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/PDPListener.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/PDPServer.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/PDPServerListener.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/PDPSimple.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/ServerAttributes.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/timedevent/DSClientEvent.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/participant/timedevent/DServerEvent.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/liveliness/WLP.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/liveliness/WLPListener.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingListener.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingNotification.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingPayloadPool.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerConsts.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerFactory.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/ThroughputControllerDescriptor.cpp
@@ -161,14 +162,11 @@ set(DATAWRITERTESTS_SOURCE DataWriterTes
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/ResourceEvent.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/TimedEvent.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/TimedEventImpl.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/RTPSDomain.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/ChannelResource.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPAcceptor.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPAcceptorBasic.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResource.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResourceBasic.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/TCPControlMessage.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/RTCPMessageManager.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPTransportInterface.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv4Transport.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv6Transport.cpp
@@ -177,12 +175,14 @@ set(DATAWRITERTESTS_SOURCE DataWriterTes
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPv4Transport.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPv6Transport.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/shared_mem/SharedMemTransportDescriptor.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/RTCPMessageManager.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/TCPControlMessage.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/LivelinessManager.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/LocatorSelectorSender.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/PersistentWriter.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/RTPSWriter.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/ReaderLocator.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/ReaderProxy.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/RTPSWriter.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/StatefulPersistentWriter.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/StatefulWriter.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/StatelessPersistentWriter.cpp
@@ -195,11 +195,11 @@ set(DATAWRITERTESTS_SOURCE DataWriterTes
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLProfileManager.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/StringMatching.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/TimedConditionVariable.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp
     )
 
     if(SQLITE3_SUPPORT)
diff -pruN 2.7.0+ds-2/test/unittest/dds/status/CMakeLists.txt 2.7.1+ds-1/test/unittest/dds/status/CMakeLists.txt
--- 2.7.0+ds-2/test/unittest/dds/status/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/dds/status/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -17,90 +17,91 @@ file(GLOB DDSSQLFILTER_SOURCES ${PROJECT
 set(LISTENERTESTS_SOURCE ListenerTests.cpp
     ${DDSSQLFILTER_SOURCES}
 
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/AnnotationDescriptor.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/AnnotationParameterValue.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/BuiltinAnnotationsTypeObject.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicData.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicDataFactory.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicDataPtr.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicPubSubType.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicType.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilder.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilderFactory.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilderPtr.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeMember.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypePtr.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/MemberDescriptor.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeDescriptor.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeIdentifier.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeIdentifierTypes.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeNamesGenerator.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObject.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObjectFactory.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObjectHashId.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypesBase.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/Entity.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/Condition.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/ConditionNotifier.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/StatusCondition.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/StatusConditionImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/WaitSetImpl.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/ParameterList.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/QosPolicyUtils.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipant.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipantFactory.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipantImpl.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/qos/DomainParticipantQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/qos/DomainParticipantFactoryQos.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/Publisher.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/PublisherImpl.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/qos/DomainParticipantQos.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/FileConsumer.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/OStreamConsumer.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutConsumer.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutErrConsumer.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriter.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriterImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriterHistory.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/PublisherQos.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriterImpl.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/Publisher.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/PublisherImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/DataWriterQos.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/PublisherQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/WriterQos.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/Subscriber.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/SubscriberImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/DataReader.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/DataReaderImpl.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/ReadCondition.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/Subscriber.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/SubscriberImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/SubscriberQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/DataReaderQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/ReaderQos.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/SubscriberQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/ContentFilteredTopic.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/ContentFilteredTopicImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/Topic.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/qos/TopicQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TopicImpl.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TopicProxyFactory.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TypeSupport.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/ParameterList.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/OStreamConsumer.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutConsumer.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutErrConsumer.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/FileConsumer.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/qos/TopicQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/PropertyPolicy.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/ThroughputControllerDescriptor.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerConsts.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/ThroughputControllerDescriptor.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/history/CacheChangePool.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/history/TopicPayloadPool.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/history/TopicPayloadPoolRegistry.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/LocatorSelectorSender.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/AnnotationDescriptor.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicData.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicDataFactory.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicType.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicPubSubType.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypePtr.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicDataPtr.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilder.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilderPtr.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeBuilderFactory.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/DynamicTypeMember.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeDescriptor.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/MemberDescriptor.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/AnnotationParameterValue.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeIdentifier.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeIdentifierTypes.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObject.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObjectFactory.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeObjectHashId.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypeNamesGenerator.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/TypesBase.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/dynamic-types/BuiltinAnnotationsTypeObject.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLProfileManager.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLParser.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLDynamicParser.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLElementParser.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLParser.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLParserCommon.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/utils/TimedConditionVariable.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/xmlparser/XMLProfileManager.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/statistics/fastdds/domain/DomainParticipant.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/statistics/fastdds/publisher/qos/DataWriterQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/TimedConditionVariable.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/statistics/fastdds/domain/DomainParticipant.cpp
-    ${PROJECT_SOURCE_DIR}/src/cpp/statistics/fastdds/publisher/qos/DataWriterQos.cpp
     )
 
 if (FASTDDS_STATISTICS)
@@ -172,6 +173,7 @@ target_include_directories(ListenerTests
     ${PROJECT_SOURCE_DIR}/test/mock/rtps/SharedMemTransportDescriptor
     ${PROJECT_SOURCE_DIR}/test/mock/rtps/TypeLookupManager
     ${PROJECT_SOURCE_DIR}/test/mock/rtps/WLP
+    ${PROJECT_SOURCE_DIR}/test/mock/rtps/XMLEndPointParser
     ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include
     ${PROJECT_SOURCE_DIR}/src/cpp
     ${THIRDPARTY_BOOST_INCLUDE_DIR}
diff -pruN 2.7.0+ds-2/test/unittest/dds/status/ListenerTests.cpp 2.7.1+ds-1/test/unittest/dds/status/ListenerTests.cpp
--- 2.7.0+ds-2/test/unittest/dds/status/ListenerTests.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/dds/status/ListenerTests.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -41,6 +41,7 @@
 using ::testing::StrictMock;
 using ::testing::NiceMock;
 using ::testing::Mock;
+using ::testing::_;
 
 using eprosima::fastrtps::rtps::RTPSDomain;
 
@@ -1328,10 +1329,18 @@ void verify_expectations_on_data_availab
 {
     fastrtps::rtps::CacheChange_t change;
 
-    RTPSDomain::reader_->listener_->onNewCacheChangeAdded(nullptr, &change);
+    auto seq = change.sequenceNumber;
+    bool notify_individual = false;
+
+    EXPECT_CALL(*RTPSDomain::reader_->history_, get_change(_, _, _))
+            .WillRepeatedly(testing::DoAll(testing::SetArgPointee<2>(&change), testing::Return(true)));
+
+    RTPSDomain::reader_->listener_->on_data_available(nullptr, change.writerGUID, seq, seq, notify_individual);
+
     Mock::VerifyAndClearExpectations(&datareader_listener_);
     Mock::VerifyAndClearExpectations(&subscriber_listener_);
     Mock::VerifyAndClearExpectations(&participant_listener_);
+    Mock::VerifyAndClearExpectations(RTPSDomain::reader_->history_);
 }
 
 TEST_F(UserListeners, data_available)
diff -pruN 2.7.0+ds-2/test/unittest/dds/subscriber/DataReaderTests.cpp 2.7.1+ds-1/test/unittest/dds/subscriber/DataReaderTests.cpp
--- 2.7.0+ds-2/test/unittest/dds/subscriber/DataReaderTests.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/dds/subscriber/DataReaderTests.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include <cassert>
+#include <forward_list>
 #include <thread>
 
 #include <gmock/gmock.h>
@@ -27,6 +28,7 @@
 #include <fastdds/dds/core/LoanableCollection.hpp>
 #include <fastdds/dds/core/LoanableSequence.hpp>
 #include <fastdds/dds/core/StackAllocatedSequence.hpp>
+#include <fastdds/dds/core/condition/WaitSet.hpp>
 #include <fastdds/dds/core/status/BaseStatus.hpp>
 #include <fastdds/dds/core/status/SampleRejectedStatus.hpp>
 #include <fastdds/dds/core/status/SubscriptionMatchedStatus.hpp>
@@ -42,8 +44,9 @@
 
 #include <fastdds/dds/subscriber/DataReader.hpp>
 #include <fastdds/dds/subscriber/DataReaderListener.hpp>
-#include <fastdds/dds/subscriber/Subscriber.hpp>
+#include <fastdds/dds/subscriber/ReadCondition.hpp>
 #include <fastdds/dds/subscriber/SampleInfo.hpp>
+#include <fastdds/dds/subscriber/Subscriber.hpp>
 #include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>
 #include <fastdds/dds/subscriber/qos/SubscriberQos.hpp>
 
@@ -61,9 +64,9 @@
 #include <fastdds/rtps/transport/test_UDPv4TransportDescriptor.h>
 #include <fastrtps/xmlparser/XMLProfileManager.h>
 
-namespace eprosima {
-namespace fastdds {
-namespace dds {
+using namespace eprosima::fastdds::dds;
+using namespace eprosima::fastrtps::rtps;
+using namespace eprosima::fastdds::rtps;
 
 static constexpr LoanableCollection::size_type num_test_elements = 10;
 
@@ -559,17 +562,17 @@ TEST_F(DataReaderTests, get_guid)
 
         void on_subscriber_discovery(
                 DomainParticipant*,
-                fastrtps::rtps::ReaderDiscoveryInfo&& info)
+                ReaderDiscoveryInfo&& info)
         {
             std::unique_lock<std::mutex> lock(mutex);
-            if (fastrtps::rtps::ReaderDiscoveryInfo::DISCOVERED_READER == info.status)
+            if (ReaderDiscoveryInfo::DISCOVERED_READER == info.status)
             {
                 guid = info.info.guid();
                 cv.notify_one();
             }
         }
 
-        fastrtps::rtps::GUID_t guid;
+        GUID_t guid;
         std::mutex mutex;
         std::condition_variable cv;
     }
@@ -577,9 +580,9 @@ TEST_F(DataReaderTests, get_guid)
 
     DomainParticipantQos participant_qos = PARTICIPANT_QOS_DEFAULT;
     participant_qos.wire_protocol().builtin.discovery_config.ignoreParticipantFlags =
-            static_cast<eprosima::fastrtps::rtps::ParticipantFilteringFlags_t>(
-        eprosima::fastrtps::rtps::ParticipantFilteringFlags_t::FILTER_DIFFERENT_HOST |
-        eprosima::fastrtps::rtps::ParticipantFilteringFlags_t::FILTER_DIFFERENT_PROCESS);
+            static_cast<ParticipantFilteringFlags_t>(
+        ParticipantFilteringFlags_t::FILTER_DIFFERENT_HOST |
+        ParticipantFilteringFlags_t::FILTER_DIFFERENT_PROCESS);
 
     DomainParticipant* listener_participant =
             DomainParticipantFactory::get_instance()->create_participant(0, participant_qos,
@@ -606,7 +609,7 @@ TEST_F(DataReaderTests, get_guid)
     DataReader* datareader = subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT);
     ASSERT_NE(datareader, nullptr);
 
-    fastrtps::rtps::GUID_t guid = datareader->guid();
+    GUID_t guid = datareader->guid();
 
     participant->enable();
 
@@ -617,7 +620,7 @@ TEST_F(DataReaderTests, get_guid)
         std::unique_lock<std::mutex> lock(discovery_listener.mutex);
         discovery_listener.cv.wait(lock, [&]()
                 {
-                    return fastrtps::rtps::GUID_t::unknown() != discovery_listener.guid;
+                    return GUID_t::unknown() != discovery_listener.guid;
                 });
     }
     ASSERT_EQ(guid, discovery_listener.guid);
@@ -664,7 +667,7 @@ TEST_F(DataReaderTests, InvalidQos)
     EXPECT_EQ(inconsistent_code, data_reader_->set_qos(qos));
 
     qos = DATAREADER_QOS_DEFAULT;
-    eprosima::fastrtps::rtps::Locator_t locator;
+    Locator_t locator;
     qos.endpoint().unicast_locator_list.push_back(locator);
     qos.properties().properties().emplace_back("fastdds.unique_network_flows", "");
     EXPECT_EQ(inconsistent_code, data_reader_->set_qos(qos));
@@ -1550,6 +1553,80 @@ TEST_F(DataReaderTests, read_unread)
     }
 }
 
+/*
+ * This test checks the behaviour of the two overloads of get_unread_count.
+ */
+TEST_F(DataReaderTests, get_unread_count)
+{
+    static const Duration_t time_to_wait(0, 100 * 1000 * 1000);
+    static constexpr int32_t num_samples = 10;
+    static constexpr uint64_t num_samples_check = static_cast<uint64_t>(num_samples);
+
+    const ReturnCode_t& ok_code = ReturnCode_t::RETCODE_OK;
+
+    DataWriterQos writer_qos = DATAWRITER_QOS_DEFAULT;
+    writer_qos.history().kind = KEEP_LAST_HISTORY_QOS;
+    writer_qos.history().depth = num_samples;
+    writer_qos.publish_mode().kind = SYNCHRONOUS_PUBLISH_MODE;
+    writer_qos.reliability().kind = RELIABLE_RELIABILITY_QOS;
+
+    DataReaderQos reader_qos = DATAREADER_QOS_DEFAULT;
+    reader_qos.reliability().kind = RELIABLE_RELIABILITY_QOS;
+    reader_qos.history().kind = KEEP_ALL_HISTORY_QOS;
+    reader_qos.resource_limits().max_instances = 1;
+    reader_qos.resource_limits().max_samples_per_instance = num_samples;
+    reader_qos.resource_limits().max_samples = 3 * num_samples;
+
+    create_instance_handles();
+    create_entities(nullptr, reader_qos, SUBSCRIBER_QOS_DEFAULT, writer_qos);
+
+    FooType data;
+    data.index(0);
+    data.message()[1] = '\0';
+
+    // Send a bunch of samples
+    for (char i = 0; i < num_samples; ++i)
+    {
+        data.message()[0] = i + '0';
+        EXPECT_EQ(ok_code, data_writer_->write(&data, handle_ok_));
+    }
+
+    // Reader should have 10 unread samples
+
+    // There are unread samples, so wait_for_unread should be ok
+    EXPECT_TRUE(data_reader_->wait_for_unread_message(time_to_wait));
+
+    // Calling get_unread_count() several times should always return the same value
+    for (char i = 0; i < num_samples; ++i)
+    {
+        EXPECT_EQ(num_samples_check, data_reader_->get_unread_count());
+    }
+
+    SampleInfo sample_info;
+    ASSERT_EQ(ReturnCode_t::RETCODE_OK, data_reader_->get_first_untaken_info(&sample_info));
+    ASSERT_EQ(SampleStateKind::NOT_READ_SAMPLE_STATE, sample_info.sample_state);
+
+    // Calling get_unread_count(false) several times should always return the same value
+    for (char i = 0; i < num_samples; ++i)
+    {
+        EXPECT_EQ(num_samples_check, data_reader_->get_unread_count(false));
+    }
+
+    ASSERT_EQ(ReturnCode_t::RETCODE_OK, data_reader_->get_first_untaken_info(&sample_info));
+    ASSERT_EQ(SampleStateKind::NOT_READ_SAMPLE_STATE, sample_info.sample_state);
+
+    // Calling get_unread_count(true) once will return the correct value
+    EXPECT_EQ(num_samples_check, data_reader_->get_unread_count(true));
+
+    ASSERT_EQ(ReturnCode_t::RETCODE_OK, data_reader_->get_first_untaken_info(&sample_info));
+    ASSERT_EQ(SampleStateKind::READ_SAMPLE_STATE, sample_info.sample_state);
+
+    // All variants should then return 0
+    EXPECT_EQ(0, data_reader_->get_unread_count(true));
+    EXPECT_EQ(0, data_reader_->get_unread_count(false));
+    EXPECT_EQ(0, data_reader_->get_unread_count());
+}
+
 template<typename DataType>
 void lookup_instance_test(
         DataType& data,
@@ -1931,7 +2008,7 @@ public:
     }
 
     bool deserialize(
-            fastrtps::rtps::SerializedPayload_t* payload,
+            SerializedPayload_t* payload,
             void* data) override
     {
         //Convert DATA to pointer of your type
@@ -2156,14 +2233,12 @@ TEST_F(DataReaderTests, SetListener)
 
 TEST_F(DataReaderTests, get_listening_locators)
 {
-    using IPLocator = eprosima::fastrtps::rtps::IPLocator;
-
     // Prepare specific listening locators
-    rtps::Locator unicast_locator;
+    Locator unicast_locator;
     IPLocator::setIPv4(unicast_locator, 127, 0, 0, 1);
     IPLocator::setPortRTPS(unicast_locator, 7399);
 
-    rtps::Locator multicast_locator;
+    Locator multicast_locator;
     IPLocator::setIPv4(multicast_locator, 239, 127, 0, 1);
     IPLocator::setPortRTPS(multicast_locator, 7398);
 
@@ -2180,7 +2255,7 @@ TEST_F(DataReaderTests, get_listening_lo
     EXPECT_FALSE(data_reader_->is_enabled());
 
     // Calling on disabled reader should return NOT_ENABLED
-    rtps::LocatorList locator_list;
+    LocatorList locator_list;
     EXPECT_EQ(ReturnCode_t::RETCODE_NOT_ENABLED, data_reader_->get_listening_locators(locator_list));
 
     // Enable and try again
@@ -2190,7 +2265,7 @@ TEST_F(DataReaderTests, get_listening_lo
     EXPECT_EQ(locator_list.size(), 2u);
     bool unicast_found = false;
     bool multicast_found = false;
-    for (const rtps::Locator& locator : locator_list)
+    for (const Locator& locator : locator_list)
     {
         unicast_found |= (locator == unicast_locator);
         multicast_found |= (locator == multicast_locator);
@@ -2316,12 +2391,10 @@ public:
  * This test checks that the DataReader methods defined in the standard not yet implemented in FastDDS return
  * ReturnCode_t::RETCODE_UNSUPPORTED. The following methods are checked:
  * 1. get_matched_publication_data
- * 2. create_readcondition
- * 3. create_querycondition
- * 4. delete_readcondition
- * 5. get_matched_publications
- * 6. get_key_value
- * 7. wait_for_historical_data
+ * 2. create_querycondition
+ * 3. get_matched_publications
+ * 4. get_key_value
+ * 5. wait_for_historical_data
  */
 TEST_F(DataReaderUnsupportedTests, UnsupportedDataReaderMethods)
 {
@@ -2342,7 +2415,7 @@ TEST_F(DataReaderUnsupportedTests, Unsup
     ASSERT_NE(data_reader, nullptr);
 
     builtin::PublicationBuiltinTopicData publication_data;
-    fastrtps::rtps::InstanceHandle_t publication_handle;
+    InstanceHandle_t publication_handle;
     EXPECT_EQ(
         ReturnCode_t::RETCODE_UNSUPPORTED,
         data_reader->get_matched_publication_data(publication_data, publication_handle));
@@ -2351,15 +2424,6 @@ TEST_F(DataReaderUnsupportedTests, Unsup
         SampleStateMask sample_states = ANY_SAMPLE_STATE;
         ViewStateMask view_states = ANY_VIEW_STATE;
         InstanceStateMask instance_states = ANY_INSTANCE_STATE;
-        EXPECT_EQ(
-            nullptr,
-            data_reader->create_readcondition(sample_states, view_states, instance_states));
-    }
-
-    {
-        SampleStateMask sample_states = ANY_SAMPLE_STATE;
-        ViewStateMask view_states = ANY_VIEW_STATE;
-        InstanceStateMask instance_states = ANY_INSTANCE_STATE;
         std::string query_expression;
         std::vector<std::string> query_parameters;
         EXPECT_EQ(
@@ -2372,70 +2436,16 @@ TEST_F(DataReaderUnsupportedTests, Unsup
                 query_parameters));
     }
 
-    {
-        EXPECT_EQ(
-            ReturnCode_t::RETCODE_UNSUPPORTED,
-            data_reader->delete_readcondition(nullptr));
-    }
-
-    {
-        FooBoundedSeq data_values;
-        SampleInfoSeq sample_infos;
-        int32_t max_samples = LENGTH_UNLIMITED;
-        EXPECT_EQ(ReturnCode_t::RETCODE_UNSUPPORTED, data_reader->read_w_condition(
-                    data_values,
-                    sample_infos,
-                    max_samples,
-                    nullptr));
-    }
-
-    {
-        FooBoundedSeq data_values;
-        SampleInfoSeq sample_infos;
-        int32_t max_samples = LENGTH_UNLIMITED;
-        fastrtps::rtps::InstanceHandle_t previous_handle;
-        EXPECT_EQ(ReturnCode_t::RETCODE_UNSUPPORTED, data_reader->read_next_instance_w_condition(
-                    data_values,
-                    sample_infos,
-                    max_samples,
-                    previous_handle,
-                    nullptr));
-    }
-
-    {
-        FooBoundedSeq data_values;
-        SampleInfoSeq sample_infos;
-        int32_t max_samples = LENGTH_UNLIMITED;
-        EXPECT_EQ(ReturnCode_t::RETCODE_UNSUPPORTED, data_reader->take_w_condition(
-                    data_values,
-                    sample_infos,
-                    max_samples,
-                    nullptr));
-    }
-
-    {
-        FooBoundedSeq data_values;
-        SampleInfoSeq sample_infos;
-        int32_t max_samples = LENGTH_UNLIMITED;
-        fastrtps::rtps::InstanceHandle_t previous_handle;
-        EXPECT_EQ(ReturnCode_t::RETCODE_UNSUPPORTED, data_reader->take_next_instance_w_condition(
-                    data_values,
-                    sample_infos,
-                    max_samples,
-                    previous_handle,
-                    nullptr));
-    }
-
-    std::vector<fastrtps::rtps::InstanceHandle_t> publication_handles;
+    std::vector<InstanceHandle_t> publication_handles;
     EXPECT_EQ(ReturnCode_t::RETCODE_UNSUPPORTED, data_reader->get_matched_publications(publication_handles));
 
-    fastrtps::rtps::InstanceHandle_t key_handle;
+    InstanceHandle_t key_handle;
     EXPECT_EQ(ReturnCode_t::RETCODE_UNSUPPORTED, data_reader->get_key_value(nullptr, key_handle));
 
     EXPECT_EQ(ReturnCode_t::RETCODE_UNSUPPORTED, data_reader->wait_for_historical_data({0, 1}));
 
-    // Expected logWarnings: create_querycondition, create_readcondition
-    HELPER_WaitForEntries(2);
+    // Expected logWarnings: create_querycondition
+    HELPER_WaitForEntries(1);
 
     ASSERT_EQ(subscriber->delete_datareader(data_reader), ReturnCode_t::RETCODE_OK);
     ASSERT_EQ(participant->delete_subscriber(subscriber), ReturnCode_t::RETCODE_OK);
@@ -2446,8 +2456,8 @@ TEST_F(DataReaderUnsupportedTests, Unsup
 // Regression test for #12133.
 TEST_F(DataReaderTests, read_samples_with_future_changes)
 {
-    fastrtps::LibrarySettingsAttributes att;
-    att.intraprocess_delivery = fastrtps::INTRAPROCESS_OFF;
+    eprosima::fastrtps::LibrarySettingsAttributes att;
+    att.intraprocess_delivery = eprosima::fastrtps::INTRAPROCESS_OFF;
     eprosima::fastrtps::xmlparser::XMLProfileManager::library_settings(att);
     static constexpr int32_t num_samples = 8;
     static constexpr int32_t expected_samples = 4;
@@ -2455,13 +2465,13 @@ TEST_F(DataReaderTests, read_samples_wit
     bool start_dropping_acks = false;
     bool start_dropping_datas = false;
     static const Duration_t time_to_wait(0, 100 * 1000 * 1000);
-    std::shared_ptr<rtps::test_UDPv4TransportDescriptor> test_descriptor =
-            std::make_shared<rtps::test_UDPv4TransportDescriptor>();
-    test_descriptor->drop_ack_nack_messages_filter_ = [&](fastrtps::rtps::CDRMessage_t&) -> bool
+    std::shared_ptr<test_UDPv4TransportDescriptor> test_descriptor =
+            std::make_shared<test_UDPv4TransportDescriptor>();
+    test_descriptor->drop_ack_nack_messages_filter_ = [&](CDRMessage_t&) -> bool
             {
                 return start_dropping_acks;
             };
-    test_descriptor->drop_data_messages_filter_ = [&](fastrtps::rtps::CDRMessage_t&) -> bool
+    test_descriptor->drop_data_messages_filter_ = [&](CDRMessage_t&) -> bool
             {
                 return start_dropping_datas;
             };
@@ -2554,6 +2564,13 @@ TEST_F(DataReaderTests, delete_contained
     SampleStateMask mock_sample_state_kind = ANY_SAMPLE_STATE;
     ViewStateMask mock_view_state_kind = ANY_VIEW_STATE;
     InstanceStateMask mock_instance_states = ANY_INSTANCE_STATE;
+
+    ReadCondition* read_condition = data_reader->create_readcondition(
+        mock_sample_state_kind,
+        mock_view_state_kind,
+        mock_instance_states);
+    EXPECT_NE(read_condition, nullptr);
+
     const std::string mock_query_expression;
     const std::vector<std::string> mock_query_parameters;
 
@@ -2568,12 +2585,454 @@ TEST_F(DataReaderTests, delete_contained
     // To be updated when Query Conditions are available
     ASSERT_EQ(query_condition, nullptr);
 
+    // Should fail with outstanding ReadConditions
+    ASSERT_EQ(subscriber->delete_datareader(data_reader), ReturnCode_t::RETCODE_PRECONDITION_NOT_MET);
+
+    // Should not fail with outstanding ReadConditions
     ASSERT_EQ(data_reader->delete_contained_entities(), ReturnCode_t::RETCODE_OK);
 }
 
-} // namespace dds
-} // namespace fastdds
-} // namespace eprosima
+TEST_F(DataReaderTests, read_conditions_management)
+{
+    create_entities();
+    DataReader& reader = *data_reader_;
+
+    // Condition masks
+    SampleStateMask sample_states = 0;
+    ViewStateMask view_states = 0;
+    InstanceStateMask instance_states = 0;
+
+    // Create and destroy testing
+
+    // 1- cannot create a ReadConditon that cannot be triggered
+    ReadCondition* cond = reader.create_readcondition( sample_states, view_states, instance_states);
+    EXPECT_EQ(cond, nullptr);
+
+    // 2- create a ReadCondition and destroy it
+    sample_states = ANY_SAMPLE_STATE;
+    cond = reader.create_readcondition( sample_states, view_states, instance_states);
+    EXPECT_NE(cond, nullptr);
+    ReturnCode_t res = reader.delete_readcondition(cond);
+    EXPECT_EQ(res, ReturnCode_t::RETCODE_OK);
+
+    // 3- Create several ReadConditions associated to the same masks (share implementation)
+    std::forward_list<ReadCondition*> conds;
+
+    for (int i = 0; i < 10; ++i )
+    {
+        conds.push_front(reader.create_readcondition( sample_states, view_states, instance_states));
+    }
+
+    for (ReadCondition* c : conds)
+    {
+        EXPECT_EQ(reader.delete_readcondition(c), ReturnCode_t::RETCODE_OK);
+    }
+    conds.clear();
+
+    // 4- Create several ReadConditions associated to different masks
+    sample_states = 0;
+    view_states = 0;
+    instance_states = 0;
+
+    for (int i = 0; i < 10; ++i )
+    {
+        conds.push_front(reader.create_readcondition( ++sample_states, ++view_states, ++instance_states));
+    }
+
+    for (ReadCondition* c : conds)
+    {
+        EXPECT_EQ(reader.delete_readcondition(c), ReturnCode_t::RETCODE_OK);
+    }
+    conds.clear();
+
+    // 5- Create several ReadConditions and destroy them using delete_contained_entities
+    sample_states = 0;
+    view_states = 0;
+    instance_states = 0;
+
+    for (int i = 0; i < 10; ++i )
+    {
+        conds.push_front(reader.create_readcondition( ++sample_states, ++view_states, ++instance_states));
+    }
+
+    EXPECT_EQ(reader.delete_contained_entities(), ReturnCode_t::RETCODE_OK);
+    conds.clear();
+
+    // 6- Check a DataReader only handles its own ReadConditions
+    DataReader* another_reader = subscriber_->create_datareader(topic_, DATAREADER_QOS_DEFAULT);
+    ASSERT_NE(another_reader, nullptr);
+
+    cond = another_reader->create_readcondition(sample_states, view_states, instance_states);
+    EXPECT_NE(cond, nullptr);
+    EXPECT_EQ(reader.delete_readcondition(cond), ReturnCode_t::RETCODE_PRECONDITION_NOT_MET);
+
+    // 7- Check the DataReader cannot be deleted with outstanding conditions
+    EXPECT_EQ(subscriber_->delete_datareader(another_reader), ReturnCode_t::RETCODE_PRECONDITION_NOT_MET);
+    // but delete_contained_entities() succeeds with outstanding ReadConditions
+    EXPECT_EQ(another_reader->delete_contained_entities(), ReturnCode_t::RETCODE_OK);
+    // no outstanding conditions (killed above)
+    EXPECT_EQ(subscriber_->delete_datareader(another_reader), ReturnCode_t::RETCODE_OK);
+}
+
+TEST_F(DataReaderTests, read_conditions_wait_on_SampleStateMask)
+{
+    DataReaderQos reader_qos = DATAREADER_QOS_DEFAULT;
+    reader_qos.reliability().kind = eprosima::fastrtps::RELIABLE_RELIABILITY_QOS;
+
+    DataWriterQos writer_qos = DATAWRITER_QOS_DEFAULT;
+    writer_qos.reliability().kind = eprosima::fastrtps::RELIABLE_RELIABILITY_QOS;
+
+    create_entities(nullptr, reader_qos, SUBSCRIBER_QOS_DEFAULT, writer_qos);
+    DataReader& data_reader = *data_reader_;
+    DataWriter& data_writer = *data_writer_;
+
+    // Condition masks
+    ViewStateMask view_states = ANY_VIEW_STATE;
+    InstanceStateMask instance_states = ANY_INSTANCE_STATE;
+
+    // Create the read conditions
+    ReadCondition* read_cond = data_reader.create_readcondition(READ_SAMPLE_STATE, view_states, instance_states);
+    EXPECT_NE(read_cond, nullptr);
+
+    ReadCondition* not_read_cond =
+            data_reader.create_readcondition(NOT_READ_SAMPLE_STATE, view_states, instance_states);
+    EXPECT_NE(not_read_cond, nullptr);
+
+    ReadCondition* any_read_cond = data_reader.create_readcondition(ANY_SAMPLE_STATE, view_states, instance_states);
+    EXPECT_NE(any_read_cond, nullptr);
+
+    // Create the waitset and associate
+    WaitSet ws;
+    EXPECT_EQ(ws.attach_condition(*read_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.attach_condition(*not_read_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.attach_condition(*any_read_cond), ReturnCode_t::RETCODE_OK);
+
+    // 1- Check NOT_READ_SAMPLE_STATE
+    // Send sample from a background thread
+    std::array<char, 256> test_message = {"Testing sample state"};
+    std::thread bw([&]
+            {
+                FooType msg;
+                msg.index(1);
+                msg.message(test_message);
+
+                // Allow main thread entering wait state, before sending
+                std::this_thread::sleep_for(std::chrono::seconds(1));
+                data_writer.write(&msg);
+            });
+
+    ConditionSeq triggered;
+    EXPECT_EQ(ws.wait(triggered, 2.0), ReturnCode_t::RETCODE_OK);
+    bw.join();
+
+    // Check the data is there
+    EXPECT_EQ(data_reader.get_unread_count(), 1);
+
+    // Check the conditions triggered were the expected ones
+    ASSERT_FALSE(read_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), read_cond), triggered.end());
+    ASSERT_TRUE(not_read_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), not_read_cond), triggered.end());
+    ASSERT_TRUE(any_read_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), any_read_cond), triggered.end());
+
+    // 2- Check READ_SAMPLE_STATE
+    // Read sample from a background thread
+    FooSeq datas;
+    SampleInfoSeq infos;
+
+    EXPECT_EQ(data_reader.read_w_condition(
+                datas,
+                infos,
+                1,
+                not_read_cond), ReturnCode_t::RETCODE_OK);
+
+    triggered.clear();
+    EXPECT_EQ(ws.wait(triggered, 1.0), ReturnCode_t::RETCODE_OK);
+
+    // Check data is good
+    ASSERT_TRUE(infos[0].valid_data);
+    EXPECT_EQ(datas[0].index(), 1u);
+    EXPECT_EQ(datas[0].message(), test_message);
+    EXPECT_EQ(data_reader.return_loan(datas, infos), ReturnCode_t::RETCODE_OK);
+
+    // Check the conditions triggered were the expected ones
+    ASSERT_TRUE(read_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), read_cond), triggered.end());
+    ASSERT_FALSE(not_read_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), not_read_cond), triggered.end());
+    ASSERT_TRUE(any_read_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), any_read_cond), triggered.end());
+
+    // take the sample to check the API works
+    EXPECT_EQ(data_reader.take_w_condition(
+                datas,
+                infos,
+                1,
+                read_cond), ReturnCode_t::RETCODE_OK);
+
+    // Check data is good
+    ASSERT_TRUE(infos[0].valid_data);
+    EXPECT_EQ(datas[0].index(), 1u);
+    EXPECT_EQ(datas[0].message(), test_message);
+    EXPECT_EQ(data_reader.return_loan(datas, infos), ReturnCode_t::RETCODE_OK);
+
+    // Detach conditions & destroy
+    EXPECT_EQ(ws.detach_condition(*read_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(read_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.detach_condition(*not_read_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(not_read_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.detach_condition(*any_read_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(any_read_cond), ReturnCode_t::RETCODE_OK);
+}
+
+TEST_F(DataReaderTests, read_conditions_wait_on_ViewStateMask)
+{
+    DataReaderQos reader_qos = DATAREADER_QOS_DEFAULT;
+    reader_qos.reliability().kind = eprosima::fastrtps::RELIABLE_RELIABILITY_QOS;
+
+    DataWriterQos writer_qos = DATAWRITER_QOS_DEFAULT;
+    writer_qos.reliability().kind = eprosima::fastrtps::RELIABLE_RELIABILITY_QOS;
+
+    create_entities(nullptr, reader_qos, SUBSCRIBER_QOS_DEFAULT, writer_qos);
+    DataReader& data_reader = *data_reader_;
+    DataWriter& data_writer = *data_writer_;
+
+    // Condition masks
+    SampleStateMask sample_states = ANY_SAMPLE_STATE;
+    InstanceStateMask instance_states = ANY_INSTANCE_STATE;
+
+    // Create the read conditions
+    ReadCondition* view_cond = data_reader.create_readcondition(sample_states, NEW_VIEW_STATE, instance_states);
+    EXPECT_NE(view_cond, nullptr);
+
+    ReadCondition* not_view_cond =
+            data_reader.create_readcondition(sample_states, NOT_NEW_VIEW_STATE, instance_states);
+    EXPECT_NE(not_view_cond, nullptr);
+
+    ReadCondition* any_view_cond = data_reader.create_readcondition(sample_states, ANY_VIEW_STATE, instance_states);
+    EXPECT_NE(any_view_cond, nullptr);
+
+    // Create the waitset and associate
+    WaitSet ws;
+    EXPECT_EQ(ws.attach_condition(*view_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.attach_condition(*not_view_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.attach_condition(*any_view_cond), ReturnCode_t::RETCODE_OK);
+
+    // 1- Check NEW_VIEW_STATE
+    // Send sample from a background thread
+    std::array<char, 256> test_message = {"Testing sample state"};
+    std::thread bw([&]
+            {
+                FooType msg;
+                msg.index(1);
+                msg.message(test_message);
+
+                // Allow main thread entering wait state, before sending
+                std::this_thread::sleep_for(std::chrono::seconds(1));
+                data_writer.write(&msg);
+            });
+
+    ConditionSeq triggered;
+    EXPECT_EQ(ws.wait(triggered, 2.0), ReturnCode_t::RETCODE_OK);
+    bw.join();
+
+    // Check the data is there
+    EXPECT_EQ(data_reader.get_unread_count(), 1);
+
+    // Check the conditions triggered were the expected ones
+    ASSERT_TRUE(view_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), view_cond), triggered.end());
+    ASSERT_FALSE(not_view_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), not_view_cond), triggered.end());
+    ASSERT_TRUE(any_view_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), any_view_cond), triggered.end());
+
+    // 2- Check NOT_NEW_VIEW_STATE
+    // Read the sample in order to change instance view state
+    FooSeq datas;
+    SampleInfoSeq infos;
+
+    EXPECT_EQ(data_reader.read_w_condition(
+                datas,
+                infos,
+                1,
+                view_cond), ReturnCode_t::RETCODE_OK);
+
+    triggered.clear();
+    EXPECT_EQ(ws.wait(triggered, 1.0), ReturnCode_t::RETCODE_OK);
+
+    // Check data is good
+    ASSERT_TRUE(infos[0].valid_data);
+    EXPECT_EQ(datas[0].index(), 1u);
+    EXPECT_EQ(datas[0].message(), test_message);
+    EXPECT_EQ(data_reader.return_loan(datas, infos), ReturnCode_t::RETCODE_OK);
+
+    // Check the conditions triggered were the expected ones
+    ASSERT_FALSE(view_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), view_cond), triggered.end());
+    ASSERT_TRUE(not_view_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), not_view_cond), triggered.end());
+    ASSERT_TRUE(any_view_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), any_view_cond), triggered.end());
+
+    // Detach conditions & destroy
+    EXPECT_EQ(ws.detach_condition(*view_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(view_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.detach_condition(*not_view_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(not_view_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.detach_condition(*any_view_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(any_view_cond), ReturnCode_t::RETCODE_OK);
+}
+
+TEST_F(DataReaderTests, read_conditions_wait_on_InstanceStateMask)
+{
+    DataReaderQos reader_qos = DATAREADER_QOS_DEFAULT;
+    reader_qos.reliability().kind = eprosima::fastrtps::RELIABLE_RELIABILITY_QOS;
+
+    DataWriterQos writer_qos = DATAWRITER_QOS_DEFAULT;
+    writer_qos.reliability().kind = eprosima::fastrtps::RELIABLE_RELIABILITY_QOS;
+
+    create_entities(nullptr, reader_qos, SUBSCRIBER_QOS_DEFAULT, writer_qos);
+    DataReader& data_reader = *data_reader_;
+    DataWriter& data_writer = *data_writer_;
+
+    // Condition masks
+    SampleStateMask sample_states = ANY_SAMPLE_STATE;
+    ViewStateMask view_states = ANY_VIEW_STATE;
+
+    // Create the read conditions
+    ReadCondition* alive_cond = data_reader.create_readcondition(sample_states, view_states, ALIVE_INSTANCE_STATE);
+    EXPECT_NE(alive_cond, nullptr);
+
+    ReadCondition* disposed_cond =
+            data_reader.create_readcondition(sample_states, view_states, NOT_ALIVE_DISPOSED_INSTANCE_STATE);
+    EXPECT_NE(disposed_cond, nullptr);
+
+    ReadCondition* no_writer_cond = data_reader.create_readcondition(sample_states, view_states,
+                    NOT_ALIVE_NO_WRITERS_INSTANCE_STATE);
+    EXPECT_NE(no_writer_cond, nullptr);
+
+    ReadCondition* any_cond = data_reader.create_readcondition(sample_states, view_states, ANY_INSTANCE_STATE);
+    EXPECT_NE(any_cond, nullptr);
+
+    // Create the waitset and associate
+    WaitSet ws;
+    EXPECT_EQ(ws.attach_condition(*alive_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.attach_condition(*disposed_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.attach_condition(*no_writer_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.attach_condition(*any_cond), ReturnCode_t::RETCODE_OK);
+
+    // 1- Check ALIVE_INSTANCE_STATE
+    // Send sample from a background thread
+    std::array<char, 256> test_message = {"Testing sample state"};
+
+    FooType msg;
+    msg.index(1);
+    msg.message(test_message);
+
+    std::thread bw([&]
+            {
+                // Allow main thread entering wait state, before sending
+                std::this_thread::sleep_for(std::chrono::seconds(1));
+                data_writer.write(&msg);
+            });
+
+    ConditionSeq triggered;
+    EXPECT_EQ(ws.wait(triggered, 2.0), ReturnCode_t::RETCODE_OK);
+    bw.join();
+
+    // Check the data is there
+    EXPECT_EQ(data_reader.get_unread_count(), 1);
+
+    // Check the conditions triggered were the expected ones
+    ASSERT_TRUE(alive_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), alive_cond), triggered.end());
+    ASSERT_FALSE(disposed_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), disposed_cond), triggered.end());
+    ASSERT_FALSE(no_writer_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), no_writer_cond), triggered.end());
+    ASSERT_TRUE(any_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), any_cond), triggered.end());
+
+    // 2 - Check NOT_ALIVE_DISPOSED_INSTANCE_STATE
+    // unregister the instance
+    EXPECT_EQ(data_writer.unregister_instance(&msg, HANDLE_NIL), ReturnCode_t::RETCODE_OK);
+
+    triggered.clear();
+    EXPECT_EQ(ws.wait(triggered, 1.0), ReturnCode_t::RETCODE_OK);
+
+    // Check the conditions triggered were the expected ones
+    ASSERT_FALSE(alive_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), alive_cond), triggered.end());
+    ASSERT_TRUE(disposed_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), disposed_cond), triggered.end());
+    ASSERT_FALSE(no_writer_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), no_writer_cond), triggered.end());
+    ASSERT_TRUE(any_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), any_cond), triggered.end());
+
+    // 4 - Check (read|take)_next_instance_w_condition() APIs
+    // take the sample to check the API works
+    FooSeq datas;
+    SampleInfoSeq infos;
+    EXPECT_EQ(data_reader.take_next_instance_w_condition(
+                datas,
+                infos,
+                1,
+                HANDLE_NIL,
+                disposed_cond), ReturnCode_t::RETCODE_OK);
+
+    // Check data is bad because the sample for instance 1 was unregistered
+    ASSERT_FALSE(infos[0].valid_data);
+    InstanceHandle_t prev_handle = infos[0].instance_handle;
+    EXPECT_EQ(data_reader.return_loan(datas, infos), ReturnCode_t::RETCODE_OK);
+
+    // new instance
+    msg.index(2u);
+    data_writer.write(&msg);
+
+    EXPECT_EQ(data_reader.read_next_instance_w_condition(
+                datas,
+                infos,
+                1,
+                prev_handle,
+                alive_cond), ReturnCode_t::RETCODE_OK);
+
+    // Check data is good
+    ASSERT_TRUE(infos[0].valid_data);
+    EXPECT_EQ(datas[0].index(), 2u);
+    EXPECT_EQ(datas[0].message(), test_message);
+    EXPECT_EQ(data_reader.return_loan(datas, infos), ReturnCode_t::RETCODE_OK);
+
+    // 5 - Check NOT_ALIVE_NO_WRITERS_INSTANCE_STATE
+    // delete the writer to remove all writers from a new instance
+    ASSERT_EQ(publisher_->delete_datawriter(data_writer_), ReturnCode_t::RETCODE_OK);
+    data_writer_ = nullptr;
+
+    triggered.clear();
+    EXPECT_EQ(ws.wait(triggered, 1.0), ReturnCode_t::RETCODE_OK);
+
+    // Check the conditions triggered were the expected ones
+    ASSERT_FALSE(alive_cond->get_trigger_value());
+    EXPECT_EQ(std::find(triggered.begin(), triggered.end(), alive_cond), triggered.end());
+    ASSERT_TRUE(disposed_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), disposed_cond), triggered.end());
+    ASSERT_TRUE(no_writer_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), no_writer_cond), triggered.end());
+    ASSERT_TRUE(any_cond->get_trigger_value());
+    EXPECT_NE(std::find(triggered.begin(), triggered.end(), any_cond), triggered.end());
+
+    // Detach conditions & destroy
+    EXPECT_EQ(ws.detach_condition(*alive_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(alive_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.detach_condition(*disposed_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(disposed_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.detach_condition(*no_writer_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(no_writer_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(ws.detach_condition(*any_cond), ReturnCode_t::RETCODE_OK);
+    EXPECT_EQ(data_reader.delete_readcondition(any_cond), ReturnCode_t::RETCODE_OK);
+}
 
 int main(
         int argc,
diff -pruN 2.7.0+ds-2/test/unittest/logging/CMakeLists.txt 2.7.1+ds-1/test/unittest/logging/CMakeLists.txt
--- 2.7.0+ds-2/test/unittest/logging/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/logging/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -25,6 +25,7 @@ set(LOG_COMMON_SOURCE
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutErrConsumer.cpp
     )
 
+# LOG TEST
 set(LOGTESTS_TEST_SOURCE LogTests.cpp)
 
 set(LOGTESTS_SOURCE
@@ -37,7 +38,9 @@ add_executable(LogTests ${LOGTESTS_SOURC
 target_compile_definitions(LogTests PRIVATE FASTRTPS_NO_LIB
     $<$<AND:$<NOT:$<BOOL:${WIN32}>>,$<STREQUAL:"${CMAKE_BUILD_TYPE}","Debug">>:__DEBUG>
     $<$<BOOL:${INTERNAL_DEBUG}>:__INTERNALDEBUG> # Internal debug activated.
+    HAVE_LOG_NO_INFO=0 FASTDDS_ENFORCE_LOG_INFO # logInfo is used in some tests
     )
+
 target_include_directories(LogTests PRIVATE
     ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include)
 target_link_libraries(LogTests GTest::gtest ${MOCKS}
@@ -45,6 +48,7 @@ target_link_libraries(LogTests GTest::gt
     )
 add_gtest(LogTests SOURCES ${LOGTESTS_TEST_SOURCE})
 
+# LOG FILE TEST
 set(LOGFILETESTS_TEST_SOURCE LogFileTests.cpp)
 
 set(LOGFILETESTS_SOURCE
diff -pruN 2.7.0+ds-2/test/unittest/logging/LogTests.cpp 2.7.1+ds-1/test/unittest/logging/LogTests.cpp
--- 2.7.0+ds-2/test/unittest/logging/LogTests.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/logging/LogTests.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -13,14 +13,13 @@
 // limitations under the License.
 //
 
-#define FASTDDS_ENFORCE_LOG_INFO
-
 #include <fastdds/dds/log/Log.hpp>
 #include <fastdds/dds/log/OStreamConsumer.hpp>
 #include <fastdds/dds/log/StdoutConsumer.hpp>
 #include <fastdds/dds/log/StdoutErrConsumer.hpp>
 #include "mock/MockConsumer.h"
 #include <gtest/gtest.h>
+#include <atomic>
 #include <memory>
 #include <thread>
 #include <chrono>
@@ -35,6 +34,10 @@ public:
 
     LogTests()
     {
+        // Remove all previous log consumers so test msgs do not show off in the console.
+        // NOTE: This is not working because Mock inherits directly from StdOut (dont know why)
+        Log::ClearConsumers();
+
         mockConsumer = new MockConsumer();
 
         Log::RegisterConsumer(std::unique_ptr<LogConsumer>(mockConsumer));
@@ -64,6 +67,27 @@ public:
             uint32_t amount);
 };
 
+class LogConsumerMock : public LogConsumer
+{
+public:
+
+    LogConsumerMock(
+            std::atomic<unsigned int>& consumed_reference)
+        : logs_consumed_(consumed_reference)
+    {
+    }
+
+    void Consume(
+            const Log::Entry&) override
+    {
+        logs_consumed_++;
+    }
+
+protected:
+
+    std::atomic<unsigned int>& logs_consumed_;
+};
+
 TEST_F(LogTests, asynchronous_logging)
 {
     logError(SampleCategory, "Sample error message");
@@ -522,6 +546,123 @@ std::vector<Log::Entry> LogTests::HELPER
     return mockConsumer->ConsumedEntries();
 }
 
+/**
+ * TEST: Test Flush functionality using a custom consumer.
+ *
+ * CASES:
+ * - 1 log Info
+ * - 1 log Warning
+ * - 1 log Error
+ * - N logs
+ */
+TEST_F(LogTests, flush_info)
+{
+    // Set general verbosity
+    Log::SetVerbosity(Log::Info);
+
+    // Create Log Consumer
+    std::atomic<unsigned int> logs_consumed(0);
+    Log::RegisterConsumer(
+        std::unique_ptr<LogConsumerMock>(new LogConsumerMock(logs_consumed)));
+
+    // Raise a log message
+    logInfo(TEST_FLUSH, "Info message");
+
+    // Flush the log
+    Log::Flush();
+
+    // Check that the consumer has the log message
+    ASSERT_EQ(1u, logs_consumed.load());
+}
+
+TEST_F(LogTests, flush_warning)
+{
+    // Set general verbosity
+    Log::SetVerbosity(Log::Info);
+
+    // Create Log Consumer
+    std::atomic<unsigned int> logs_consumed(0);
+    Log::RegisterConsumer(
+        std::unique_ptr<LogConsumerMock>(new LogConsumerMock(logs_consumed)));
+
+    // Raise a log message
+    logWarning(TEST_FLUSH, "Warning message");
+
+    // Flush the log
+    Log::Flush();
+
+    // Check that the consumer has the log message
+    ASSERT_EQ(1u, logs_consumed.load());
+}
+
+TEST_F(LogTests, flush_error)
+{
+    // Set general verbosity
+    Log::SetVerbosity(Log::Info);
+
+    // Create Log Consumer
+    std::atomic<unsigned int> logs_consumed(0);
+    Log::RegisterConsumer(
+        std::unique_ptr<LogConsumerMock>(new LogConsumerMock(logs_consumed)));
+
+    // Raise a log message
+    logError(TEST_FLUSH, "Error message");
+
+    // Flush the log
+    Log::Flush();
+
+    // Check that the consumer has the log message
+    ASSERT_EQ(1u, logs_consumed.load());
+}
+
+/**
+ * @brief This tests that doing Flush will always wait till the message has been correctly consumed by all consumers
+ *
+ * This test creats a custom consumer, and for N iterations, it raises a log message, and then flushes the log.
+ * After this flush, the internal consumer variable must be raised.
+ *
+ * This tests uses an auxiliary thread to simulate a multithread production of log messages.
+ * This is needed because raising the log in the same thread that is flushed does not fail consistently.
+ * However, adding random delays in the log queue force this error much more often.
+ * The variable is checked to be equal or higher than 1, not just 1, because the consumer will also consume thread logs.
+ *
+ * N = 1000
+ */
+TEST_F(LogTests, flush_n)
+{
+    // Set general verbosity
+    Log::SetVerbosity(Log::Info);
+    unsigned int n_logs = 1000;
+
+    // Create Log Consumer
+    std::atomic<unsigned int> logs_consumed(0);
+    Log::RegisterConsumer(
+        std::unique_ptr<LogConsumerMock>(new LogConsumerMock(logs_consumed)));
+
+    std::thread loggind_thread(
+        [&n_logs]()
+        {
+            for (unsigned int i = 0; i < n_logs; i++)
+            {
+                logInfo(TEST_FLUSH, "Secondary message " << i);
+            }
+        }
+        );
+
+    // Raise N messages
+    for (unsigned int i = 1; i < n_logs; i++)
+    {
+        logs_consumed.store(0);
+        logInfo(TEST_FLUSH, "Info message " << i);
+
+        // Flush the log
+        Log::Flush();
+        ASSERT_GE(logs_consumed.load(), 1u);
+    }
+
+    loggind_thread.join();
+}
+
 int main(
         int argc,
         char** argv)
diff -pruN 2.7.0+ds-2/test/unittest/rtps/builtin/BuiltinDataSerializationTests.cpp 2.7.1+ds-1/test/unittest/rtps/builtin/BuiltinDataSerializationTests.cpp
--- 2.7.0+ds-2/test/unittest/rtps/builtin/BuiltinDataSerializationTests.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/rtps/builtin/BuiltinDataSerializationTests.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -15,8 +15,9 @@
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
-#include <fastrtps/rtps/builtin/data/WriterProxyData.h>
+#include <fastrtps/rtps/builtin/data/ParticipantProxyData.h>
 #include <fastrtps/rtps/builtin/data/ReaderProxyData.h>
+#include <fastrtps/rtps/builtin/data/WriterProxyData.h>
 #include <fastrtps/rtps/network/NetworkFactory.h>
 #include <fastdds/core/policy/ParameterSerializer.hpp>
 
@@ -347,6 +348,83 @@ TEST(BuiltinDataSerializationTests, igno
     }
 }
 
+TEST(BuiltinDataSerializationTests, property_list_with_binary_properties)
+{
+    octet data_p_buffer[] =
+    {
+        // Encapsulation
+        0x00, 0x03, 0x00, 0x00,
+
+        // PID_PROPERTY_LIST
+        0x59, 0, 104, 0,
+        // 3 properties
+        0x03, 0x00, 0x00, 0x00,
+        // key-1
+        0x0e, 0x00, 0x00, 0x00,
+        0x5f, 0x5f, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x00, 0x00, 0x00,
+        // value-1
+        0x07, 0x00, 0x00, 0x00,
+        0x74, 0x61, 0x6c, 0x6b, 0x65, 0x72, 0x00, 0x00,
+        // key-2
+        0x06, 0x00, 0x00, 0x00,
+        0x5f, 0x5f, 0x50, 0x69, 0x64, 0x00, 0x00, 0x00,
+        // value-2
+        0x05, 0x00, 0x00, 0x00,
+        0x32, 0x35, 0x31, 0x39, 0x00, 0x00, 0x00, 0x00,
+        // key-3
+        0x0b, 0x00, 0x00, 0x00,
+        0x5f, 0x5f, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x00, 0x00,
+        // value-3
+        0x11, 0x00, 0x00, 0x00,
+        0x6e, 0x6f, 0x6e, 0x5f, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x5f, 0x68, 0x61, 0x73, 0x68,
+        0x00, 0x00, 0x00, 0x00,
+        // 0 binary properties
+        0x00, 0x00, 0x00, 0x00,
+
+        // PID_PROTOCOL_VERSION
+        0x15, 0, 4, 0,
+        2, 1, 0, 0,
+
+        // PID_VENDORID
+        0x16, 0, 4, 0,
+        1, 16, 0, 0,
+
+        // PID_PARTICIPANT_LEASE_DURATION
+        0x02, 0, 8, 0,
+        10, 0, 0, 0, 0, 0, 0, 0,
+
+        // PID_PARTICIPANT_GUID
+        0x50, 0, 16, 0,
+        1, 16, 54, 83, 136, 247, 149, 252, 47, 105, 174, 141, 0, 0, 1, 193,
+
+        // PID_BUILTIN_ENDPOINT_SET
+        0x58, 0, 4, 0,
+        63, 12, 0, 0,
+
+        // PID_DOMAIN_ID
+        0x0f, 0, 4, 0,
+        0, 0, 0, 0,
+
+        // PID_DEFAULT_UNICAST_LOCATOR
+        0x31, 0, 24, 0,
+        1, 0, 0, 0, 68, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 31, 133, 54,
+
+        // PID_METATRAFFIC_UNICAST_LOCATOR
+        0x32, 0, 24, 0,
+        1, 0, 0, 0, 68, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 31, 133, 54,
+
+        // PID_SENTINEL
+        0x01, 0, 0, 0
+    };
+
+    CDRMessage_t msg(0);
+    msg.init(data_p_buffer, static_cast<uint32_t>(sizeof(data_p_buffer)));
+    msg.length = msg.max_size;
+
+    ParticipantProxyData out(RTPSParticipantAllocationAttributes{});
+    EXPECT_NO_THROW(EXPECT_TRUE(out.readFromCDRMessage(&msg, true, network, false)));
+}
+
 /*!
  * \test RTPS-CFT-CFP-01 Tests serialization of `ContentFilterProperty_t` works successfully without parameters.
  */
diff -pruN 2.7.0+ds-2/test/unittest/rtps/builtin/CMakeLists.txt 2.7.1+ds-1/test/unittest/rtps/builtin/CMakeLists.txt
--- 2.7.0+ds-2/test/unittest/rtps/builtin/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/rtps/builtin/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -21,9 +21,13 @@ set(BUILTIN_DATA_SERIALIZATION_TESTS_SOU
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/ParameterList.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/WriterQos.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/ReaderQos.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/ParticipantProxyData.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/ReaderProxyData.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/WriterProxyData.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerConsts.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/ResourceEvent.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/TimedEvent.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/TimedEventImpl.cpp
 
     ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp
 
@@ -54,6 +58,7 @@ set(BUILTIN_DATA_SERIALIZATION_TESTS_SOU
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
     ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp
+    ${PROJECT_SOURCE_DIR}/src/cpp/utils/TimedConditionVariable.cpp
     )
 
 if(WIN32)
diff -pruN 2.7.0+ds-2/test/unittest/rtps/history/ReaderHistoryTests.cpp 2.7.1+ds-1/test/unittest/rtps/history/ReaderHistoryTests.cpp
--- 2.7.0+ds-2/test/unittest/rtps/history/ReaderHistoryTests.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/rtps/history/ReaderHistoryTests.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include <algorithm>
+#include <random>
+#include <vector>
+
 #include <gtest/gtest.h>
 #include <gmock/gmock.h>
 
@@ -19,7 +23,8 @@
 #include <fastrtps/rtps/reader/StatefulReader.h>
 #include <fastrtps/utils/TimedMutex.hpp>
 
-#include <vector>
+#include <rtps/common/ChangeComparison.hpp>
+
 
 using namespace eprosima::fastrtps;
 using namespace ::rtps;
@@ -171,6 +176,70 @@ TEST_F(ReaderHistoryTests, get_change)
     }
 }
 
+TEST_F(ReaderHistoryTests, change_order)
+{
+    constexpr uint32_t n_writers = 4;
+    constexpr uint32_t changes_per_writer = 5;
+    std::vector<CacheChange_t*> changes;
+
+    // Create changes list
+    for (uint32_t i = 1; i <= n_writers; i++)
+    {
+        uint32_t ts = 0;
+        GUID_t writer_guid = GUID_t(GuidPrefix_t::unknown(), i);
+
+        for (uint32_t j = 1; j <= changes_per_writer; j++)
+        {
+            CacheChange_t* ch = new CacheChange_t(0);
+            ch->writerGUID = writer_guid;
+            ch->sequenceNumber = SequenceNumber_t(0, j);
+            ch->sourceTimestamp = rtps::Time_t(0, ts);
+
+            changes.push_back(ch);
+            ts += i;
+        }
+    }
+
+    size_t total_changes = changes.size();
+    ASSERT_EQ(total_changes, n_writers * changes_per_writer);
+    int num_removes = static_cast<int>(total_changes * total_changes);
+    EXPECT_CALL(*readerMock, change_removed_by_history(_)).Times(num_removes).WillRepeatedly(Return(true));
+    EXPECT_CALL(*readerMock, releaseCache(_)).Times(num_removes);
+
+    auto rng = std::default_random_engine{};
+    for (size_t n = 0; n < changes.size(); ++n)
+    {
+        // Shuffle the generated samples
+        std::shuffle(std::begin(changes), std::end(changes), rng);
+
+        // Add samples to history
+        for (CacheChange_t* ch : changes)
+        {
+            history->add_change(ch);
+        }
+
+        // Check full history order
+        ASSERT_EQ(history->getHistorySize(), total_changes);
+        for (auto it = history->changesBegin(); it != history->changesEnd(); ++it)
+        {
+            for (auto it2 = it + 1; it2 != history->changesEnd(); ++it2)
+            {
+                EXPECT_FALSE(eprosima::fastdds::rtps::history_order_cmp(*it2, *it));
+            }
+        }
+
+        // Prepare for next iteration
+        history->remove_all_changes();
+        ASSERT_EQ(history->getHistorySize(), 0);
+    }
+
+    // Clean-up
+    for (CacheChange_t* ch : changes)
+    {
+        delete ch;
+    }
+}
+
 TEST_F(ReaderHistoryTests, get_min_change_from_writer)
 {
     for (uint32_t i = 0; i < num_changes; i++)
diff -pruN 2.7.0+ds-2/test/unittest/security/authentication/BuiltinPKIDHTests.cpp 2.7.1+ds-1/test/unittest/security/authentication/BuiltinPKIDHTests.cpp
--- 2.7.0+ds-2/test/unittest/security/authentication/BuiltinPKIDHTests.cpp	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/security/authentication/BuiltinPKIDHTests.cpp	2022-07-28 07:22:18.000000000 +0000
@@ -12,6 +12,10 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// TODO This isn't a proper fix for compatibility with OpenSSL 3.0, but
+// suppresses the warnings until true OpenSSL 3.0 APIs can be used.
+#define OPENSSL_API_COMPAT 10101
+
 #include "AuthenticationPluginTests.hpp"
 
 #include <security/authentication/PKIIdentityHandle.h>
diff -pruN 2.7.0+ds-2/test/unittest/statistics/dds/CMakeLists.txt 2.7.1+ds-1/test/unittest/statistics/dds/CMakeLists.txt
--- 2.7.0+ds-2/test/unittest/statistics/dds/CMakeLists.txt	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/test/unittest/statistics/dds/CMakeLists.txt	2022-07-28 07:22:18.000000000 +0000
@@ -113,31 +113,32 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTI
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/StatusCondition.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/StatusConditionImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/condition/WaitSetImpl.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/QosPolicyUtils.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/ParameterList.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/QosPolicyUtils.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/core/policy/QosPolicyUtils.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipant.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/DomainParticipantFactory.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/domain/qos/DomainParticipantQos.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/FileConsumer.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/Log.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/OStreamConsumer.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutConsumer.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/log/StdoutErrConsumer.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriter.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriterImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriterHistory.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/DataWriterImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/PublisherImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/DataWriterQos.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/PublisherQos.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/publisher/qos/WriterQos.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/DataReader.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/DataReaderImpl.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/ReadCondition.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/Subscriber.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/SubscriberImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/history/DataReaderHistory.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/DataReaderQos.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/ReaderQos.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/Subscriber.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/SubscriberImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/subscriber/qos/SubscriberQos.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/ContentFilteredTopic.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/ContentFilteredTopicImpl.cpp
@@ -146,16 +147,20 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTI
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TopicProxyFactory.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/TypeSupport.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/fastdds/topic/qos/TopicQos.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingListener.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingNotification.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingPayloadPool.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/RTPSDomain.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/attributes/PropertyPolicy.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/BuiltinProtocols.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/ParticipantProxyData.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/ReaderProxyData.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/data/WriterProxyData.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/backup/SharedBackupFunctions.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryDataBase.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantsAckStatus.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantInfo.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoveryParticipantsAckStatus.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/DiscoverySharedInfo.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/database/backup/SharedBackupFunctions.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDP.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDPClient.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/discovery/endpoint/EDPServer.cpp
@@ -176,9 +181,6 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTI
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/liveliness/WLP.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/builtin/liveliness/WLPListener.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/common/Time_t.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingListener.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingNotification.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/DataSharing/DataSharingPayloadPool.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerConsts.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/FlowControllerFactory.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/flowcontrol/ThroughputControllerDescriptor.cpp
@@ -198,8 +200,8 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTI
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/participant/RTPSParticipant.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/participant/RTPSParticipantImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/persistence/PersistenceFactory.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/persistence/sqlite3.c
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/persistence/SQLite3PersistenceService.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/persistence/sqlite3.c
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/reader/RTPSReader.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/reader/StatefulPersistentReader.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/reader/StatefulReader.cpp
@@ -209,14 +211,11 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTI
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/ResourceEvent.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/TimedEvent.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/resources/TimedEventImpl.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/RTPSDomain.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/ChannelResource.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPAcceptor.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPAcceptorBasic.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResource.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPChannelResourceBasic.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/TCPControlMessage.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/RTCPMessageManager.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPTransportInterface.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv4Transport.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/TCPv6Transport.cpp
@@ -225,12 +224,14 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTI
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPv4Transport.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/UDPv6Transport.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/shared_mem/SharedMemTransportDescriptor.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/RTCPMessageManager.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/transport/tcp/TCPControlMessage.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/LivelinessManager.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/LocatorSelectorSender.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/PersistentWriter.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/RTPSWriter.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/ReaderLocator.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/ReaderProxy.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/RTPSWriter.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/StatefulPersistentWriter.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/StatefulWriter.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/rtps/writer/StatelessPersistentWriter.cpp
@@ -246,17 +247,17 @@ if (SQLITE3_SUPPORT AND FASTDDS_STATISTI
         ${PROJECT_SOURCE_DIR}/src/cpp/statistics/fastdds/domain/DomainParticipantStatisticsListener.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/statistics/fastdds/publisher/qos/DataWriterQos.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/statistics/rtps/StatisticsBase.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/statistics/rtps/writer/StatisticsWriterImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/statistics/rtps/reader/StatisticsReaderImpl.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/statistics/rtps/writer/StatisticsWriterImpl.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/statistics/types/types.cxx
         ${PROJECT_SOURCE_DIR}/src/cpp/statistics/types/typesPubSubTypes.cxx
         ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPFinder.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/utils/IPLocator.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/utils/StringMatching.cpp
-        ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/utils/SystemInfo.cpp
         ${PROJECT_SOURCE_DIR}/src/cpp/utils/TimedConditionVariable.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/utils/md5.cpp
+        ${PROJECT_SOURCE_DIR}/src/cpp/utils/string_convert.cpp
         )
 
     # SHM Transport
diff -pruN 2.7.0+ds-2/versions.md 2.7.1+ds-1/versions.md
--- 2.7.0+ds-2/versions.md	2022-07-04 14:32:31.000000000 +0000
+++ 2.7.1+ds-1/versions.md	2022-07-28 07:22:18.000000000 +0000
@@ -1,3 +1,9 @@
+Version 2.7.1
+-------------
+
+* ReadCondition implementation according to DDS version 1.4 standard document
+* Added a new CMake option to allow users to force the use of our third party shared_mutex
+
 Version 2.7.0
 -------------
 
