blob: 192cfa59fd3d685bb617c7e095cd52e67d2329d4 [file] [log] [blame]
/* Loosely-coupled notifications via the Publish-Subscribe pattern.
Copyright (C) 2025 Free Software Foundation, Inc.
Contributed by David Malcolm <dmalcolm@redhat.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#define INCLUDE_LIST
#define INCLUDE_STRING
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "pub-sub.h"
#if CHECKING_P
#include "selftest.h"
namespace selftest {
/* Selftests. */
// A topic for use in selftests
namespace snafu {
struct paper_jam {};
struct out_of_paper
{
int tray;
};
struct ink_low
{
std::string color;
};
struct subscriber
{
virtual void on_message (const paper_jam &m) = 0;
virtual void on_message (const out_of_paper &m) = 0;
virtual void on_message (const ink_low &m) = 0;
};
} // namespace snafu
static void
test_example ()
{
struct logger : public snafu::subscriber
{
void on_message (const snafu::paper_jam &) final override
{
m_log += "paper jam\n";
}
void on_message (const snafu::out_of_paper &m) final override
{
m_log += "out of paper (tray " + std::to_string (m.tray) + ")\n";
}
void on_message (const snafu::ink_low &m) final override
{
m_log += "ink low: " + m.color + "\n";
}
std::string m_log;
};
pub_sub::channel<snafu::subscriber> printer_a;
pub_sub::channel<snafu::subscriber> printer_b;
pub_sub::channel<snafu::subscriber> printer_c;
// No subscribers yet
ASSERT_EQ (printer_a.get_if_active (), nullptr);
ASSERT_EQ (printer_b.get_if_active (), nullptr);
ASSERT_EQ (printer_c.get_if_active (), nullptr);
// Subscribers to individual channels
logger log_a;
logger log_b;
logger log_c;
printer_a.add_subscriber (log_a);
printer_b.add_subscriber (log_b);
printer_c.add_subscriber (log_c);
// A subscriber to all channels
logger log_all;
printer_a.add_subscriber (log_all);
printer_b.add_subscriber (log_all);
printer_c.add_subscriber (log_all);
// The channels now have subscribers
ASSERT_EQ (printer_a.get_if_active (), &printer_a);
ASSERT_EQ (printer_b.get_if_active (), &printer_b);
ASSERT_EQ (printer_c.get_if_active (), &printer_c);
// Publish a message to each channel
printer_a.publish (snafu::paper_jam {});
printer_b.publish (snafu::out_of_paper {1});
printer_c.publish (snafu::ink_low {"cyan"});
// Verify that the subscribers got the messages they were meant to
ASSERT_EQ (log_a.m_log, "paper jam\n");
ASSERT_EQ (log_b.m_log, "out of paper (tray 1)\n");
ASSERT_EQ (log_c.m_log, "ink low: cyan\n");
ASSERT_EQ (log_all.m_log,
"paper jam\n"
"out of paper (tray 1)\n"
"ink low: cyan\n");
}
/* Run all of the selftests within this file. */
void
pub_sub_cc_tests ()
{
test_example ();
}
} // namespace selftest
#endif /* #if CHECKING_P */