-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: separated queue into a shared library * fix: compile structure done feat: tests added * fix: queue tests finalised * fix: header-only library built * fix: linter errors fixed * fix: requested changes implemented fix: added header-only include location correctly
- Loading branch information
Showing
8 changed files
with
197 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
cmake_minimum_required(VERSION 3.8) | ||
project(common) | ||
|
||
find_package(ament_cmake REQUIRED) | ||
|
||
add_library(${PROJECT_NAME} INTERFACE) | ||
target_include_directories( | ||
${PROJECT_NAME} | ||
INTERFACE "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>" | ||
"$<INSTALL_INTERFACE:include>") | ||
|
||
install( | ||
TARGETS ${PROJECT_NAME} | ||
EXPORT "export_${PROJECT_NAME}" | ||
ARCHIVE DESTINATION lib | ||
LIBRARY DESTINATION lib | ||
RUNTIME DESTINATION bin | ||
INCLUDES | ||
DESTINATION include) | ||
|
||
install(DIRECTORY include/ DESTINATION include/${PROJECT_NAME}) | ||
|
||
if(BUILD_TESTING) | ||
find_package(ament_cmake_gtest REQUIRED) | ||
add_subdirectory("tests") | ||
endif() | ||
|
||
ament_export_targets("export_${PROJECT_NAME}") | ||
ament_package() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?xml version="1.0"?> | ||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?> | ||
<package format="3"> | ||
<name>common</name> | ||
<version>0.0.0</version> | ||
<description>common</description> | ||
<license>MIT</license> | ||
<maintainer email="[email protected]">Denis Bakin</maintainer> | ||
|
||
<buildtool_depend>ament_cmake</buildtool_depend> | ||
<buildtool_depend>rosidl_default_generators</buildtool_depend> | ||
<build_depend>builtin_interfaces</build_depend> | ||
|
||
<test_depend>ament_lint_auto</test_depend> | ||
<test_depend>ament_lint_common</test_depend> | ||
<test_depend>ament_cmake_gtest</test_depend> | ||
|
||
<member_of_group>rosidl_interface_packages</member_of_group> | ||
|
||
<export> | ||
<build_type>ament_cmake</build_type> | ||
</export> | ||
</package> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
ament_add_gtest(queue_test src/test.cpp) | ||
target_include_directories( | ||
queue_test PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>") | ||
target_link_libraries(queue_test ${PROJECT_NAME}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
#include "lock_free_queue.h" | ||
|
||
#include <gtest/gtest.h> | ||
|
||
#include <thread> | ||
#include <vector> | ||
|
||
TEST(Correctness, push) { | ||
handy::LockFreeQueue<int> queue(2); | ||
ASSERT_TRUE(queue.push(2)); | ||
ASSERT_TRUE(queue.push(2)); | ||
ASSERT_FALSE(queue.push(2)); | ||
ASSERT_FALSE(queue.push(2)); | ||
} | ||
|
||
TEST(Correctness, pop) { | ||
int value; | ||
handy::LockFreeQueue<int> queue(2); | ||
ASSERT_FALSE(queue.pop(value)); | ||
ASSERT_FALSE(queue.pop(value)); | ||
} | ||
|
||
TEST(Correctness, pushpop) { | ||
int value = 0; | ||
handy::LockFreeQueue<int> queue(2); | ||
ASSERT_TRUE(queue.push(1)); | ||
ASSERT_TRUE(queue.pop(value)); | ||
ASSERT_EQ(value, 1); | ||
ASSERT_FALSE(queue.pop(value)); | ||
|
||
ASSERT_TRUE(queue.push(2)); | ||
ASSERT_TRUE(queue.push(3)); | ||
ASSERT_FALSE(queue.push(4)); | ||
|
||
ASSERT_TRUE(queue.pop(value)); | ||
ASSERT_EQ(value, 2); | ||
ASSERT_TRUE(queue.pop(value)); | ||
ASSERT_EQ(value, 3); | ||
|
||
ASSERT_FALSE(queue.pop(value)); | ||
} | ||
|
||
TEST(Performance, NoSpuriousFails) { | ||
const int n = 1024 * 1024; | ||
const int n_threads = 8; | ||
handy::LockFreeQueue<int> queue(n * n_threads); | ||
|
||
std::vector<std::thread> writers; | ||
// check that all threads managed to push elements without fake fails | ||
for (int i = 0; i < n_threads; i++) { | ||
writers.emplace_back([&] { // NOLINT | ||
for (int j = 0; j < n; ++j) { | ||
ASSERT_TRUE(queue.push(0)); | ||
} | ||
}); | ||
} | ||
|
||
for (auto& t : writers) { | ||
t.join(); | ||
} | ||
|
||
std::vector<std::thread> readers; | ||
// check that all threads managed to pop elements without fake fails | ||
// and no elements were lost | ||
for (int i = 0; i < n_threads; i++) { | ||
readers.emplace_back([&] { // NOLINT | ||
for (int j = 0; j < n; ++j) { | ||
int k; | ||
ASSERT_TRUE(queue.pop(k)); | ||
} | ||
}); | ||
} | ||
|
||
for (auto& t : readers) { | ||
t.join(); | ||
} | ||
} | ||
|
||
TEST(Performance, NoQueueLock) { | ||
const int n = 1024 * 1024; | ||
const int n_threads = 8; | ||
handy::LockFreeQueue<int> queue(64); | ||
|
||
std::vector<std::thread> threads; | ||
int id = 0; | ||
for (int i = 0; i < n_threads; i++) { | ||
const int current_id = id++; | ||
if (current_id % 2 == 0) { | ||
threads.emplace_back([&] { // NOLINT | ||
for (int cnt = 0; cnt < n; ++cnt) { | ||
queue.push(0); | ||
} | ||
}); | ||
} else { | ||
threads.emplace_back([&] { // NOLINT | ||
for (int cnt = 0; cnt < n; ++cnt) { | ||
int _; | ||
queue.pop(_); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
for (auto& t : threads) { | ||
t.join(); | ||
} | ||
|
||
int k; | ||
// empty queue | ||
while (queue.pop(k)) { | ||
queue.pop(k); | ||
} | ||
// check that it still works | ||
ASSERT_TRUE(queue.push(0)); | ||
ASSERT_TRUE(queue.pop(k)); | ||
ASSERT_EQ(k, 0); | ||
// must be empty | ||
ASSERT_FALSE(queue.pop(k)); | ||
} | ||
|
||
int main(int argc, char** argv) { | ||
testing::InitGoogleTest(&argc, argv); | ||
return RUN_ALL_TESTS(); | ||
} |