Skip to content

Commit

Permalink
[Jenkins] auto-formatting by clang-format version 10.0.0-4ubuntu1
Browse files Browse the repository at this point in the history
  • Loading branch information
stan-buildbot committed Mar 6, 2025
1 parent 71c5863 commit 89d756b
Show file tree
Hide file tree
Showing 2 changed files with 164 additions and 149 deletions.
254 changes: 129 additions & 125 deletions src/stan/callbacks/dispatcher.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,129 +11,133 @@
#include <utility>
#include <type_traits>


namespace stan {
namespace callbacks {

enum class InfoType {
CONFIG, // series of string messages
SAMPLE, // draw from posterior
METRIC, // struct with kv pairs 'metric_type', 'stepsize', 'inv_metric'
ALGORITHM_STATE, // sampler state for returned draw
};

struct InfoTypeHash {
std::size_t operator()(const InfoType& type) const {
return std::hash<int>()(static_cast<int>(type));
}
};

// Base type for type erasure.
class Channel {
public:
virtual ~Channel() {}
};

// Adapter for plain writers.
// These writer types (e.g., stream_writer, unique_stream_writer) support only a one-argument operator().
class WriterChannel : public Channel {
public:
explicit WriterChannel(stan::callbacks::writer* w) : writer_(w) {
if (!w)
throw std::runtime_error("Null writer pointer provided to WriterChannel");
}
// Single-argument dispatch: forwards to operator().
template <typename T>
void dispatch(const T& value) {
(*writer_)(value);
}
// Plain writers do not support key/value writes.
void begin_record() { }
void end_record() { }
private:
stan::callbacks::writer* writer_;
};

// Adapter for structured writers.
// The structured_writer interface provides a one-argument write(const std::string&)
// and a key/value write(const std::string&, const T&) overload.
class StructuredWriterChannel : public Channel {
public:
explicit StructuredWriterChannel(stan::callbacks::structured_writer* sw) : writer_(sw) {
if (!sw)
throw std::runtime_error("Null structured writer pointer provided to StructuredWriterChannel");
}
// Key dispatch
void dispatch(const std::string& key) {
writer_->write(key);
}
// Key/value dispatch
template <typename T>
void dispatch(const std::string& key, const T& value) {
writer_->write(key, std::forward<T>(value));
}
void begin_record() {
writer_->begin_record();
}
void end_record() {
writer_->end_record();
}
private:
stan::callbacks::structured_writer* writer_;
};

// dispatcher class with two overloads for dispatch().
class dispatcher {
public:
dispatcher() = default;
~dispatcher() = default;

void register_channel(InfoType type, std::unique_ptr<Channel> channel) {
channels_[type] = std::move(channel);
}

// Overload for non-string types: only forward to plain writer channels.
template <typename T,
typename = std::enable_if_t<!std::is_same<std::decay_t<T>, std::string>::value>>
void dispatch(InfoType type, T&& info) {
auto it = channels_.find(type);
if (it == channels_.end()) return; // silently do nothing
if (auto* wc = dynamic_cast<WriterChannel*>(it->second.get()))
wc->dispatch(std::forward<T>(info));
// We do not forward non-string types to structured writer channels.
}

// Overload for string types: forward to both plain and structured writer channels.
void dispatch(InfoType type, const std::string& info) {
auto it = channels_.find(type);
if (it == channels_.end()) return; // silently do nothing
if (auto* wc = dynamic_cast<WriterChannel*>(it->second.get()))
wc->dispatch(info);
if (auto* sw = dynamic_cast<StructuredWriterChannel*>(it->second.get()))
sw->dispatch(info);
}

// Forward a begin_record call.
void begin_record(InfoType type) {
auto it = channels_.find(type);
if (it == channels_.end()) return;
if (auto* sw = dynamic_cast<StructuredWriterChannel*>(it->second.get()))
sw->begin_record();
}

// Forward an end_record call.
void end_record(InfoType type) {
auto it = channels_.find(type);
if (it == channels_.end()) return;
if (auto* sw = dynamic_cast<StructuredWriterChannel*>(it->second.get()))
sw->end_record();
}

protected:
std::unordered_map<InfoType, std::unique_ptr<Channel>, InfoTypeHash> channels_;
};

} // namespace callbacks
} // namespace stan

