Skip to content

Commit 2cb5124

Browse files
committed
Structure find_by_* calls to avoid raw loops
This set of changes is made as preparation for the addition of the Aviso attribute, and is expected to reduce the duplication of source code. Re ECFLOW-1931
1 parent b4f9b99 commit 2cb5124

File tree

7 files changed

+281
-288
lines changed

7 files changed

+281
-288
lines changed

ACore/src/ecflow/core/Stl.hpp

+43
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,49 @@ void AssoDeletePtrs(Container& pContainer) {
5757
std::for_each(pContainer.begin(), pContainer.end(), TAsoDeletor<typename Container::value_type>());
5858
pContainer.clear();
5959
}
60+
61+
namespace algorithm {
62+
63+
namespace detail {
64+
65+
template <typename T>
66+
struct is_shared_pointer : std::false_type
67+
{
68+
};
69+
70+
template <typename T>
71+
struct is_shared_pointer<std::shared_ptr<T>> : std::true_type
72+
{
73+
};
74+
75+
} // namespace detail
76+
77+
template <typename T>
78+
constexpr bool is_shared_pointer_v = detail::is_shared_pointer<T>::value;
79+
80+
template <typename C, typename Predicate>
81+
inline auto find_by(C& container, Predicate predicate) {
82+
return std::find_if(std::begin(container), std::end(container), predicate);
83+
}
84+
85+
template <typename C>
86+
inline auto find_by_name(C& container, std::string_view name) {
87+
// Important: special handling to seamlessly handle containers of std::shared_ptr.
88+
if constexpr (is_shared_pointer_v<typename C::value_type>) {
89+
return find_by(container, [&](const auto& item) { return item->name() == name; });
90+
}
91+
else {
92+
return find_by(container, [&](const auto& item) { return item.name() == name; });
93+
}
94+
}
95+
96+
template <typename C, typename I>
97+
inline auto find_by_number(C& container, I number) {
98+
return find_by(container, [&](const auto& item) { return item.number() == number; });
99+
}
100+
101+
} // namespace algorithm
102+
60103
} // namespace ecf
61104

62105
#endif /* ecflow_core_Stl_HPP */

ANode/src/ecflow/node/Jobs.cpp

