Skip to content

Commit

Permalink
app: makes component-model-selector thread safe
Browse files Browse the repository at this point in the history
  • Loading branch information
quesnel committed Oct 21, 2024
1 parent 9e5735a commit 34164da
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 121 deletions.
59 changes: 37 additions & 22 deletions app/gui/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ bool application::init() noexcept
// Update the component selector in task.
add_gui_task([&]() noexcept { this->component_sel.update(); });


// @TODO at beggining, open a default generic component ?
// auto id = component_ed.add_generic_component();
// component_ed.open_as_main(id);
Expand Down Expand Up @@ -615,16 +614,14 @@ bool show_select_model_box(const char* button_label,
tree_node& tn,
grid_observer& access) noexcept
{
static grid_observer copy;
// static vector<component_id> selectable_components;

auto ret = false;

ImGui::BeginDisabled(app.component_model_sel.update_in_progress());
if (ImGui::Button(button_label)) {
debug::ensure(app.pj.tree_nodes.get_id(tn) == access.parent_id);
app.component_model_sel.select(
app.component_model_sel.start_update(
access.parent_id, access.compo_id, access.tn_id, access.mdl_id);
copy = access;

ImGui::OpenPopup(popup_label);
}

Expand All @@ -633,11 +630,15 @@ bool show_select_model_box(const char* button_label,
if (ImGui::BeginPopupModal(
popup_label, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {

app.component_model_sel.combobox("Select model to grid-observe",
access.parent_id,
access.compo_id,
access.tn_id,
access.mdl_id);
if (not app.component_model_sel.update_in_progress()) {
app.component_model_sel.combobox("Select model to observe grid",
access.parent_id,
access.compo_id,
access.tn_id,
access.mdl_id);
} else {
ImGui::Text("Computing observable children");
}

if (ImGui::Button("OK", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
Expand All @@ -647,12 +648,18 @@ bool show_select_model_box(const char* button_label,
ImGui::SetItemDefaultFocus();
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(120, 0))) {
access = copy;
const auto& old_access =
app.component_model_sel.get_update_access();
access.parent_id = old_access.parent_id;
access.compo_id = old_access.compo_id;
access.tn_id = old_access.tn_id;
access.mdl_id = old_access.mdl_id;
ImGui::CloseCurrentPopup();
}

ImGui::EndPopup();
}
ImGui::EndDisabled();

return ret;
}
Expand All @@ -663,15 +670,14 @@ bool show_select_model_box(const char* button_label,
tree_node& tn,
graph_observer& access) noexcept
{
static graph_observer copy;

auto ret = false;

ImGui::BeginDisabled(app.component_model_sel.update_in_progress());
if (ImGui::Button(button_label)) {
debug::ensure(app.pj.tree_nodes.get_id(tn) == access.parent_id);
app.component_model_sel.select(
app.component_model_sel.start_update(
access.parent_id, access.compo_id, access.tn_id, access.mdl_id);
copy = access;

ImGui::OpenPopup(popup_label);
}

Expand All @@ -680,11 +686,15 @@ bool show_select_model_box(const char* button_label,
if (ImGui::BeginPopupModal(
popup_label, nullptr, ImGuiWindowFlags_AlwaysAutoResize)) {

app.component_model_sel.combobox("Select model to graph-observe",
access.parent_id,
access.compo_id,
access.tn_id,
access.mdl_id);
if (not app.component_model_sel.update_in_progress()) {
app.component_model_sel.combobox("Select model to observe graph",
access.parent_id,
access.compo_id,
access.tn_id,
access.mdl_id);
} else {
ImGui::Text("Computing observable children");
}

if (ImGui::Button("OK", ImVec2(120, 0))) {
ImGui::CloseCurrentPopup();
Expand All @@ -694,7 +704,12 @@ bool show_select_model_box(const char* button_label,
ImGui::SetItemDefaultFocus();
ImGui::SameLine();
if (ImGui::Button("Cancel", ImVec2(120, 0))) {
access = copy;
const auto& old_access =
app.component_model_sel.get_update_access();
access.parent_id = old_access.parent_id;
access.compo_id = old_access.compo_id;
access.tn_id = old_access.tn_id;
access.mdl_id = old_access.mdl_id;
ImGui::CloseCurrentPopup();
}

Expand Down
62 changes: 40 additions & 22 deletions app/gui/application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
namespace irt {

template<class T, class M>
constexpr std::ptrdiff_t offset_of(const M T::*member)
constexpr std::ptrdiff_t offset_of(const M T::* member)
{
return reinterpret_cast<std::ptrdiff_t>(
&(reinterpret_cast<T*>(0)->*member));
Expand All @@ -46,14 +46,14 @@ constexpr std::ptrdiff_t offset_of(const M T::*member)
//! }
//! @endcode
template<class T, class M>
constexpr T& container_of(M* ptr, const M T::*member) noexcept
constexpr T& container_of(M* ptr, const M T::* member) noexcept
{
return *reinterpret_cast<T*>(reinterpret_cast<intptr_t>(ptr) -
offset_of(member));
}

template<class T, class M>
constexpr const T& container_of(const M* ptr, const M T::*member) noexcept
constexpr const T& container_of(const M* ptr, const M T::* member) noexcept
{
return *reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(ptr) -
offset_of(member));
Expand Down Expand Up @@ -946,49 +946,67 @@ class component_selector
class component_model_selector
{
public:
component_model_selector() noexcept = default;
struct access {
tree_node_id parent_id;
component_id compo_id;
tree_node_id tn_id;
model_id mdl_id;
};

/// If @c id is not equal to @c current_tree_node the clear and rebuild
/// vector and cache from the @c tree_node @c id.
void select(const tree_node_id parent_id) noexcept;
component_model_selector() noexcept = default;

/// If @c id is not equal to @c current_tree_node the clear and rebuild
/// vector and cache from the @c tree_node @c id. Component selected are
/// read from the @c g_obs.
void select(const tree_node_id parent_id,
const component_id compo_id,
const tree_node_id tn_id,
const model_id mdl_id) noexcept;
/** Get the parent, component, treenode and model identifiers store in
* the last call to the @c update function. */
const access& get_update_access() noexcept { return m_access; }

bool combobox(const char* label,
tree_node_id& parent_id,
component_id& compo_id,
tree_node_id& tn_id,
model_id& mdl_id) noexcept;
model_id& mdl_id) const noexcept;

/** A boolean to indicate that an update task is in progress. To be use to
* disable control to avoid double update. */
bool update_in_progress() const noexcept { return task_in_progress; }

void start_update(const tree_node_id parent_id,
const component_id compo_id,
const tree_node_id tn_id,
const model_id mdl_id) noexcept;

private:
// Used in the component ComboBox to select the grid element.
vector<std::pair<tree_node_id, component_id>> components;
vector<small_string<254>> names;

// A cache to proceed recursive search.
vector<tree_node*> stack_tree_nodes;
access m_access;

tree_node_id current_tree_node;
int component_selected = -1;
mutable int component_selected = -1;
bool task_in_progress = false;

/** Clean and rebuild the components and names vector to be used with the @c
* combobox function. */
void update(const tree_node_id parent_id,
const component_id compo_id,
const tree_node_id tn_id,
const model_id mdl_id) noexcept;

bool component_comboxbox(const char* label,
component_id& compo_id,
tree_node_id& tn_id) noexcept;
tree_node_id& tn_id) const noexcept;

bool observable_model_treenode(component_id& compo_id,
tree_node_id& tn_id,
model_id& mdl_id) noexcept;
model_id& mdl_id) const noexcept;

bool observable_model_treenode(tree_node& tn,
component_id& compo_id,
tree_node_id& tn_id,
model_id& mdl_id) noexcept;
model_id& mdl_id) const noexcept;

mutable std::shared_mutex m_mutex; /**< @c update() lock the class to read
modeling data and build the @c ids and @c names
vectors. Other functions try to lock. */
};

struct application {
Expand Down
Loading

0 comments on commit 34164da

Please sign in to comment.