#endif // STAN_CALLBACKS_DISPATCHER_HPP
namespace callbacks {

enum class InfoType {
CONFIG, // series of string messages
SAMPLE, // draw from posterior
METRIC, // struct with kv pairs 'metric_type', 'stepsize', 'inv_metric'
ALGORITHM_STATE, // sampler state for returned draw
};

struct InfoTypeHash {
std::size_t operator()(const InfoType& type) const {
return std::hash<int>()(static_cast<int>(type));
}
};

// Base type for type erasure.
class Channel {
public:
virtual ~Channel() {}
};

// Adapter for plain writers.
// These writer types (e.g., stream_writer, unique_stream_writer) support only a
// one-argument operator().
class WriterChannel : public Channel {
public:
explicit WriterChannel(stan::callbacks::writer* w) : writer_(w) {
if (!w)
throw std::runtime_error("Null writer pointer provided to WriterChannel");
}
// Single-argument dispatch: forwards to operator().
template <typename T>
void dispatch(const T& value) {
(*writer_)(value);
}
// Plain writers do not support key/value writes.
void begin_record() {}
void end_record() {}

private:
stan::callbacks::writer* writer_;
};

// Adapter for structured writers.
// The structured_writer interface provides a one-argument write(const
// std::string&) and a key/value write(const std::string&, const T&) overload.
class StructuredWriterChannel : public Channel {
public:
explicit StructuredWriterChannel(stan::callbacks::structured_writer* sw)
: writer_(sw) {
if (!sw)
throw std::runtime_error(
"Null structured writer pointer provided to StructuredWriterChannel");
}
// Key dispatch
void dispatch(const std::string& key) { writer_->write(key); }
// Key/value dispatch
template <typename T>
void dispatch(const std::string& key, const T& value) {
writer_->write(key, std::forward<T>(value));
}
void begin_record() { writer_->begin_record(); }
void end_record() { writer_->end_record(); }

private:
stan::callbacks::structured_writer* writer_;
};

// dispatcher class with two overloads for dispatch().
class dispatcher {
public:
dispatcher() = default;
~dispatcher() = default;

void register_channel(InfoType type, std::unique_ptr<Channel> channel) {
channels_[type] = std::move(channel);
}

// Overload for non-string types: only forward to plain writer channels.
template <typename T, typename = std::enable_if_t<
!std::is_same<std::decay_t<T>, std::string>::value>>
void dispatch(InfoType type, T&& info) {
auto it = channels_.find(type);
if (it == channels_.end())
return; // silently do nothing
if (auto* wc = dynamic_cast<WriterChannel*>(it->second.get()))
wc->dispatch(std::forward<T>(info));
// We do not forward non-string types to structured writer channels.
}

// Overload for string types: forward to both plain and structured writer
// channels.
void dispatch(InfoType type, const std::string& info) {
auto it = channels_.find(type);
if (it == channels_.end())
return; // silently do nothing
if (auto* wc = dynamic_cast<WriterChannel*>(it->second.get()))
wc->dispatch(info);
if (auto* sw = dynamic_cast<StructuredWriterChannel*>(it->second.get()))
sw->dispatch(info);
}

// Forward a begin_record call.
void begin_record(InfoType type) {
auto it = channels_.find(type);
if (it == channels_.end())
return;
if (auto* sw = dynamic_cast<StructuredWriterChannel*>(it->second.get()))
sw->begin_record();
}

// Forward an end_record call.
void end_record(InfoType type) {
auto it = channels_.find(type);
if (it == channels_.end())
return;
if (auto* sw = dynamic_cast<StructuredWriterChannel*>(it->second.get()))
sw->end_record();
}

protected:
std::unordered_map<InfoType, std::unique_ptr<Channel>, InfoTypeHash>
channels_;
};

} // namespace callbacks
} // namespace stan

#endif // STAN_CALLBACKS_DISPATCHER_HPP
59 changes: 35 additions & 24 deletions src/test/unit/callbacks/dispatcher_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
#include <iostream>

// For this test we assume that InfoType has at least these values:
using stan::callbacks::InfoType;
using stan::callbacks::dispatcher;
using stan::callbacks::InfoType;

