-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcatanMain.cpp
More file actions
132 lines (121 loc) · 5.5 KB
/
Copy pathcatanMain.cpp
File metadata and controls
132 lines (121 loc) · 5.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2026.
// Project : nioc
// Author : Anurag Jakhotia
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// A complete nioc application in one file. It creates the producers and consumers, connects them
// through a Port (nioc's message bus), and runs until you press Ctrl-C.
//
// clang-format off
// Producers Builders (consume -> produce)
// --------- -----------------------------
// hills -> brick road builder : brick, lumber -> road
// forest -> lumber settlement builder : road, brick, lumber, wool, grain -> settlement
// pasture -> wool city builder : settlement, ore, grain -> city
// fields -> grain dev-card builder : ore, wool, grain -> dev card
// mountains -> ore
// clang-format on
//
// Producers and consumers share only topic names. The bus delivers each published message to every
// subscriber, so e.g. every grain card reaches all three builders that consume grain. Each finished
// piece is printed by its builder.
//
////////////////////////////////////////////////////////////////////////////////////////////////////
#include <capnp/schema.h>
#include <chrono>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <nioc/common/utils.hpp>
#include <nioc/concurrent/threadedRunner.hpp>
#include <nioc/example/cityBuilder.hpp>
#include <nioc/example/config/catanConfig.capnp.h>
#include <nioc/example/developmentCardBuilder.hpp>
#include <nioc/example/fields.hpp>
#include <nioc/example/forest.hpp>
#include <nioc/example/hills.hpp>
#include <nioc/example/mountains.hpp>
#include <nioc/example/pasture.hpp>
#include <nioc/example/roadBuilder.hpp>
#include <nioc/example/settlementBuilder.hpp>
#include <nioc/logger/logger.hpp>
#include <nioc/terminus/defaultSignalCatcher.hpp>
#include <nioc/terminus/manifest.hpp>
#include <nioc/terminus/port.hpp>
#include <nioc/terminus/programOption.hpp>
#include <utility>
int main(const int argC, const char* const* const argV)
{
try
{
const auto programName = nioc::common::programName(argC, argV);
nioc::logger::setupDefaultLogger(programName);
auto options = nioc::terminus::programOptions(programName);
options.add(nioc::terminus::Manifest::cliOptions());
const auto variableMap = nioc::terminus::parseCommandLine(argC, argV, options);
// Decode the run's config against CatanConfig: schema defaults, then any --append-config file,
// then any --config-override entries.
auto manifest = nioc::terminus::Manifest{
variableMap,
capnp::Schema::from<nioc::example::CatanConfig>()};
// The Port owns the run. Its constructor calls this hook to build the routine graph, handing
// each routine only its own config block.
auto port = nioc::terminus::Port{
std::move(manifest),
[](nioc::terminus::Port& port,
nioc::terminus::Port::Drivers& drivers,
nioc::terminus::Port::Components& components,
nioc::terminus::Port::Runners& runners)
{
const auto config = port.config<nioc::example::CatanConfig>();
// Components (consumers).
components.push_back(
std::make_shared<nioc::example::RoadBuilder>(port, config.getRoadBuilder()));
components.push_back(
std::make_shared<nioc::example::SettlementBuilder>(
port,
config.getSettlementBuilder()));
components.push_back(
std::make_shared<nioc::example::CityBuilder>(port, config.getCityBuilder()));
components.push_back(
std::make_shared<nioc::example::DevelopmentCardBuilder>(
port,
config.getDevelopmentCardBuilder()));
// Drivers (producers).
drivers.push_back(std::make_shared<nioc::example::Hills>(port, config.getHills()));
drivers.push_back(std::make_shared<nioc::example::Forest>(port, config.getForest()));
drivers.push_back(std::make_shared<nioc::example::Pasture>(port, config.getPasture()));
drivers.push_back(std::make_shared<nioc::example::Fields>(port, config.getFields()));
drivers.push_back(
std::make_shared<nioc::example::Mountains>(port, config.getMountains()));
// Launch consumers before producers, so no message is published before its subscriber's
// runner is up. Each routine gets its own thread.
for(const auto& component: components)
{
auto runner = std::make_shared<nioc::concurrent::ThreadedRunner>();
runner->launch(component);
runners.push_back(std::move(runner));
}
for(const auto& driver: drivers)
{
auto runner = std::make_shared<nioc::concurrent::ThreadedRunner>();
runner->launch(driver);
runners.push_back(std::move(runner));
}
}};
const auto signalCatcher = nioc::terminus::defaultSignalCatcher(port);
// Park main in fixed beats until shutdown (Ctrl-C); teardown then happens in ~Port.
constexpr auto kPollPeriod = std::chrono::milliseconds{10};
while(port.wait(kPollPeriod, [] {}))
{
}
}
catch(const std::exception& error)
{
static_cast<void>(std::fputs("Encountered exception. Error: ", stderr));
static_cast<void>(std::fputs(error.what(), stderr));
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}