Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2019 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #include "module.h" |
| 18 | |
Zach Johnson | 7ea2068 | 2019-04-29 14:48:42 -0700 | [diff] [blame] | 19 | using ::bluetooth::os::Handler; |
| 20 | using ::bluetooth::os::Thread; |
| 21 | |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 22 | namespace bluetooth { |
| 23 | |
Hansong Zhang | 28f5244 | 2019-11-12 12:23:30 -0800 | [diff] [blame] | 24 | constexpr std::chrono::milliseconds kModuleStopTimeout = std::chrono::milliseconds(20); |
| 25 | |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 26 | ModuleFactory::ModuleFactory(std::function<Module*()> ctor) : ctor_(ctor) { |
| 27 | } |
| 28 | |
Zongheng Wang | 6fd349a | 2019-11-12 16:14:01 -0800 | [diff] [blame] | 29 | std::string Module::ToString() const { |
| 30 | return "Module"; |
| 31 | } |
| 32 | |
Myles Watson | a61337d | 2019-10-18 11:21:47 -0700 | [diff] [blame] | 33 | Handler* Module::GetHandler() const { |
Hansong Zhang | 712e9e2 | 2019-05-29 17:52:24 -0700 | [diff] [blame] | 34 | ASSERT_LOG(handler_ != nullptr, "Can't get handler when it's not started"); |
Zach Johnson | 7ea2068 | 2019-04-29 14:48:42 -0700 | [diff] [blame] | 35 | return handler_; |
| 36 | } |
| 37 | |
Myles Watson | a61337d | 2019-10-18 11:21:47 -0700 | [diff] [blame] | 38 | const ModuleRegistry* Module::GetModuleRegistry() const { |
Zach Johnson | 84b448b | 2019-04-29 15:34:55 -0700 | [diff] [blame] | 39 | return registry_; |
| 40 | } |
| 41 | |
| 42 | Module* Module::GetDependency(const ModuleFactory* module) const { |
| 43 | for (auto& dependency : dependencies_.list_) { |
| 44 | if (dependency == module) { |
| 45 | return registry_->Get(module); |
| 46 | } |
| 47 | } |
| 48 | |
| 49 | ASSERT_LOG(false, "Module was not listed as a dependency in ListDependencies"); |
| 50 | } |
| 51 | |
| 52 | Module* ModuleRegistry::Get(const ModuleFactory* module) const { |
| 53 | auto instance = started_modules_.find(module); |
| 54 | ASSERT(instance != started_modules_.end()); |
| 55 | return instance->second; |
| 56 | } |
| 57 | |
| 58 | bool ModuleRegistry::IsStarted(const ModuleFactory* module) const { |
| 59 | return started_modules_.find(module) != started_modules_.end(); |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 60 | } |
| 61 | |
Zach Johnson | 7ea2068 | 2019-04-29 14:48:42 -0700 | [diff] [blame] | 62 | void ModuleRegistry::Start(ModuleList* modules, Thread* thread) { |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 63 | for (auto it = modules->list_.begin(); it != modules->list_.end(); it++) { |
Zach Johnson | 7ea2068 | 2019-04-29 14:48:42 -0700 | [diff] [blame] | 64 | Start(*it, thread); |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 65 | } |
| 66 | } |
| 67 | |
Myles Watson | 879fbfb | 2019-05-06 17:54:51 -0700 | [diff] [blame] | 68 | void ModuleRegistry::set_registry_and_handler(Module* instance, Thread* thread) const { |
| 69 | instance->registry_ = this; |
| 70 | instance->handler_ = new Handler(thread); |
| 71 | } |
| 72 | |
Zach Johnson | 84b448b | 2019-04-29 15:34:55 -0700 | [diff] [blame] | 73 | Module* ModuleRegistry::Start(const ModuleFactory* module, Thread* thread) { |
| 74 | auto started_instance = started_modules_.find(module); |
| 75 | if (started_instance != started_modules_.end()) { |
| 76 | return started_instance->second; |
Zach Johnson | e0e158c | 2019-04-26 11:57:05 -0700 | [diff] [blame] | 77 | } |
| 78 | |
| 79 | Module* instance = module->ctor_(); |
Myles Watson | 879fbfb | 2019-05-06 17:54:51 -0700 | [diff] [blame] | 80 | set_registry_and_handler(instance, thread); |
Zach Johnson | 7ea2068 | 2019-04-29 14:48:42 -0700 | [diff] [blame] | 81 | |
Myles Watson | 879fbfb | 2019-05-06 17:54:51 -0700 | [diff] [blame] | 82 | instance->ListDependencies(&instance->dependencies_); |
Zach Johnson | 84b448b | 2019-04-29 15:34:55 -0700 | [diff] [blame] | 83 | Start(&instance->dependencies_, thread); |
Zach Johnson | e0e158c | 2019-04-26 11:57:05 -0700 | [diff] [blame] | 84 | |
Zach Johnson | 84b448b | 2019-04-29 15:34:55 -0700 | [diff] [blame] | 85 | instance->Start(); |
Zach Johnson | e0e158c | 2019-04-26 11:57:05 -0700 | [diff] [blame] | 86 | start_order_.push_back(module); |
| 87 | started_modules_[module] = instance; |
Zach Johnson | 84b448b | 2019-04-29 15:34:55 -0700 | [diff] [blame] | 88 | return instance; |
Zach Johnson | e0e158c | 2019-04-26 11:57:05 -0700 | [diff] [blame] | 89 | } |
| 90 | |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 91 | void ModuleRegistry::StopAll() { |
Myles Watson | 742fe6d | 2019-06-07 08:57:16 -0700 | [diff] [blame] | 92 | // Since modules were brought up in dependency order, it is safe to tear down by going in reverse order. |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 93 | for (auto it = start_order_.rbegin(); it != start_order_.rend(); it++) { |
| 94 | auto instance = started_modules_.find(*it); |
| 95 | ASSERT(instance != started_modules_.end()); |
Zach Johnson | 84b448b | 2019-04-29 15:34:55 -0700 | [diff] [blame] | 96 | |
Myles Watson | 742fe6d | 2019-06-07 08:57:16 -0700 | [diff] [blame] | 97 | // Clear the handler before stopping the module to allow it to shut down gracefully. |
| 98 | instance->second->handler_->Clear(); |
| 99 | instance->second->handler_->WaitUntilStopped(kModuleStopTimeout); |
Zach Johnson | 84b448b | 2019-04-29 15:34:55 -0700 | [diff] [blame] | 100 | instance->second->Stop(); |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 101 | |
Zach Johnson | 7ea2068 | 2019-04-29 14:48:42 -0700 | [diff] [blame] | 102 | delete instance->second->handler_; |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 103 | delete instance->second; |
| 104 | started_modules_.erase(instance); |
| 105 | } |
| 106 | |
| 107 | ASSERT(started_modules_.empty()); |
| 108 | start_order_.clear(); |
| 109 | } |
Hansong Zhang | 7079983 | 2019-05-09 16:40:37 -0700 | [diff] [blame] | 110 | |
| 111 | os::Handler* ModuleRegistry::GetModuleHandler(const ModuleFactory* module) const { |
| 112 | auto started_instance = started_modules_.find(module); |
| 113 | if (started_instance != started_modules_.end()) { |
| 114 | return started_instance->second->GetHandler(); |
| 115 | } |
| 116 | return nullptr; |
| 117 | } |
Zach Johnson | 429c94b | 2019-04-25 22:24:54 -0700 | [diff] [blame] | 118 | } // namespace bluetooth |