+5-6
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,11 @@ bool Jobs::generate(JobsParam& jobsParam) const {
5454

5555
if (defs_) {
5656
if (defs_->server().get_state() == SState::RUNNING) {
57-
const std::vector<suite_ptr>& suiteVec = defs_->suiteVec();
58-
size_t theSize = suiteVec.size();
59-
for (size_t i = 0; i < theSize; i++) {
60-
// SuiteChanged moved internal to Suite::resolveDependencies. i.e on fast path
61-
// and when suites not begun we save a constructor/destructor calls
62-
(void)suiteVec[i]->resolveDependencies(jobsParam);
57+
const std::vector<suite_ptr>& suites = defs_->suiteVec();
58+
for (const suite_ptr& suite: suites) {
59+
// SuiteChanged moved into Suite::resolveDependencies.
60+
// This ensures the fast path and when suite are not begun we save a ctor/dtor call
61+
(void)suite->resolveDependencies(jobsParam);
6362
}
6463
}
6564
}

ANode/src/ecflow/node/Node.cpp

+21-17
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "ecflow/core/Log.hpp"
2121
#include "ecflow/core/PrintStyle.hpp"
2222
#include "ecflow/core/Serialization.hpp"
23+
#include "ecflow/core/Stl.hpp"
2324
#include "ecflow/core/Str.hpp"
2425
#include "ecflow/core/cereal_boost_time.hpp"
2526
#include "ecflow/node/AbstractObserver.hpp"
@@ -1045,11 +1046,9 @@ void Node::setStateOnly(NState::State newState,
10451046

10461047
// Record state changes for verification
10471048
if (misc_attrs_) {
1048-
size_t theSize = misc_attrs_->verifys_.size();
1049-
for (size_t i = 0; i < theSize; i++) {
1050-
if (misc_attrs_->verifys_[i].state() == newState) {
1051-
// cout << "Verify: calendar " << to_simple_string(calendar.date()) << "\n";
1052-
misc_attrs_->verifys_[i].incrementActual();
1049+
for (auto& verify : misc_attrs_->verifys_) {
1050+
if (verify.state() == newState) {
1051+
verify.incrementActual();
10531052
}
10541053
}
10551054
}
@@ -1092,22 +1091,27 @@ DState::State Node::dstate() const {
10921091
}
10931092

10941093
bool Node::set_event(const std::string& event_name_or_number) {
1095-
for (Event& e : events_) {
1096-
if (e.name_or_number() == event_name_or_number) {
1097-
e.set_value(true);
1098-
return true;
1099-
}
1094+
auto found = ecf::algorithm::find_by(
1095+
events_, [&](const auto& item) { return item.name_or_number() == event_name_or_number; });
1096+
1097+
if (found == std::end(events_)) {
1098+
return false;
11001099
}
1101-
return false;
1100+
1101+
found->set_value(true);
1102+
return true;
11021103
}
1104+
11031105
bool Node::clear_event(const std::string& event_name_or_number) {
1104-
for (Event& e : events_) {
1105-
if (e.name_or_number() == event_name_or_number) {
1106-
e.set_value(false);
1107-
return true;
1108-
}
1106+
auto found = ecf::algorithm::find_by(
1107+
events_, [&](const auto& item) { return item.name_or_number() == event_name_or_number; });
1108+
1109+
if (found == std::end(events_)) {
1110+
return false;
11091111
}
1110-
return false;
1112+
1113+
found->set_value(false);
1114+
return true;
11111115
}
11121116

11131117
void Node::setRepeatToLastValue() {

ANode/src/ecflow/node/NodeAdd.cpp

+12-11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "ecflow/attribute/LateAttr.hpp"
1616
#include "ecflow/core/Converter.hpp"
1717
#include "ecflow/core/Ecf.hpp"
18+
#include "ecflow/core/Stl.hpp"
1819
#include "ecflow/node/AutoRestoreAttr.hpp"
1920
#include "ecflow/node/Expression.hpp"
2021
#include "ecflow/node/Limit.hpp"
@@ -25,18 +26,18 @@ using namespace ecf;
2526
using namespace std;
2627

2728
bool Node::update_variable(const std::string& name, const std::string& value) {
28-
size_t theSize = vars_.size();
29-
for (size_t i = 0; i < theSize; i++) {
30-
if (vars_[i].name() == name) {
31-
// Variable already exist, *UPDATE* its value
32-
vars_[i].set_value(value);
33-
if (0 == Ecf::debug_level())
34-
std::cerr << "Node::addVariable: Variable of name '" << name << "' already exist for node "
35-
<< debugNodePath() << " updating with value '" << value << "'\n";
36-
return true;
37-
}
29+
auto found = ecf::algorithm::find_by_name(vars_, name);
30+
31+
if (found == std::end(vars_)) {
32+
return false;
33+
}
34+
35+
found->set_value(value);
36+
if (0 == Ecf::debug_level()) {
37+
std::cerr << "Node::addVariable: Variable of name '" << name << "' already exist for node " << debugNodePath()
38+
<< " updating with value '" << value << "'\n";
3839
}
39-
return false;
40+
return true;
4041
}
4142

4243
void Node::addVariable(const Variable& v) {

ANode/src/ecflow/node/NodeChange.cpp

+66-70
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "ecflow/attribute/LateAttr.hpp"
1414
#include "ecflow/core/Converter.hpp"
1515
#include "ecflow/core/Ecf.hpp"
16+
#include "ecflow/core/Stl.hpp"
1617
#include "ecflow/core/Str.hpp"
1718
#include "ecflow/node/ExprAst.hpp"
1819
#include "ecflow/node/Limit.hpp"
@@ -22,15 +23,14 @@ using namespace ecf;
2223
using namespace std;
2324

2425
void Node::changeVariable(const std::string& name, const std::string& value) {
25-
size_t theSize = vars_.size();
26-
for (size_t i = 0; i < theSize; i++) {
27-
if (vars_[i].name() == name) {
28-
vars_[i].set_value(value);
29-
variable_change_no_ = Ecf::incr_state_change_no();
30-
return;
31-
}
26+
auto found = ecf::algorithm::find_by_name(vars_, name);
27+
28+
if (found == std::end(vars_)) {
29+
throw std::runtime_error("Node::changeVariable: Could not find variable " + name);
3230
}
33-
throw std::runtime_error("Node::changeVariable: Could not find variable " + name);
31+
32+
found->set_value(value);
33+
variable_change_no_ = Ecf::incr_state_change_no();
3434
}
3535

3636
bool Node::set_event(const std::string& event_name_or_number, bool value) {
@@ -39,23 +39,22 @@ bool Node::set_event(const std::string& event_name_or_number, bool value) {
3939
}
4040

4141
// find by name first
42-
size_t theSize = events_.size();
43-
for (size_t i = 0; i < theSize; i++) {
44-
if (events_[i].name() == event_name_or_number) {
45-
events_[i].set_value(value);
42+
{
43+
auto found = ecf::algorithm::find_by_name(events_, event_name_or_number);
44+
if (found != std::end(events_)) {
45+
found->set_value(value);
4646
return true;
4747
}
4848
}
4949

5050
// Test for numeric, and then casting, is ****faster***** than relying on exception alone
5151
if (event_name_or_number.find_first_of(Str::NUMERIC()) == 0) {
5252
try {
53-
auto eventNumber = ecf::convert_to<int>(event_name_or_number);
54-
for (size_t i = 0; i < theSize; i++) {
55-
if (events_[i].number() == eventNumber) {
56-
events_[i].set_value(value);
57-
return true;
58-
}
53+
auto number = ecf::convert_to<int>(event_name_or_number);
54+
auto found = ecf::algorithm::find_by_number(events_, number);
55+
if (found != std::end(events_)) {
56+
found->set_value(value);
57+
return true;
5958
}
6059
}
6160
catch (const ecf::bad_conversion&) {
@@ -70,29 +69,28 @@ bool Node::set_event_used_in_trigger(const std::string& event_name_or_number) {
7069
}
7170

7271
// find by name first
73-
size_t theSize = events_.size();
74-
for (size_t i = 0; i < theSize; i++) {
75-
if (events_[i].name() == event_name_or_number) {
76-
events_[i].usedInTrigger(true);
72+
{
73+
auto found = ecf::algorithm::find_by_name(events_, event_name_or_number);
74+
if (found != std::end(events_)) {
75+
found->usedInTrigger(true);
7776
return true;
7877
}
7978
}
8079

8180
// Test for numeric, and then casting, is ****faster***** than relying on exception alone
8281
if (event_name_or_number.find_first_of(Str::NUMERIC()) == 0) {
8382
try {
84-
auto eventNumber = ecf::convert_to<int>(event_name_or_number);
85-
for (size_t i = 0; i < theSize; i++) {
86-
if (events_[i].number() == eventNumber) {
87-
events_[i].usedInTrigger(true);
88-
return true;
89-
;
90-
}
83+
auto number = ecf::convert_to<int>(event_name_or_number);
84+
auto found = ecf::algorithm::find_by_number(events_, number);
85+
if (found != std::end(events_)) {
86+
found->usedInTrigger(true);
87+
return true;
9188
}
9289
}
9390
catch (const ecf::bad_conversion&) {
9491
}
9592
}
93+
9694
return false;
9795
}
9896
void Node::changeEvent(const std::string& event_name_or_number, const std::string& setOrClear) {
@@ -116,25 +114,25 @@ void Node::changeEvent(const std::string& event_name_or_number, bool value) {
116114
throw std::runtime_error("Node::changeEvent: Could not find event " + event_name_or_number);
117115
}
118116

119-
bool Node::set_meter(const std::string& meter_name, int value) {
120-
size_t the_meter_size = meters_.size();
121-
for (size_t i = 0; i < the_meter_size; ++i) {
122-
if (meters_[i].name() == meter_name) {
123-
meters_[i].set_value(value);
124-
return true;
125-
}
117+
bool Node::set_meter(const std::string& name, int value) {
118+
auto found = ecf::algorithm::find_by_name(meters_, name);
119+
120+
if (found == std::end(meters_)) {
121+
return false;
126122
}
127-
return false;
123+
124+
found->set_value(value);
125+
return true;
128126
}
129-
bool Node::set_meter_used_in_trigger(const std::string& meter_name) {
130-
size_t the_meter_size = meters_.size();
131-
for (size_t i = 0; i < the_meter_size; ++i) {
132-
if (meters_[i].name() == meter_name) {
133-
meters_[i].usedInTrigger(true);
134-
return true;
135-
}
127+
bool Node::set_meter_used_in_trigger(const std::string& name) {
128+
auto found = ecf::algorithm::find_by_name(meters_, name);
129+
130+
if (found == std::end(meters_)) {
131+
return false;
136132
}
137-
return false;
133+
134+
found->usedInTrigger(true);
135+
return true;
138136
}
139137
void Node::changeMeter(const std::string& meter_name, const std::string& value) {
140138
int theValue = 0;
@@ -146,21 +144,21 @@ void Node::changeMeter(const std::string& meter_name, const std::string& value)
146144
}
147145
changeMeter(meter_name, theValue);
148146
}
147+
149148
void Node::changeMeter(const std::string& meter_name, int value) {
150149
if (set_meter(meter_name, value))
151150
return;
152151
throw std::runtime_error("Node::changeMeter: Could not find meter " + meter_name);
153152
}
154153

155154
void Node::changeLabel(const std::string& name, const std::string& value) {
156-
size_t theSize = labels_.size();
157-
for (size_t i = 0; i < theSize; i++) {
158-
if (labels_[i].name() == name) {
159-
labels_[i].set_new_value(value);
160-
return;
161-
}
155+
auto found = ecf::algorithm::find_by_name(labels_, name);
156+
157+
if (found == std::end(labels_)) {
158+
throw std::runtime_error("Node::changeLabel: Could not find label " + name);
162159
}
163-
throw std::runtime_error("Node::changeLabel: Could not find label " + name);
160+
161+
found->set_new_value(value);
164162
}
165163

166164
void Node::changeTrigger(const std::string& expression) {
@@ -241,30 +239,28 @@ void Node::change_time(const std::string& old, const std::string& new_time) {
241239
TimeAttr old_attr(TimeSeries::create(old)); // can throw if parse fails
242240
TimeAttr new_attr(TimeSeries::create(new_time)); // can throw if parse fails
243241

244-
size_t theSize = times_.size();
245-
for (size_t i = 0; i < theSize; i++) {
246-
// Dont use '==' since that compares additional state like free_
247-
if (times_[i].structureEquals(old_attr)) {
248-
times_[i] = new_attr;
249-
state_change_no_ = Ecf::incr_state_change_no();
250-
return;
251-
}
242+
// Don't use '==' since that compares additional state like free_
243+
auto found = ecf::algorithm::find_by(times_, [&](const auto& item) { return item.structureEquals(old_attr); });
244+
245+
if (found == std::end(times_)) {
246+
throw std::runtime_error("Node::change_time : Cannot find time attribute: ");
252247
}
253-
throw std::runtime_error("Node::change_time : Cannot find time attribute: ");
248+
249+
*found = new_attr;
250+
state_change_no_ = Ecf::incr_state_change_no();
254251
}
255252

256253
void Node::change_today(const std::string& old, const std::string& new_time) {
257254
TodayAttr old_attr(TimeSeries::create(old)); // can throw if parse fails
258255
TodayAttr new_attr(TimeSeries::create(new_time)); // can throw if parse fails
259256

260-
size_t theSize = todays_.size();
261-
for (size_t i = 0; i < theSize; i++) {
262-
// Dont use '==' since that compares additional state like free_
263-
if (todays_[i].structureEquals(old_attr)) {
264-
todays_[i] = new_attr;
265-
state_change_no_ = Ecf::incr_state_change_no();
266-
return;
267-
}
257+
// Don't use '==' since that compares additional state like free_
258+
auto found = ecf::algorithm::find_by(todays_, [&](const auto& item) { return item.structureEquals(old_attr); });
259+
260+
if (found == std::end(todays_)) {
261+
throw std::runtime_error("Node::change_today : Cannot find time attribute: ");
268262
}
269-
throw std::runtime_error("Node::change_today : Cannot find today attribute: ");
263+
264+
*found = new_attr;
265+
state_change_no_ = Ecf::incr_state_change_no();
270266
}

0 commit comments

Comments
 (0)