From cb716f976b078dff72aa3a61f9435d45e4beb9f5 Mon Sep 17 00:00:00 2001 From: Tom Cherry Date: Tue, 11 Aug 2015 12:34:22 -0700 Subject: [PATCH] init: Queue Triggers instead of Actions When init queues a trigger, it actually enqueues all of the Actions that match with that given trigger. This works currently because all init scripts are loaded and therefore all Actions are available before init starts queueing any triggers. To support loading init scripts after init has started queueing triggers, this change enqueues Trigger objects instead of their matching Actions. Each Trigger object then matches its associated Actions during its execution. Additionally, this makes a few cosmetic clean ups related to triggers. Bug: 23186545 Change-Id: I5d177458e6df1c4b32b1072cf77e87ef952c87e4 --- init/action.cpp | 120 +++++++++++++++++++++++++++++++----------------- init/action.h | 13 ++++-- 2 files changed, 87 insertions(+), 46 deletions(-) diff --git a/init/action.cpp b/init/action.cpp index 2eb809ec0..dd366d3ae 100644 --- a/init/action.cpp +++ b/init/action.cpp @@ -154,7 +154,7 @@ bool Action::InitTriggers(const std::vector& args, std::string* err const static std::string prop_str("property:"); for (std::size_t i = 0; i < args.size(); ++i) { if (i % 2) { - if (args[i].compare("&&")) { + if (args[i] != "&&") { *err = "&& is the only symbol allowed to concatenate actions"; return false; } else { @@ -189,24 +189,24 @@ bool Action::InitSingleTrigger(const std::string& trigger) bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const { - bool found = !name.compare(""); + bool found = name.empty(); if (property_triggers_.empty()) { return true; } for (const auto& t : property_triggers_) { - if (!t.first.compare(name)) { - if (t.second.compare("*") && - t.second.compare(value)) { + const auto& trigger_name = t.first; + const auto& trigger_value = t.second; + if (trigger_name == name) { + if (trigger_value != "*" && trigger_value != value) { return false; } else { found = true; } } else { - std::string prop_val = property_get(t.first.c_str()); - if (prop_val.empty() || - (t.second.compare("*") && - t.second.compare(prop_val))) { + std::string prop_val = property_get(trigger_name.c_str()); + if (prop_val.empty() || (trigger_value != "*" && + trigger_value != prop_val)) { return false; } } @@ -217,7 +217,7 @@ bool Action::CheckPropertyTriggers(const std::string& name, bool Action::CheckEventTrigger(const std::string& trigger) const { return !event_trigger_.empty() && - !trigger.compare(event_trigger_) && + trigger == event_trigger_ && CheckPropertyTriggers(); } @@ -229,10 +229,8 @@ bool Action::CheckPropertyTrigger(const std::string& name, bool Action::TriggersEqual(const class Action& other) const { - return property_triggers_.size() == other.property_triggers_.size() && - std::equal(property_triggers_.begin(), property_triggers_.end(), - other.property_triggers_.begin()) && - !event_trigger_.compare(other.event_trigger_); + return property_triggers_ == other.property_triggers_ && + event_trigger_ == other.event_trigger_; } std::string Action::BuildTriggersString() const @@ -255,19 +253,53 @@ std::string Action::BuildTriggersString() const void Action::DumpState() const { - INFO("on "); std::string trigger_name = BuildTriggersString(); - INFO("%s", trigger_name.c_str()); - INFO("\n"); + INFO("on %s\n", trigger_name.c_str()); for (const auto& c : commands_) { std::string cmd_str = c->BuildCommandString(); - INFO(" %s", cmd_str.c_str()); + INFO(" %s\n", cmd_str.c_str()); } INFO("\n"); } -ActionManager::ActionManager() : cur_command_(0) + +class EventTrigger : public Trigger { +public: + EventTrigger(const std::string& trigger) : trigger_(trigger) { + } + bool CheckTriggers(const Action* action) override { + return action->CheckEventTrigger(trigger_); + } +private: + std::string trigger_; +}; + +class PropertyTrigger : public Trigger { +public: + PropertyTrigger(const std::string& name, const std::string& value) + : name_(name), value_(value) { + } + bool CheckTriggers(const Action* action) override { + return action->CheckPropertyTrigger(name_, value_); + } +private: + std::string name_; + std::string value_; +}; + +class BuiltinTrigger : public Trigger { +public: + BuiltinTrigger(Action* action) : action_(action) { + } + bool CheckTriggers(const Action* action) override { + return action == action_; + } +private: + Action* action_; +}; + +ActionManager::ActionManager() : current_command_(0) { } @@ -278,21 +310,13 @@ ActionManager& ActionManager::GetInstance() { void ActionManager::QueueEventTrigger(const std::string& trigger) { - for (const auto& a : action_list_) { - if (a->CheckEventTrigger(trigger)) { - action_queue_.push(a); - } - } + trigger_queue_.push(std::make_unique(trigger)); } void ActionManager::QueuePropertyTrigger(const std::string& name, const std::string& value) { - for (const auto& a : action_list_) { - if (a->CheckPropertyTrigger(name, value)) { - action_queue_.push(a); - } - } + trigger_queue_.push(std::make_unique(name, value)); } void ActionManager::QueueAllPropertyTriggers() @@ -312,35 +336,45 @@ void ActionManager::QueueBuiltinAction(int (*func)(const std::vectorAddCommand(func, name_vector); - action_queue_.push(act); + actions_.push_back(act); + trigger_queue_.push(std::make_unique(act)); } void ActionManager::ExecuteOneCommand() { - if (action_queue_.empty()) { + while (current_executing_actions_.empty() && !trigger_queue_.empty()) { + std::copy_if(actions_.begin(), actions_.end(), + std::back_inserter(current_executing_actions_), + [this] (Action* act) { + return trigger_queue_.front()->CheckTriggers(act); + }); + trigger_queue_.pop(); + } + + if (current_executing_actions_.empty()) { return; } - Action* action = action_queue_.front(); + Action* action = current_executing_actions_.back(); if (!action->NumCommands()) { - action_queue_.pop(); + current_executing_actions_.pop_back(); return; } - if (cur_command_ == 0) { + if (current_command_ == 0) { std::string trigger_name = action->BuildTriggersString(); INFO("processing action %p (%s)\n", action, trigger_name.c_str()); } - action->ExecuteOneCommand(cur_command_++); - if (cur_command_ == action->NumCommands()) { - cur_command_ = 0; - action_queue_.pop(); + action->ExecuteOneCommand(current_command_++); + if (current_command_ == action->NumCommands()) { + current_command_ = 0; + current_executing_actions_.pop_back(); } } bool ActionManager::HasMoreCommands() const { - return !action_queue_.empty(); + return !current_executing_actions_.empty() || !trigger_queue_.empty(); } Action* ActionManager::AddNewAction(const std::vector& triggers, @@ -357,21 +391,21 @@ Action* ActionManager::AddNewAction(const std::vector& triggers, } auto old_act_it = - std::find_if(action_list_.begin(), action_list_.end(), + std::find_if(actions_.begin(), actions_.end(), [&act] (Action* a) { return act->TriggersEqual(*a); }); - if (old_act_it != action_list_.end()) { + if (old_act_it != actions_.end()) { delete act; return *old_act_it; } - action_list_.push_back(act); + actions_.push_back(act); return act; } void ActionManager::DumpState() const { - for (const auto& a : action_list_) { + for (const auto& a : actions_) { a->DumpState(); } INFO("\n"); diff --git a/init/action.h b/init/action.h index ae28fe125..5088c710f 100644 --- a/init/action.h +++ b/init/action.h @@ -54,6 +54,12 @@ private: std::vector commands_; }; +class Trigger { +public: + virtual ~Trigger() { } + virtual bool CheckTriggers(const Action* action) = 0; +}; + class ActionManager { public: static ActionManager& GetInstance(); @@ -74,9 +80,10 @@ private: ActionManager(ActionManager const&) = delete; void operator=(ActionManager const&) = delete; - std::vector action_list_; - std::queue action_queue_; - std::size_t cur_command_; + std::vector actions_; + std::queue> trigger_queue_; + std::vector current_executing_actions_; + std::size_t current_command_; }; #endif