Loading init/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ include $(CLEAR_VARS) LOCAL_CPPFLAGS := $(init_cflags) LOCAL_SRC_FILES:= \ action.cpp \ import_parser.cpp \ init_parser.cpp \ log.cpp \ parser.cpp \ Loading init/action.cpp +151 −135 Original line number Diff line number Diff line Loading @@ -21,46 +21,27 @@ #include <base/strings.h> #include <base/stringprintf.h> #include "builtins.h" #include "error.h" #include "init_parser.h" #include "log.h" #include "property_service.h" #include "util.h" class Action::Command { public: Command(int (*f)(const std::vector<std::string>& args), const std::vector<std::string>& args, const std::string& filename, int line); int InvokeFunc() const; std::string BuildCommandString() const; std::string BuildSourceString() const; private: int (*func_)(const std::vector<std::string>& args); const std::vector<std::string> args_; const std::string filename_; int line_; }; using android::base::Join; using android::base::StringPrintf; Action::Command::Command(int (*f)(const std::vector<std::string>& args), const std::vector<std::string>& args, const std::string& filename, int line) : func_(f), args_(args), filename_(filename), line_(line) { Command::Command(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line) : func_(f), args_(args), filename_(filename), line_(line) { } int Action::Command::InvokeFunc() const { int Command::InvokeFunc() const { std::vector<std::string> expanded_args; expanded_args.resize(args_.size()); expanded_args[0] = args_[0]; for (std::size_t i = 1; i < args_.size(); ++i) { if (expand_props(args_[i], &expanded_args[i]) == -1) { if (!expand_props(args_[i], &expanded_args[i])) { ERROR("%s: cannot expand '%s'\n", args_[0].c_str(), args_[i].c_str()); return -EINVAL; } Loading @@ -69,51 +50,71 @@ int Action::Command::InvokeFunc() const return func_(expanded_args); } std::string Action::Command::BuildCommandString() const { return android::base::Join(args_, ' '); std::string Command::BuildCommandString() const { return Join(args_, ' '); } std::string Action::Command::BuildSourceString() const { std::string Command::BuildSourceString() const { if (!filename_.empty()) { return android::base::StringPrintf(" (%s:%d)", filename_.c_str(), line_); return StringPrintf(" (%s:%d)", filename_.c_str(), line_); } else { return std::string(); } } Action::Action() { Action::Action(bool oneshot) : oneshot_(oneshot) { } const KeywordMap<BuiltinFunction>* Action::function_map_ = nullptr; bool Action::AddCommand(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) { if (!function_map_) { *err = "no function map available"; return false; } if (args.empty()) { *err = "command needed, but not provided"; return false; } void Action::AddCommand(int (*f)(const std::vector<std::string>& args), auto function = function_map_->FindFunction(args[0], args.size() - 1, err); if (!function) { return false; } AddCommand(function, args, filename, line); return true; } void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line) { Action::Command* cmd = new Action::Command(f, args, filename, line); commands_.push_back(cmd); const std::string& filename, int line) { commands_.emplace_back(f, args, filename, line); } std::size_t Action::NumCommands() const { void Action::CombineAction(const Action& action) { for (const auto& c : action.commands_) { commands_.emplace_back(c); } } std::size_t Action::NumCommands() const { return commands_.size(); } void Action::ExecuteOneCommand(std::size_t command) const { ExecuteCommand(*commands_[command]); void Action::ExecuteOneCommand(std::size_t command) const { ExecuteCommand(commands_[command]); } void Action::ExecuteAllCommands() const { void Action::ExecuteAllCommands() const { for (const auto& c : commands_) { ExecuteCommand(*c); ExecuteCommand(c); } } void Action::ExecuteCommand(const Command& command) const { void Action::ExecuteCommand(const Command& command) const { Timer t; int result = command.InvokeFunc(); Loading @@ -128,8 +129,7 @@ void Action::ExecuteCommand(const Command& command) const } } bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) { bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) { const static std::string prop_str("property:"); std::string prop_name(trigger.substr(prop_str.length())); size_t equal_pos = prop_name.find('='); Loading @@ -149,8 +149,7 @@ bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) return true; } bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err) { bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err) { const static std::string prop_str("property:"); for (std::size_t i = 0; i < args.size(); ++i) { if (i % 2) { Loading Loading @@ -179,21 +178,26 @@ bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err return true; } bool Action::InitSingleTrigger(const std::string& trigger) { bool Action::InitSingleTrigger(const std::string& trigger) { std::vector<std::string> name_vector{trigger}; std::string err; return InitTriggers(name_vector, &err); } // This function checks that all property triggers are satisfied, that is // for each (name, value) in property_triggers_, check that the current // value of the property 'name' == value. // // It takes an optional (name, value) pair, which if provided must // be present in property_triggers_; it skips the check of the current // property value for this pair. bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const { bool found = name.empty(); const std::string& value) const { if (property_triggers_.empty()) { return true; } bool found = name.empty(); for (const auto& t : property_triggers_) { const auto& trigger_name = t.first; const auto& trigger_value = t.second; Loading @@ -214,27 +218,23 @@ bool Action::CheckPropertyTriggers(const std::string& name, return found; } bool Action::CheckEventTrigger(const std::string& trigger) const { bool Action::CheckEventTrigger(const std::string& trigger) const { return !event_trigger_.empty() && trigger == event_trigger_ && CheckPropertyTriggers(); } bool Action::CheckPropertyTrigger(const std::string& name, const std::string& value) const { const std::string& value) const { return event_trigger_.empty() && CheckPropertyTriggers(name, value); } bool Action::TriggersEqual(const class Action& other) const { bool Action::TriggersEqual(const Action& other) const { return property_triggers_ == other.property_triggers_ && event_trigger_ == other.event_trigger_; } std::string Action::BuildTriggersString() const { std::string Action::BuildTriggersString() const { std::string result; for (const auto& t : property_triggers_) { Loading @@ -251,28 +251,26 @@ std::string Action::BuildTriggersString() const return result; } void Action::DumpState() const { void Action::DumpState() const { std::string trigger_name = BuildTriggersString(); INFO("on %s\n", trigger_name.c_str()); for (const auto& c : commands_) { std::string cmd_str = c->BuildCommandString(); std::string cmd_str = c.BuildCommandString(); INFO(" %s\n", cmd_str.c_str()); } INFO("\n"); } class EventTrigger : public Trigger { public: EventTrigger(const std::string& trigger) : trigger_(trigger) { } bool CheckTriggers(const Action* action) override { return action->CheckEventTrigger(trigger_); bool CheckTriggers(const Action& action) const override { return action.CheckEventTrigger(trigger_); } private: std::string trigger_; const std::string trigger_; }; class PropertyTrigger : public Trigger { Loading @@ -280,27 +278,26 @@ 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_); bool CheckTriggers(const Action& action) const override { return action.CheckPropertyTrigger(name_, value_); } private: std::string name_; std::string value_; const std::string name_; const std::string value_; }; class BuiltinTrigger : public Trigger { public: BuiltinTrigger(Action* action) : action_(action) { } bool CheckTriggers(const Action* action) override { return action == action_; bool CheckTriggers(const Action& action) const override { return action_ == &action; } private: Action* action_; const Action* action_; }; ActionManager::ActionManager() : current_command_(0) { ActionManager::ActionManager() : current_command_(0) { } ActionManager& ActionManager::GetInstance() { Loading @@ -308,45 +305,56 @@ ActionManager& ActionManager::GetInstance() { return instance; } void ActionManager::QueueEventTrigger(const std::string& trigger) { void ActionManager::AddAction(std::unique_ptr<Action> action) { auto old_action_it = std::find_if(actions_.begin(), actions_.end(), [&action] (std::unique_ptr<Action>& a) { return action->TriggersEqual(*a); }); if (old_action_it != actions_.end()) { (*old_action_it)->CombineAction(*action); } else { actions_.emplace_back(std::move(action)); } } void ActionManager::QueueEventTrigger(const std::string& trigger) { trigger_queue_.push(std::make_unique<EventTrigger>(trigger)); } void ActionManager::QueuePropertyTrigger(const std::string& name, const std::string& value) { const std::string& value) { trigger_queue_.push(std::make_unique<PropertyTrigger>(name, value)); } void ActionManager::QueueAllPropertyTriggers() { void ActionManager::QueueAllPropertyTriggers() { QueuePropertyTrigger("", ""); } void ActionManager::QueueBuiltinAction(int (*func)(const std::vector<std::string>& args), const std::string& name) { Action* act = new Action(); void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) { auto action = std::make_unique<Action>(true); std::vector<std::string> name_vector{name}; if (!act->InitSingleTrigger(name)) { if (!action->InitSingleTrigger(name)) { return; } act->AddCommand(func, name_vector); action->AddCommand(func, name_vector); actions_.push_back(act); trigger_queue_.push(std::make_unique<BuiltinTrigger>(act)); trigger_queue_.push(std::make_unique<BuiltinTrigger>(action.get())); actions_.emplace_back(std::move(action)); } void ActionManager::ExecuteOneCommand() { // Loop through the trigger queue until we have an action to execute 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); }); for (const auto& action : actions_) { if (trigger_queue_.front()->CheckTriggers(*action)) { current_executing_actions_.emplace(action.get()); } } trigger_queue_.pop(); } Loading @@ -354,59 +362,67 @@ void ActionManager::ExecuteOneCommand() { return; } Action* action = current_executing_actions_.back(); if (!action->NumCommands()) { current_executing_actions_.pop_back(); return; } auto action = current_executing_actions_.front(); if (current_command_ == 0) { std::string trigger_name = action->BuildTriggersString(); INFO("processing action %p (%s)\n", action, trigger_name.c_str()); INFO("processing action (%s)\n", trigger_name.c_str()); } action->ExecuteOneCommand(current_command_++); action->ExecuteOneCommand(current_command_); // If this was the last command in the current action, then remove // the action from the executing list. // If this action was oneshot, then also remove it from actions_. ++current_command_; if (current_command_ == action->NumCommands()) { current_executing_actions_.pop(); current_command_ = 0; current_executing_actions_.pop_back(); if (action->oneshot()) { auto eraser = [&action] (std::unique_ptr<Action>& a) { return a.get() == action; }; actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser)); } } } bool ActionManager::HasMoreCommands() const { bool ActionManager::HasMoreCommands() const { return !current_executing_actions_.empty() || !trigger_queue_.empty(); } Action* ActionManager::AddNewAction(const std::vector<std::string>& triggers, std::string* err) { if (triggers.size() < 1) { *err = "actions must have a trigger\n"; return nullptr; void ActionManager::DumpState() const { for (const auto& a : actions_) { a->DumpState(); } INFO("\n"); } Action* act = new Action(); if (!act->InitTriggers(triggers, err)) { return nullptr; bool ActionParser::ParseSection(const std::vector<std::string>& args, std::string* err) { std::vector<std::string> triggers(args.begin() + 1, args.end()); if (triggers.size() < 1) { *err = "actions must have a trigger"; return false; } auto old_act_it = std::find_if(actions_.begin(), actions_.end(), [&act] (Action* a) { return act->TriggersEqual(*a); }); auto action = std::make_unique<Action>(false); if (!action->InitTriggers(triggers, err)) { return false; } if (old_act_it != actions_.end()) { delete act; return *old_act_it; action_ = std::move(action); return true; } actions_.push_back(act); return act; bool ActionParser::ParseLineSection(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) const { return action_ ? action_->AddCommand(args, filename, line, err) : false; } void ActionManager::DumpState() const { for (const auto& a : actions_) { a->DumpState(); void ActionParser::EndSection() { if (action_ && action_->NumCommands() > 0) { ActionManager::GetInstance().AddAction(std::move(action_)); } INFO("\n"); } init/action.h +57 −13 Original line number Diff line number Diff line Loading @@ -22,13 +22,36 @@ #include <string> #include <vector> #include "builtins.h" #include "init_parser.h" #include "keyword_map.h" class Command { public: Command(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line); int InvokeFunc() const; std::string BuildCommandString() const; std::string BuildSourceString() const; private: BuiltinFunction func_; std::vector<std::string> args_; std::string filename_; int line_; }; class Action { public: Action(); Action(bool oneshot = false); void AddCommand(int (*f)(const std::vector<std::string>& args), bool AddCommand(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err); void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename = "", int line = 0); void CombineAction(const Action& action); bool InitTriggers(const std::vector<std::string>& args, std::string* err); bool InitSingleTrigger(const std::string& trigger); std::size_t NumCommands() const; Loading @@ -37,13 +60,17 @@ public: bool CheckEventTrigger(const std::string& trigger) const; bool CheckPropertyTrigger(const std::string& name, const std::string& value) const; bool TriggersEqual(const class Action& other) const; bool TriggersEqual(const Action& other) const; std::string BuildTriggersString() const; void DumpState() const; private: class Command; bool oneshot() const { return oneshot_; } static void set_function_map(const KeywordMap<BuiltinFunction>* function_map) { function_map_ = function_map; } private: void ExecuteCommand(const Command& command) const; bool CheckPropertyTriggers(const std::string& name = "", const std::string& value = "") const; Loading @@ -51,27 +78,28 @@ private: std::map<std::string, std::string> property_triggers_; std::string event_trigger_; std::vector<Command*> commands_; std::vector<Command> commands_; bool oneshot_; static const KeywordMap<BuiltinFunction>* function_map_; }; class Trigger { public: virtual ~Trigger() { } virtual bool CheckTriggers(const Action* action) = 0; virtual bool CheckTriggers(const Action& action) const = 0; }; class ActionManager { public: static ActionManager& GetInstance(); void AddAction(std::unique_ptr<Action> action); void QueueEventTrigger(const std::string& trigger); void QueuePropertyTrigger(const std::string& name, const std::string& value); void QueueAllPropertyTriggers(); void QueueBuiltinAction(int (*func)(const std::vector<std::string>& args), const std::string& name); void QueueBuiltinAction(BuiltinFunction func, const std::string& name); void ExecuteOneCommand(); bool HasMoreCommands() const; Action* AddNewAction(const std::vector<std::string>& triggers, std::string* err); void DumpState() const; private: Loading @@ -80,10 +108,26 @@ private: ActionManager(ActionManager const&) = delete; void operator=(ActionManager const&) = delete; std::vector<Action*> actions_; std::vector<std::unique_ptr<Action>> actions_; std::queue<std::unique_ptr<Trigger>> trigger_queue_; std::vector<Action*> current_executing_actions_; std::queue<const Action*> current_executing_actions_; std::size_t current_command_; }; class ActionParser : public SectionParser { public: ActionParser() : action_(nullptr) { } bool ParseSection(const std::vector<std::string>& args, std::string* err) override; bool ParseLineSection(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) const override; void EndSection() override; void EndFile(const std::string&) override { } private: std::unique_ptr<Action> action_; }; #endif init/bootchart.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ #include "bootchart.h" #include "keywords.h" #include "log.h" #include "property_service.h" Loading @@ -32,6 +31,7 @@ #include <memory> #include <string> #include <vector> #include <base/file.h> Loading init/bootchart.h +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,10 @@ #ifndef _BOOTCHART_H #define _BOOTCHART_H #include <string> #include <vector> int do_bootchart_init(const std::vector<std::string>& args); void bootchart_sample(int* timeout); #endif /* _BOOTCHART_H */ Loading
init/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ include $(CLEAR_VARS) LOCAL_CPPFLAGS := $(init_cflags) LOCAL_SRC_FILES:= \ action.cpp \ import_parser.cpp \ init_parser.cpp \ log.cpp \ parser.cpp \ Loading
init/action.cpp +151 −135 Original line number Diff line number Diff line Loading @@ -21,46 +21,27 @@ #include <base/strings.h> #include <base/stringprintf.h> #include "builtins.h" #include "error.h" #include "init_parser.h" #include "log.h" #include "property_service.h" #include "util.h" class Action::Command { public: Command(int (*f)(const std::vector<std::string>& args), const std::vector<std::string>& args, const std::string& filename, int line); int InvokeFunc() const; std::string BuildCommandString() const; std::string BuildSourceString() const; private: int (*func_)(const std::vector<std::string>& args); const std::vector<std::string> args_; const std::string filename_; int line_; }; using android::base::Join; using android::base::StringPrintf; Action::Command::Command(int (*f)(const std::vector<std::string>& args), const std::vector<std::string>& args, const std::string& filename, int line) : func_(f), args_(args), filename_(filename), line_(line) { Command::Command(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line) : func_(f), args_(args), filename_(filename), line_(line) { } int Action::Command::InvokeFunc() const { int Command::InvokeFunc() const { std::vector<std::string> expanded_args; expanded_args.resize(args_.size()); expanded_args[0] = args_[0]; for (std::size_t i = 1; i < args_.size(); ++i) { if (expand_props(args_[i], &expanded_args[i]) == -1) { if (!expand_props(args_[i], &expanded_args[i])) { ERROR("%s: cannot expand '%s'\n", args_[0].c_str(), args_[i].c_str()); return -EINVAL; } Loading @@ -69,51 +50,71 @@ int Action::Command::InvokeFunc() const return func_(expanded_args); } std::string Action::Command::BuildCommandString() const { return android::base::Join(args_, ' '); std::string Command::BuildCommandString() const { return Join(args_, ' '); } std::string Action::Command::BuildSourceString() const { std::string Command::BuildSourceString() const { if (!filename_.empty()) { return android::base::StringPrintf(" (%s:%d)", filename_.c_str(), line_); return StringPrintf(" (%s:%d)", filename_.c_str(), line_); } else { return std::string(); } } Action::Action() { Action::Action(bool oneshot) : oneshot_(oneshot) { } const KeywordMap<BuiltinFunction>* Action::function_map_ = nullptr; bool Action::AddCommand(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) { if (!function_map_) { *err = "no function map available"; return false; } if (args.empty()) { *err = "command needed, but not provided"; return false; } void Action::AddCommand(int (*f)(const std::vector<std::string>& args), auto function = function_map_->FindFunction(args[0], args.size() - 1, err); if (!function) { return false; } AddCommand(function, args, filename, line); return true; } void Action::AddCommand(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line) { Action::Command* cmd = new Action::Command(f, args, filename, line); commands_.push_back(cmd); const std::string& filename, int line) { commands_.emplace_back(f, args, filename, line); } std::size_t Action::NumCommands() const { void Action::CombineAction(const Action& action) { for (const auto& c : action.commands_) { commands_.emplace_back(c); } } std::size_t Action::NumCommands() const { return commands_.size(); } void Action::ExecuteOneCommand(std::size_t command) const { ExecuteCommand(*commands_[command]); void Action::ExecuteOneCommand(std::size_t command) const { ExecuteCommand(commands_[command]); } void Action::ExecuteAllCommands() const { void Action::ExecuteAllCommands() const { for (const auto& c : commands_) { ExecuteCommand(*c); ExecuteCommand(c); } } void Action::ExecuteCommand(const Command& command) const { void Action::ExecuteCommand(const Command& command) const { Timer t; int result = command.InvokeFunc(); Loading @@ -128,8 +129,7 @@ void Action::ExecuteCommand(const Command& command) const } } bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) { bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) { const static std::string prop_str("property:"); std::string prop_name(trigger.substr(prop_str.length())); size_t equal_pos = prop_name.find('='); Loading @@ -149,8 +149,7 @@ bool Action::ParsePropertyTrigger(const std::string& trigger, std::string* err) return true; } bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err) { bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err) { const static std::string prop_str("property:"); for (std::size_t i = 0; i < args.size(); ++i) { if (i % 2) { Loading Loading @@ -179,21 +178,26 @@ bool Action::InitTriggers(const std::vector<std::string>& args, std::string* err return true; } bool Action::InitSingleTrigger(const std::string& trigger) { bool Action::InitSingleTrigger(const std::string& trigger) { std::vector<std::string> name_vector{trigger}; std::string err; return InitTriggers(name_vector, &err); } // This function checks that all property triggers are satisfied, that is // for each (name, value) in property_triggers_, check that the current // value of the property 'name' == value. // // It takes an optional (name, value) pair, which if provided must // be present in property_triggers_; it skips the check of the current // property value for this pair. bool Action::CheckPropertyTriggers(const std::string& name, const std::string& value) const { bool found = name.empty(); const std::string& value) const { if (property_triggers_.empty()) { return true; } bool found = name.empty(); for (const auto& t : property_triggers_) { const auto& trigger_name = t.first; const auto& trigger_value = t.second; Loading @@ -214,27 +218,23 @@ bool Action::CheckPropertyTriggers(const std::string& name, return found; } bool Action::CheckEventTrigger(const std::string& trigger) const { bool Action::CheckEventTrigger(const std::string& trigger) const { return !event_trigger_.empty() && trigger == event_trigger_ && CheckPropertyTriggers(); } bool Action::CheckPropertyTrigger(const std::string& name, const std::string& value) const { const std::string& value) const { return event_trigger_.empty() && CheckPropertyTriggers(name, value); } bool Action::TriggersEqual(const class Action& other) const { bool Action::TriggersEqual(const Action& other) const { return property_triggers_ == other.property_triggers_ && event_trigger_ == other.event_trigger_; } std::string Action::BuildTriggersString() const { std::string Action::BuildTriggersString() const { std::string result; for (const auto& t : property_triggers_) { Loading @@ -251,28 +251,26 @@ std::string Action::BuildTriggersString() const return result; } void Action::DumpState() const { void Action::DumpState() const { std::string trigger_name = BuildTriggersString(); INFO("on %s\n", trigger_name.c_str()); for (const auto& c : commands_) { std::string cmd_str = c->BuildCommandString(); std::string cmd_str = c.BuildCommandString(); INFO(" %s\n", cmd_str.c_str()); } INFO("\n"); } class EventTrigger : public Trigger { public: EventTrigger(const std::string& trigger) : trigger_(trigger) { } bool CheckTriggers(const Action* action) override { return action->CheckEventTrigger(trigger_); bool CheckTriggers(const Action& action) const override { return action.CheckEventTrigger(trigger_); } private: std::string trigger_; const std::string trigger_; }; class PropertyTrigger : public Trigger { Loading @@ -280,27 +278,26 @@ 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_); bool CheckTriggers(const Action& action) const override { return action.CheckPropertyTrigger(name_, value_); } private: std::string name_; std::string value_; const std::string name_; const std::string value_; }; class BuiltinTrigger : public Trigger { public: BuiltinTrigger(Action* action) : action_(action) { } bool CheckTriggers(const Action* action) override { return action == action_; bool CheckTriggers(const Action& action) const override { return action_ == &action; } private: Action* action_; const Action* action_; }; ActionManager::ActionManager() : current_command_(0) { ActionManager::ActionManager() : current_command_(0) { } ActionManager& ActionManager::GetInstance() { Loading @@ -308,45 +305,56 @@ ActionManager& ActionManager::GetInstance() { return instance; } void ActionManager::QueueEventTrigger(const std::string& trigger) { void ActionManager::AddAction(std::unique_ptr<Action> action) { auto old_action_it = std::find_if(actions_.begin(), actions_.end(), [&action] (std::unique_ptr<Action>& a) { return action->TriggersEqual(*a); }); if (old_action_it != actions_.end()) { (*old_action_it)->CombineAction(*action); } else { actions_.emplace_back(std::move(action)); } } void ActionManager::QueueEventTrigger(const std::string& trigger) { trigger_queue_.push(std::make_unique<EventTrigger>(trigger)); } void ActionManager::QueuePropertyTrigger(const std::string& name, const std::string& value) { const std::string& value) { trigger_queue_.push(std::make_unique<PropertyTrigger>(name, value)); } void ActionManager::QueueAllPropertyTriggers() { void ActionManager::QueueAllPropertyTriggers() { QueuePropertyTrigger("", ""); } void ActionManager::QueueBuiltinAction(int (*func)(const std::vector<std::string>& args), const std::string& name) { Action* act = new Action(); void ActionManager::QueueBuiltinAction(BuiltinFunction func, const std::string& name) { auto action = std::make_unique<Action>(true); std::vector<std::string> name_vector{name}; if (!act->InitSingleTrigger(name)) { if (!action->InitSingleTrigger(name)) { return; } act->AddCommand(func, name_vector); action->AddCommand(func, name_vector); actions_.push_back(act); trigger_queue_.push(std::make_unique<BuiltinTrigger>(act)); trigger_queue_.push(std::make_unique<BuiltinTrigger>(action.get())); actions_.emplace_back(std::move(action)); } void ActionManager::ExecuteOneCommand() { // Loop through the trigger queue until we have an action to execute 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); }); for (const auto& action : actions_) { if (trigger_queue_.front()->CheckTriggers(*action)) { current_executing_actions_.emplace(action.get()); } } trigger_queue_.pop(); } Loading @@ -354,59 +362,67 @@ void ActionManager::ExecuteOneCommand() { return; } Action* action = current_executing_actions_.back(); if (!action->NumCommands()) { current_executing_actions_.pop_back(); return; } auto action = current_executing_actions_.front(); if (current_command_ == 0) { std::string trigger_name = action->BuildTriggersString(); INFO("processing action %p (%s)\n", action, trigger_name.c_str()); INFO("processing action (%s)\n", trigger_name.c_str()); } action->ExecuteOneCommand(current_command_++); action->ExecuteOneCommand(current_command_); // If this was the last command in the current action, then remove // the action from the executing list. // If this action was oneshot, then also remove it from actions_. ++current_command_; if (current_command_ == action->NumCommands()) { current_executing_actions_.pop(); current_command_ = 0; current_executing_actions_.pop_back(); if (action->oneshot()) { auto eraser = [&action] (std::unique_ptr<Action>& a) { return a.get() == action; }; actions_.erase(std::remove_if(actions_.begin(), actions_.end(), eraser)); } } } bool ActionManager::HasMoreCommands() const { bool ActionManager::HasMoreCommands() const { return !current_executing_actions_.empty() || !trigger_queue_.empty(); } Action* ActionManager::AddNewAction(const std::vector<std::string>& triggers, std::string* err) { if (triggers.size() < 1) { *err = "actions must have a trigger\n"; return nullptr; void ActionManager::DumpState() const { for (const auto& a : actions_) { a->DumpState(); } INFO("\n"); } Action* act = new Action(); if (!act->InitTriggers(triggers, err)) { return nullptr; bool ActionParser::ParseSection(const std::vector<std::string>& args, std::string* err) { std::vector<std::string> triggers(args.begin() + 1, args.end()); if (triggers.size() < 1) { *err = "actions must have a trigger"; return false; } auto old_act_it = std::find_if(actions_.begin(), actions_.end(), [&act] (Action* a) { return act->TriggersEqual(*a); }); auto action = std::make_unique<Action>(false); if (!action->InitTriggers(triggers, err)) { return false; } if (old_act_it != actions_.end()) { delete act; return *old_act_it; action_ = std::move(action); return true; } actions_.push_back(act); return act; bool ActionParser::ParseLineSection(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) const { return action_ ? action_->AddCommand(args, filename, line, err) : false; } void ActionManager::DumpState() const { for (const auto& a : actions_) { a->DumpState(); void ActionParser::EndSection() { if (action_ && action_->NumCommands() > 0) { ActionManager::GetInstance().AddAction(std::move(action_)); } INFO("\n"); }
init/action.h +57 −13 Original line number Diff line number Diff line Loading @@ -22,13 +22,36 @@ #include <string> #include <vector> #include "builtins.h" #include "init_parser.h" #include "keyword_map.h" class Command { public: Command(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename, int line); int InvokeFunc() const; std::string BuildCommandString() const; std::string BuildSourceString() const; private: BuiltinFunction func_; std::vector<std::string> args_; std::string filename_; int line_; }; class Action { public: Action(); Action(bool oneshot = false); void AddCommand(int (*f)(const std::vector<std::string>& args), bool AddCommand(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err); void AddCommand(BuiltinFunction f, const std::vector<std::string>& args, const std::string& filename = "", int line = 0); void CombineAction(const Action& action); bool InitTriggers(const std::vector<std::string>& args, std::string* err); bool InitSingleTrigger(const std::string& trigger); std::size_t NumCommands() const; Loading @@ -37,13 +60,17 @@ public: bool CheckEventTrigger(const std::string& trigger) const; bool CheckPropertyTrigger(const std::string& name, const std::string& value) const; bool TriggersEqual(const class Action& other) const; bool TriggersEqual(const Action& other) const; std::string BuildTriggersString() const; void DumpState() const; private: class Command; bool oneshot() const { return oneshot_; } static void set_function_map(const KeywordMap<BuiltinFunction>* function_map) { function_map_ = function_map; } private: void ExecuteCommand(const Command& command) const; bool CheckPropertyTriggers(const std::string& name = "", const std::string& value = "") const; Loading @@ -51,27 +78,28 @@ private: std::map<std::string, std::string> property_triggers_; std::string event_trigger_; std::vector<Command*> commands_; std::vector<Command> commands_; bool oneshot_; static const KeywordMap<BuiltinFunction>* function_map_; }; class Trigger { public: virtual ~Trigger() { } virtual bool CheckTriggers(const Action* action) = 0; virtual bool CheckTriggers(const Action& action) const = 0; }; class ActionManager { public: static ActionManager& GetInstance(); void AddAction(std::unique_ptr<Action> action); void QueueEventTrigger(const std::string& trigger); void QueuePropertyTrigger(const std::string& name, const std::string& value); void QueueAllPropertyTriggers(); void QueueBuiltinAction(int (*func)(const std::vector<std::string>& args), const std::string& name); void QueueBuiltinAction(BuiltinFunction func, const std::string& name); void ExecuteOneCommand(); bool HasMoreCommands() const; Action* AddNewAction(const std::vector<std::string>& triggers, std::string* err); void DumpState() const; private: Loading @@ -80,10 +108,26 @@ private: ActionManager(ActionManager const&) = delete; void operator=(ActionManager const&) = delete; std::vector<Action*> actions_; std::vector<std::unique_ptr<Action>> actions_; std::queue<std::unique_ptr<Trigger>> trigger_queue_; std::vector<Action*> current_executing_actions_; std::queue<const Action*> current_executing_actions_; std::size_t current_command_; }; class ActionParser : public SectionParser { public: ActionParser() : action_(nullptr) { } bool ParseSection(const std::vector<std::string>& args, std::string* err) override; bool ParseLineSection(const std::vector<std::string>& args, const std::string& filename, int line, std::string* err) const override; void EndSection() override; void EndFile(const std::string&) override { } private: std::unique_ptr<Action> action_; }; #endif
init/bootchart.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -15,7 +15,6 @@ */ #include "bootchart.h" #include "keywords.h" #include "log.h" #include "property_service.h" Loading @@ -32,6 +31,7 @@ #include <memory> #include <string> #include <vector> #include <base/file.h> Loading
init/bootchart.h +4 −0 Original line number Diff line number Diff line Loading @@ -17,6 +17,10 @@ #ifndef _BOOTCHART_H #define _BOOTCHART_H #include <string> #include <vector> int do_bootchart_init(const std::vector<std::string>& args); void bootchart_sample(int* timeout); #endif /* _BOOTCHART_H */