struct deleter_noop {
template <typename T>
Expand All @@ -20,14 +20,15 @@ struct deleter_noop {

class DispatcherTest : public ::testing::Test {
public:
DispatcherTest() :
ss_sample(),
ss_config(),
ss_metric(),
writer_sample(ss_sample),
writer_config(ss_config),
writer_metric(std::unique_ptr<std::stringstream, deleter_noop>(&ss_metric)),
dispatcher() {}
DispatcherTest()
: ss_sample(),
ss_config(),
ss_metric(),
writer_sample(ss_sample),
writer_config(ss_config),
writer_metric(
std::unique_ptr<std::stringstream, deleter_noop>(&ss_metric)),
dispatcher() {}

void SetUp() {
ss_sample.str(std::string());
Expand All @@ -37,14 +38,20 @@ class DispatcherTest : public ::testing::Test {
ss_metric.str(std::string());
ss_metric.clear();

dispatcher.register_channel(InfoType::CONFIG,
std::unique_ptr<stan::callbacks::Channel>(new stan::callbacks::WriterChannel(&writer_config)));
dispatcher.register_channel(
InfoType::CONFIG,
std::unique_ptr<stan::callbacks::Channel>(
new stan::callbacks::WriterChannel(&writer_config)));

dispatcher.register_channel(InfoType::SAMPLE,
std::unique_ptr<stan::callbacks::Channel>(new stan::callbacks::WriterChannel(&writer_sample)));
dispatcher.register_channel(
InfoType::SAMPLE,
std::unique_ptr<stan::callbacks::Channel>(
new stan::callbacks::WriterChannel(&writer_sample)));

dispatcher.register_channel(InfoType::METRIC,
std::unique_ptr<stan::callbacks::Channel>(new stan::callbacks::StructuredWriterChannel(&writer_metric)));
dispatcher.register_channel(
InfoType::METRIC,
std::unique_ptr<stan::callbacks::Channel>(
new stan::callbacks::StructuredWriterChannel(&writer_metric)));
}

void TearDown() {}
Expand Down Expand Up @@ -78,21 +85,25 @@ TEST_F(DispatcherTest, SamplePlainVector) {
}

TEST_F(DispatcherTest, MetricStructuredKeyValueRecord) {
// For METRIC (structured writer), open a record, dispatch key/value pairs, then close the record.
// For METRIC (structured writer), open a record, dispatch key/value pairs,
// then close the record.
dispatcher.begin_record(InfoType::METRIC);
dispatcher.dispatch(InfoType::METRIC, "metric_type", std::string("diag"));
dispatcher.dispatch(InfoType::METRIC, "stepsize", 0.6789);
// For the inv_metric, assume the caller converts the vector to a comma-separated string.
// For the inv_metric, assume the caller converts the vector to a
// comma-separated string.
std::vector<double> inv_metric = {0.1, 0.2, 0.3};
std::string inv_metric_str;
for (size_t i = 0; i < inv_metric.size(); ++i) {
inv_metric_str += std::to_string(inv_metric[i]);
if(i != inv_metric.size() - 1) inv_metric_str += ",";
if (i != inv_metric.size() - 1)
inv_metric_str += ",";
}
dispatcher.dispatch(InfoType::METRIC, "inv_metric", inv_metric_str);
dispatcher.end_record(InfoType::METRIC);
// Expected output:
// Begin record marker, followed by key/value pairs each formatted as "key:value;" and then end record marker.
// Begin record marker, followed by key/value pairs each formatted as
// "key:value;" and then end record marker.
std::cout << ss_metric.str() << std::endl;
}

Expand All @@ -104,14 +115,14 @@ TEST_F(DispatcherTest, MetricStructuredKeyValueRecord) {
// }

// TEST_F(DispatcherTest, NonStringDispatchToStructuredIgnored) {
// // Dispatch a non-string (e.g., an int) to a structured writer (METRIC) should be ignored.
// dispatcher.dispatch(InfoType::METRIC, 123);
// // Dispatch a non-string (e.g., an int) to a structured writer (METRIC)
// should be ignored. dispatcher.dispatch(InfoType::METRIC, 123);
// EXPECT_EQ(structuredWriter.output, "");
// }

// TEST_F(DispatcherTest, UnregisteredInfoType) {
// // Dispatch to an unregistered InfoType (e.g., ALGORITHM_STATE) produces no output.
// dispatcher.dispatch(InfoType::ALGORITHM_STATE, std::string("NoOutput"));
// EXPECT_EQ(plainWriter.output, "");
// // Dispatch to an unregistered InfoType (e.g., ALGORITHM_STATE) produces no
// output. dispatcher.dispatch(InfoType::ALGORITHM_STATE,
// std::string("NoOutput")); EXPECT_EQ(plainWriter.output, "");
// EXPECT_EQ(structuredWriter.output, "");
// }

0 comments on commit 89d756b

Please sign in to comment.