Index: tools/gn/loader.h |
diff --git a/tools/gn/loader.h b/tools/gn/loader.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..63a10de777817b8f35f0dd45546f5461d99eda79 |
--- /dev/null |
+++ b/tools/gn/loader.h |
@@ -0,0 +1,177 @@ |
+// Copyright (c) 2013 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#ifndef TOOLS_GN_LOADER_H_ |
+#define TOOLS_GN_LOADER_H_ |
+ |
+#include <map> |
+#include <set> |
+ |
+#include "base/callback.h" |
+#include "base/memory/ref_counted.h" |
+#include "tools/gn/label.h" |
+#include "tools/gn/scope.h" |
+ |
+namespace base { |
+class MessageLoop; |
+} |
+ |
+class BuildSettings; |
+class Settings; |
+class SourceFile; |
+class Toolchain; |
+ |
+// The loader manages execution of the different build files. It receives |
+// requests (normally from the Builder) when new references are found, and also |
+// manages loading the build config files. |
+// |
+// This loader class is abstract so it can be mocked out for testing the |
+// Builder. |
+class Loader : public base::RefCountedThreadSafe<Loader> { |
+ public: |
+ Loader(); |
+ |
+ // Loads the given file in the conext of the given toolchain. The initial |
+ // call to this (the one that actually starts the generation) should have an |
+ // empty toolchain name, which will trigger the load of the default build |
+ // config. |
+ virtual void Load(const SourceFile& file, |
+ const Label& toolchain_name) = 0; |
+ |
+ // Notification that the given toolchain has loaded. This will unblock files |
+ // waiting on this definition. |
+ virtual void ToolchainLoaded(const Toolchain* toolchain) = 0; |
+ |
+ // Returns the label of the default toolchain. |
+ virtual Label GetDefaultToolchain() const = 0; |
+ |
+ // Returns information about the toolchain with the given label. Will return |
+ // false if we haven't processed this toolchain yet. |
+ virtual const Settings* GetToolchainSettings(const Label& label) = 0; |
+ |
+ // Helper function that extracts the file and toolchain name from the given |
+ // label, and calls Load(). |
+ void Load(const Label& label); |
+ |
+ // Returns the build file that the given label references. |
+ static SourceFile BuildFileForLabel(const Label& label); |
+ |
+ // When processing the default build config, we want to capture the argument |
+ // of set_default_build_config. The implementation of that function uses this |
+ // constant as a property key to get the Label* out of the scope where the |
+ // label should be stored. |
+ static const void* kDefaultToolchainKey; |
+ |
+ protected: |
+ friend class base::RefCountedThreadSafe<Loader>; |
+ virtual ~Loader(); |
+}; |
+ |
+class LoaderImpl : public Loader { |
+ public: |
+ // Callback to emulate InputFileManager::AsyncLoadFile. |
+ typedef base::Callback<bool(const LocationRange&, |
+ const BuildSettings*, |
+ const SourceFile&, |
+ const base::Callback<void(const ParseNode*)>&, |
+ Err*)> AsyncLoadFileCallback; |
+ |
+ LoaderImpl(const BuildSettings* build_settings); |
+ |
+ // Loader implementation. |
+ virtual void Load(const SourceFile& file, |
+ const Label& toolchain_name) OVERRIDE; |
+ virtual void ToolchainLoaded(const Toolchain* toolchain) OVERRIDE; |
+ virtual Label GetDefaultToolchain() const OVERRIDE; |
+ virtual const Settings* GetToolchainSettings(const Label& label) OVERRIDE; |
+ |
+ // Sets the message loop corresponding to the main thread. By default this |
+ // class will use the thread active during construction, but there is not |
+ // a message loop active during construction all the time. |
+ void set_main_loop(base::MessageLoop* loop) { main_loop_ = loop; } |
+ |
+ // The complete callback is called whenever there are no more pending loads. |
+ // Called on the main thread only. This may be called more than once if the |
+ // queue is drained, but then more stuff gets added. |
+ void set_complete_callback(const base::Closure& cb) { |
+ complete_callback_ = cb; |
+ } |
+ |
+ // This callback is used when the loader finds it wants to load a file. |
+ void set_async_load_file(const AsyncLoadFileCallback& cb) { |
+ async_load_file_ = cb; |
+ } |
+ |
+ const Label& default_toolchain_label() const { |
+ return default_toolchain_label_; |
+ } |
+ |
+ private: |
+ struct LoadID; |
+ struct ToolchainRecord; |
+ |
+ virtual ~LoaderImpl(); |
+ |
+ // Schedules the input file manager to load the given file. |
+ void ScheduleLoadFile(const Settings* settings, |
+ const SourceFile& file); |
+ void ScheduleLoadBuildConfig( |
+ Settings* settings, |
+ const Scope::KeyValueMap& toolchain_overrides); |
+ |
+ // Runs the given file on the background thread. These are called by the |
+ // input file manager. |
+ void BackgroundLoadFile(const Settings* settings, |
+ const SourceFile& file_name, |
+ const ParseNode* root); |
+ void BackgroundLoadBuildConfig( |
+ Settings* settings, |
+ const Scope::KeyValueMap& toolchain_overrides, |
+ const ParseNode* root); |
+ |
+ // Posted to the main thread when any file other than a build config file |
+ // file has completed running. |
+ void DidLoadFile(); |
+ |
+ // Posted to the main thread when any build config file has completed |
+ // running. The label should be the name of the toolchain. |
+ // |
+ // If there is no defauled toolchain loaded yet, we'll assume that the first |
+ // call to this indicates to the default toolchain, and this function will |
+ // set the default toolchain name to the given label. |
+ void DidLoadBuildConfig(const Label& label); |
+ |
+ // Decrements the pending_loads_ variable and issues the complete callback if |
+ // necessary. |
+ void DecrementPendingLoads(); |
+ |
+ // Forwards to the appropriate location to load the file. |
+ bool AsyncLoadFile(const LocationRange& origin, |
+ const BuildSettings* build_settings, |
+ const SourceFile& file_name, |
+ const base::Callback<void(const ParseNode*)>& callback, |
+ Err* err); |
+ |
+ base::MessageLoop* main_loop_; |
+ |
+ int pending_loads_; |
+ base::Closure complete_callback_; |
+ |
+ // When non-null, use this callback instead of the InputFileManager for |
+ // mocking purposes. |
+ AsyncLoadFileCallback async_load_file_; |
+ |
+ typedef std::set<LoadID> LoadIDSet; |
+ LoadIDSet invocations_; |
+ |
+ const BuildSettings* build_settings_; |
+ Label default_toolchain_label_; |
+ |
+ // Records for the build config file loads. |
+ // Owning pointers. |
+ typedef std::map<Label, ToolchainRecord*> ToolchainRecordMap; |
+ ToolchainRecordMap toolchain_records_; |
+}; |
+ |
+#endif // TOOLS_GN_LOADER_H_ |