================ @@ -338,17 +460,129 @@ ModulesBuilder::buildPrerequisiteModulesFor(PathRef File, return std::move(RequiredModules); } -bool StandalonePrerequisiteModules::canReuse( +ReusableModulesBuilder::ModuleBuildingSharedOwner +ReusableModulesBuilder::getOrCreateModuleBuildingOwner(StringRef ModuleName) { + std::lock_guard<std::mutex> _(ModulesBuildingMutex); + + auto MutexIter = BuildingModuleMutexes.find(ModuleName); + if (MutexIter == BuildingModuleMutexes.end()) + MutexIter = BuildingModuleMutexes + .try_emplace(ModuleName, std::make_shared<std::mutex>()) + .first; + + auto CVIter = BuildingModuleCVs.find(ModuleName); + if (CVIter == BuildingModuleCVs.end()) + CVIter = BuildingModuleCVs + .try_emplace(ModuleName, + std::make_shared<std::condition_variable>()) + .first; + + return ModuleBuildingSharedOwner(ModuleName, MutexIter->getValue(), + CVIter->getValue(), *this); +} + +llvm::Error ReusableModulesBuilder::getOrBuildModuleFile( + StringRef ModuleName, const ThreadsafeFS &TFS, ProjectModules &MDB, + ReusablePrerequisiteModules &BuiltModuleFiles) { + if (BuiltModuleFiles.isModuleUnitBuilt(ModuleName)) + return llvm::Error::success(); + + PathRef ModuleUnitFileName = MDB.getSourceForModuleName(ModuleName); + /// It is possible that we're meeting third party modules (modules whose + /// source are not in the project. e.g, the std module may be a third-party + /// module for most project) or something wrong with the implementation of + /// ProjectModules. + /// FIXME: How should we treat third party modules here? If we want to ignore + /// third party modules, we should return true instead of false here. + /// Currently we simply bail out. + if (ModuleUnitFileName.empty()) + return llvm::createStringError( + llvm::formatv("Don't get the module unit for module {0}", ModuleName)); + + for (auto &RequiredModuleName : MDB.getRequiredModules(ModuleUnitFileName)) + // Return early if there are errors building the module file. + if (!getOrBuildModuleFile(RequiredModuleName, TFS, MDB, BuiltModuleFiles)) + return llvm::createStringError( + llvm::formatv("Failed to build module {0}", RequiredModuleName)); + + if (std::shared_ptr<ModuleFile> Cached = + getValidModuleFile(ModuleName, MDB, TFS, BuiltModuleFiles)) { + log("Reusing module {0} from {1}", ModuleName, Cached->ModuleFilePath); + BuiltModuleFiles.addModuleFile(Cached); + return llvm::Error::success(); + } + + ModuleBuildingSharedOwner ModuleBuildingOwner = + getOrCreateModuleBuildingOwner(ModuleName); + + std::condition_variable &CV = ModuleBuildingOwner.getCV(); + std::unique_lock<std::mutex> lk(ModuleBuildingOwner.getMutex()); + if (!ModuleBuildingOwner.isUniqueBuildingOwner()) { ---------------- ChuanqiXu9 wrote:
Done. Sounds not bad. https://github.com/llvm/llvm-project/pull/106683 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits