Skip to content

Commit 9d69668

Browse files
psalzPeterTh
authored andcommitted
Add new as<> wrapper around static_cast for use with isa<>
Mainly to silence clang-tidy warnings. Move isa<> to utils header.
1 parent b403f85 commit 9d69668

File tree

9 files changed

+43
-38
lines changed

9 files changed

+43
-38
lines changed

include/command.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,6 @@ namespace detail {
1919
// ------------------------------------------------ COMMAND GRAPH -------------------------------------------------
2020
// ----------------------------------------------------------------------------------------------------------------
2121

22-
// TODO: Consider using LLVM-style RTTI for better performance
23-
template <typename T, typename P>
24-
bool isa(P* p) {
25-
return dynamic_cast<T*>(const_cast<std::remove_const_t<P>*>(p)) != nullptr;
26-
}
27-
2822
// TODO: Consider adding a mechanism (during debug builds?) to assert that dependencies can only exist between commands on the same node
2923
class abstract_command : public intrusive_graph_node<abstract_command> {
3024
friend class command_graph;

include/command_graph.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,13 @@ namespace detail {
140140
m_execution_front.erase(dependee);
141141

142142
// Sanity check: For non-dataflow dependencies the commands can only be of specific types
143-
if(origin == dependency_origin::execution_front) { assert(isa<epoch_command>(depender) || isa<horizon_command>(depender)); }
143+
if(origin == dependency_origin::execution_front) { assert(utils::isa<epoch_command>(depender) || utils::isa<horizon_command>(depender)); }
144144
if(origin == dependency_origin::collective_group_serialization) {
145-
assert(isa<execution_command>(depender));
145+
assert(utils::isa<execution_command>(depender));
146146
// The original execution command may have been subsumed by a horizon / epoch
147-
assert(isa<execution_command>(dependee) || isa<epoch_command>(dependee) || isa<horizon_command>(dependee));
147+
assert(utils::isa<execution_command>(dependee) || utils::isa<epoch_command>(dependee) || utils::isa<horizon_command>(dependee));
148148
}
149-
if(origin == dependency_origin::last_epoch) { assert(isa<epoch_command>(dependee) || isa<horizon_command>(dependee)); }
149+
if(origin == dependency_origin::last_epoch) { assert(utils::isa<epoch_command>(dependee) || utils::isa<horizon_command>(dependee)); }
150150

151151
// Sanity check for unit tests, where we may have multiple CDAGS
152152
assert(m_commands.at(depender->get_cid()).get() == depender);

include/utils.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,17 @@
77

88
namespace celerity::detail::utils {
99

10+
template <typename T, typename P>
11+
bool isa(const P* p) {
12+
return dynamic_cast<const T*>(p) != nullptr;
13+
}
14+
15+
template <typename T, typename P>
16+
auto as(P* p) {
17+
assert(isa<T>(p));
18+
return static_cast<std::conditional_t<std::is_const_v<P>, const T*, T*>>(p);
19+
}
20+
1021
template <typename BitMaskT>
1122
constexpr inline uint32_t popcount(const BitMaskT bit_mask) noexcept {
1223
static_assert(std::is_integral_v<BitMaskT> && std::is_unsigned_v<BitMaskT>, "popcount argument needs to be an unsigned integer type.");

src/distributed_graph_generator.cc

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ void distributed_graph_generator::generate_distributed_commands(const task& tsk)
220220
// we have to include it in exactly one of the per-node intermediate reductions.
221221
for(const auto& reduction : tsk.get_reductions()) {
222222
if(nid == reduction_initializer_nid && reduction.init_from_buffer) {
223-
static_cast<execution_command*>(cmd)->set_is_reduction_initializer(true);
223+
utils::as<execution_command>(cmd)->set_is_reduction_initializer(true);
224224
break;
225225
}
226226
}
@@ -313,7 +313,7 @@ void distributed_graph_generator::generate_distributed_commands(const task& tsk)
313313
// possibly even multiple for partially already-replicated data.
314314
// TODO: Can and/or should we consolidate?
315315
auto* const push_cmd = create_command<push_command>(bid, 0, nid, trid, grid_box_to_subrange(replicated_box));
316-
assert(!isa<await_push_command>(m_cdag.get(wcs)) && "Attempting to push non-owned data?!");
316+
assert(!utils::isa<await_push_command>(m_cdag.get(wcs)) && "Attempting to push non-owned data?!");
317317
m_cdag.add_dependency(push_cmd, m_cdag.get(wcs), dependency_kind::true_dep, dependency_origin::dataflow);
318318
generated_pushes.push_back(push_cmd);
319319

@@ -450,13 +450,13 @@ void distributed_graph_generator::generate_distributed_commands(const task& tsk)
450450
assert(writer_cmd != nullptr);
451451

452452
// We're only interested in writes that happen within the same task as the push
453-
if(isa<task_command>(writer_cmd) && static_cast<task_command*>(writer_cmd)->get_tid() == tsk.get_id()) {
453+
if(utils::isa<task_command>(writer_cmd) && utils::as<task_command>(writer_cmd)->get_tid() == tsk.get_id()) {
454454
// In certain situations the push might have a true dependency on the last writer,
455455
// in that case don't add an anti-dependency (as that would cause a cycle).
456456
// TODO: Is this still possible? We don't have a unit test exercising this branch...
457457
if(push_cmd->has_dependency(writer_cmd, dependency_kind::true_dep)) {
458458
// This can currently only happen for await_push commands.
459-
assert(isa<await_push_command>(writer_cmd));
459+
assert(utils::isa<await_push_command>(writer_cmd));
460460
continue;
461461
}
462462
m_cdag.add_dependency(writer_cmd, push_cmd, dependency_kind::anti_dep, dependency_origin::dataflow);
@@ -495,7 +495,7 @@ void distributed_graph_generator::generate_anti_dependencies(
495495
const auto last_writers = last_writers_map.get_region_values(write_req);
496496
for(const auto& [box, wcs] : last_writers) {
497497
auto* const last_writer_cmd = m_cdag.get(static_cast<command_id>(wcs));
498-
assert(!isa<task_command>(last_writer_cmd) || static_cast<task_command*>(last_writer_cmd)->get_tid() != tid);
498+
assert(!utils::isa<task_command>(last_writer_cmd) || utils::as<task_command>(last_writer_cmd)->get_tid() != tid);
499499

500500
// Add anti-dependencies onto all successors of the writer
501501
bool has_successors = false;
@@ -506,7 +506,7 @@ void distributed_graph_generator::generate_anti_dependencies(
506506
auto* const cmd = d.node;
507507

508508
// We might have already generated new commands within the same task that also depend on this; in that case, skip it
509-
if(isa<task_command>(cmd) && static_cast<task_command*>(cmd)->get_tid() == tid) continue;
509+
if(utils::isa<task_command>(cmd) && utils::as<task_command>(cmd)->get_tid() == tid) continue;
510510

511511
// So far we don't know whether the dependent actually intersects with the subrange we're writing
512512
if(const auto command_reads_it = m_command_buffer_reads.find(cmd->get_cid()); command_reads_it != m_command_buffer_reads.end()) {
@@ -549,7 +549,7 @@ void distributed_graph_generator::process_task_side_effect_requirements(const ta
549549

550550
void distributed_graph_generator::set_epoch_for_new_commands(const abstract_command* const epoch_or_horizon) {
551551
// both an explicit epoch command and an applied horizon can be effective epochs
552-
assert(isa<epoch_command>(epoch_or_horizon) || isa<horizon_command>(epoch_or_horizon));
552+
assert(utils::isa<epoch_command>(epoch_or_horizon) || utils::isa<horizon_command>(epoch_or_horizon));
553553

554554
for(auto& [bid, bs] : m_buffer_states) {
555555
bs.local_last_writer.apply_to_values([epoch_or_horizon](const write_command_state& wcs) {

src/executor.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ namespace detail {
8686
if(m_jobs[d].unsatisfied_dependencies == 0) { ready_jobs.push_back(d); }
8787
}
8888

89-
if(isa<device_execute_job>(job_handle.job.get())) {
89+
if(utils::isa<device_execute_job>(job_handle.job.get())) {
9090
m_running_device_compute_jobs--;
9191
} else if(const auto epoch = dynamic_cast<epoch_job*>(job_handle.job.get()); epoch && epoch->get_epoch_action() == epoch_action::shutdown) {
9292
assert(m_command_queue.empty());
@@ -106,7 +106,7 @@ namespace detail {
106106
auto* job = m_jobs.at(cid).job.get();
107107
job->start();
108108
job->update();
109-
if(isa<device_execute_job>(job)) { m_running_device_compute_jobs++; }
109+
if(utils::isa<device_execute_job>(job)) { m_running_device_compute_jobs++; }
110110
}
111111
}
112112

src/graph_serializer.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ namespace detail {
2727
task_cmds.reserve(cmds.size() / 2); // Somewhat overzealous, we are likely to have more push commands
2828

2929
for(const auto& cmd : cmds) {
30-
if(isa<push_command>(cmd)) {
30+
if(utils::isa<push_command>(cmd)) {
3131
push_cmds.push_back(cmd);
32-
} else if(isa<task_command>(cmd)) {
32+
} else if(utils::isa<task_command>(cmd)) {
3333
task_cmds.push_back(cmd);
3434
}
3535
}
@@ -40,10 +40,10 @@ namespace detail {
4040
const auto flush_recursive = [this, &check_tid, &flush_count](abstract_command* cmd, auto recurse) -> void {
4141
(void)check_tid;
4242
#if defined(CELERITY_DETAIL_ENABLE_DEBUG)
43-
if(isa<task_command>(cmd)) {
43+
if(utils::isa<task_command>(cmd)) {
4444
// Verify that all commands belong to the same task
45-
assert(check_tid == task_id(-1) || check_tid == static_cast<task_command*>(cmd)->get_tid());
46-
check_tid = static_cast<task_command*>(cmd)->get_tid();
45+
assert(check_tid == task_id(-1) || check_tid == utils::as<task_command>(cmd)->get_tid());
46+
check_tid = utils::as<task_command>(cmd)->get_tid();
4747
}
4848
#endif
4949
std::vector<command_id> deps;

src/print_graph.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ namespace detail {
170170
const auto id = local_to_global_id(cmd.get_cid());
171171
const auto label = get_command_label(local_nid, cmd, tm, bm);
172172
const auto* const fontcolor = colors[local_nid % (sizeof(colors) / sizeof(char*))];
173-
const auto* const shape = isa<task_command>(&cmd) ? "box" : "ellipse";
173+
const auto* const shape = utils::isa<task_command>(&cmd) ? "box" : "ellipse";
174174
return fmt::format("{}[label=<{}> fontcolor={} shape={}];", id, label, fontcolor, shape);
175175
};
176176

test/distributed_graph_generator_test_utils.h

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -157,8 +157,8 @@ class command_query {
157157
if(node_filter.has_value() && *node_filter != nid) continue;
158158
for(const auto* cmd : m_commands_by_node[nid]) {
159159
if(task_filter.has_value()) {
160-
if(!isa<task_command>(cmd)) continue;
161-
if(static_cast<const task_command*>(cmd)->get_tid() != *task_filter) continue;
160+
if(!utils::isa<task_command>(cmd)) continue;
161+
if(utils::as<task_command>(cmd)->get_tid() != *task_filter) continue;
162162
}
163163
if(type_filter.has_value()) {
164164
if(get_type(cmd) != *type_filter) continue;
@@ -345,13 +345,13 @@ class command_query {
345345
}
346346

347347
static command_type get_type(const abstract_command* cmd) {
348-
if(isa<epoch_command>(cmd)) return command_type::epoch;
349-
if(isa<horizon_command>(cmd)) return command_type::horizon;
350-
if(isa<execution_command>(cmd)) return command_type::execution;
351-
if(isa<push_command>(cmd)) return command_type::push;
352-
if(isa<await_push_command>(cmd)) return command_type::await_push;
353-
if(isa<reduction_command>(cmd)) return command_type::reduction;
354-
if(isa<fence_command>(cmd)) return command_type::fence;
348+
if(utils::isa<epoch_command>(cmd)) return command_type::epoch;
349+
if(utils::isa<horizon_command>(cmd)) return command_type::horizon;
350+
if(utils::isa<execution_command>(cmd)) return command_type::execution;
351+
if(utils::isa<push_command>(cmd)) return command_type::push;
352+
if(utils::isa<await_push_command>(cmd)) return command_type::await_push;
353+
if(utils::isa<reduction_command>(cmd)) return command_type::reduction;
354+
if(utils::isa<fence_command>(cmd)) return command_type::fence;
355355
throw query_exception("Unknown command type");
356356
}
357357

test/graph_generation_tests.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,13 @@ TEST_CASE("command_graph keeps track of execution front", "[command_graph][comma
6161
TEST_CASE("isa<> RTTI helper correctly handles command hierarchies", "[rtti][command-graph]") {
6262
command_graph cdag;
6363
auto* const np = cdag.create<epoch_command>(task_manager::initial_epoch_task, epoch_action::none);
64-
REQUIRE(isa<abstract_command>(np));
64+
REQUIRE(utils::isa<abstract_command>(np));
6565
auto* const hec = cdag.create<execution_command>(0, subrange<3>{});
66-
REQUIRE(isa<execution_command>(hec));
66+
REQUIRE(utils::isa<execution_command>(hec));
6767
auto* const pc = cdag.create<push_command>(0, 0, 0, 0, subrange<3>{});
68-
REQUIRE(isa<abstract_command>(pc));
68+
REQUIRE(utils::isa<abstract_command>(pc));
6969
auto* const apc = cdag.create<await_push_command>(0, 0, 0, GridRegion<3>{});
70-
REQUIRE(isa<abstract_command>(apc));
70+
REQUIRE(utils::isa<abstract_command>(apc));
7171
}
7272

7373
TEST_CASE("distributed_graph_generator generates dependencies for execution commands", "[distributed_graph_generator][command-graph]") {

0 commit comments

Comments
 (0)