Skip to content

Examples #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jun 17, 2025
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,10 @@
"source=cache,target=/home/ubuntu/.cache,type=volume"
],
"workspaceFolder": "/workspace",
"runArgs": [
"--cap-add=SYS_PTRACE",
"--security-opt",
"seccomp=unconfined"
],
"remoteUser": "ubuntu"
}
3 changes: 2 additions & 1 deletion examples/.clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ InheritParentConfig: true

Checks: >
-cppcoreguidelines-avoid-magic-numbers,
-readability-magic-numbers
-readability-magic-numbers,
-fuchsia-default-arguments-calls
6 changes: 0 additions & 6 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ add_custom_target(examples)
add_custom_target(run_examples)

# Examples
add_example(example_basic basic.cpp)
run_example(example_basic)

add_example(example_close close.cpp)
run_example(example_close)

add_example(example_move move.cpp)
run_example(example_move)

Expand Down
21 changes: 0 additions & 21 deletions examples/basic.cpp

This file was deleted.

58 changes: 0 additions & 58 deletions examples/close.cpp

This file was deleted.

85 changes: 77 additions & 8 deletions examples/move.cpp
Original file line number Diff line number Diff line change
@@ -1,58 +1,127 @@
#include <msd/channel.hpp>

#include <cstddef>
#include <iostream>
#include <utility>
#include <vector>

class data final {
int value_{};

public:
static std::size_t copies_;
static std::size_t moves_;

data() = default;
explicit data(int value) : value_{value} {}

int get_value() const { return value_; }

data(const data& other) noexcept : value_{other.value_} { std::cout << "copy " << value_ << '\n'; }
data(const data& other) noexcept : value_{other.value_}
{
std::cout << "copy " << value_ << '\n';
++copies_;
}

data& operator=(const data& other)
{
if (this != &other) {
value_ = other.value_;
std::cout << "copy " << value_ << '\n';
++copies_;
}
std::cout << "copy " << value_ << '\n';

return *this;
}

data(data&& other) noexcept : value_{other.value_} { std::cout << "move " << value_ << '\n'; }
data(data&& other) noexcept : value_{other.value_}
{
std::cout << "move " << value_ << '\n';
++moves_;
}

data& operator=(data&& other) noexcept
{
if (this != &other) {
value_ = other.value_;
std::cout << "move " << value_ << '\n';
++moves_;
}

return *this;
}

~data() = default;
virtual ~data() = default;

private:
int value_{};
};

std::size_t data::copies_{};
std::size_t data::moves_{};

int main()
{
msd::channel<data> chan{10};

auto in1 = data{1};
// l-value: will be copied
const auto in1 = data{1};
chan << in1;

// r-value: will be moved
chan << data{2};

// l-value -> std::move -> r-value: will be moved
auto in3 = data{3};
chan << std::move(in3);

for (const auto& out : chan) {
std::vector<int> actual;

// Each value will be moved when read
for (const data& out : chan) {
std::cout << out.get_value() << '\n';

actual.push_back(out.get_value());

if (chan.empty()) {
break;
}
}

const std::vector<int> expected{
1,
2,
3,
};

if (actual != expected) {
std::cerr << "Error: got: ";
for (const int value : actual) {
std::cerr << value << ", ";
}

std::cerr << ", expected: ";
for (const int value : expected) {
std::cerr << value << ", ";
}
std::cerr << '\n';

std::terminate();
}

// 1 copy when in1 was written
constexpr std::size_t expected_copies = 1;

if (data::copies_ != expected_copies) {
std::cerr << "Error: copies: " << data::copies_ << ", expected: " << expected_copies << '\n';
std::terminate();
}

// 1 move when the second value was written
// 1 move when in3 was written
// 3 moves when the 3 values were read
constexpr std::size_t expected_moves = 5;

if (data::moves_ != expected_moves) {
std::cerr << "Error: moves: " << data::moves_ << ", expected: " << expected_moves << '\n';
std::terminate();
}
}
22 changes: 12 additions & 10 deletions examples/streaming.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <thread>
#include <vector>

// Spawns multiple producers that send strings into a channel, which are streamed to std::cout from a consumer.

int main()
{
using messages = msd::channel<std::string>;
Expand All @@ -15,7 +17,7 @@ int main()
messages channel{threads};

// Continuously get some data on multiple threads and send it all to a channel
const auto input = [](messages& chan, std::size_t thread, std::chrono::milliseconds pause) {
const auto produce = [](const std::size_t thread, const std::chrono::milliseconds pause, messages& chan) {
thread_local static std::size_t inc = 0U;

while (!chan.closed()) {
Expand All @@ -26,24 +28,24 @@ int main()
}
};

std::vector<std::future<void>> in_futures;
std::vector<std::future<void>> producers;
for (std::size_t i = 0U; i < threads; ++i) {
in_futures.push_back(std::async(input, std::ref(channel), i, std::chrono::milliseconds{500}));
producers.push_back(std::async(produce, i, std::chrono::milliseconds{500}, std::ref(channel)));
}

// Close the channel after some time
const auto timeout = [](messages& chan, std::chrono::milliseconds after) {
const auto close = [](const std::chrono::milliseconds after, messages& chan) {
std::this_thread::sleep_for(after);
chan.close();
};
const auto timeout_future = std::async(timeout, std::ref(channel), std::chrono::milliseconds{3000U});
const auto closer = std::async(close, std::chrono::milliseconds{3000U}, std::ref(channel));

// Stream incoming data to a destination
// Stream incoming messages
std::move(channel.begin(), channel.end(), std::ostream_iterator<std::string>(std::cout, "\n"));

// Wait for other threads
for (auto& future : in_futures) {
future.wait();
// Wait all tasks
for (auto& producer : producers) {
producer.wait();
}
timeout_future.wait();
closer.wait();
}