SharedLibraryPtr Compiler::getOrCount( const std::string & key, UInt32 min_count_to_compile, const std::string & additional_compiler_flags, CodeGenerator get_code, ReadyCallback on_ready) { HashedKey hashed_key = getHash(key); std::lock_guard<std::mutex> lock(mutex); UInt32 count = ++counts[hashed_key]; /// Is there a ready open library? Or, if the library is in the process of compiling, there will be nullptr. Libraries::iterator it = libraries.find(hashed_key); if (libraries.end() != it) { if (!it->second) LOG_INFO(log, "Library " << hashedKeyToFileName(hashed_key) << " is already compiling or compilation was failed."); /// TODO In this case, after the compilation is finished, the callback will not be called. return it->second; } /// Is there a file with the library left over from the previous launch? std::string file_name = hashedKeyToFileName(hashed_key); if (files.count(file_name)) { std::string so_file_path = path + '/' + file_name + ".so"; LOG_INFO(log, "Loading existing library " << so_file_path); SharedLibraryPtr lib(new SharedLibrary(so_file_path)); libraries[hashed_key] = lib; return lib; } /// Has min_count_to_compile been reached? if (count >= min_count_to_compile) { /// The min_count_to_compile value of zero indicates the need for synchronous compilation. /// Are there any free threads? if (min_count_to_compile == 0 || pool.active() < pool.size()) { /// Indicates that the library is in the process of compiling. libraries[hashed_key] = nullptr; LOG_INFO(log, "Compiling code " << file_name << ", key: " << key); if (min_count_to_compile == 0) { { ext::unlock_guard<std::mutex> unlock(mutex); compile(hashed_key, file_name, additional_compiler_flags, get_code, on_ready); } return libraries[hashed_key]; } else { pool.schedule([=] { try { compile(hashed_key, file_name, additional_compiler_flags, get_code, on_ready); } catch (...) { tryLogCurrentException("Compiler"); } }); } } else LOG_INFO(log, "All threads are busy."); } return nullptr; }
SharedLibraryPtr Compiler::getOrCount( const std::string & key, UInt32 min_count_to_compile, const std::string & additional_compiler_flags, CodeGenerator get_code, ReadyCallback on_ready) { HashedKey hashed_key = getHash(key); std::lock_guard<std::mutex> lock(mutex); UInt32 count = ++counts[hashed_key]; /// Есть готовая открытая библиотека? Или, если библиотека в процессе компиляции, там будет nullptr. Libraries::iterator it = libraries.find(hashed_key); if (libraries.end() != it) { if (!it->second) LOG_INFO(log, "Library " << hashedKeyToFileName(hashed_key) << " is already compiling or compilation was failed."); /// TODO В этом случае, после окончания компиляции, не будет дёрнут колбэк. return it->second; } /// Есть файл с библиотекой, оставшийся от предыдущего запуска? std::string file_name = hashedKeyToFileName(hashed_key); if (files.count(file_name)) { std::string so_file_path = path + '/' + file_name + ".so"; LOG_INFO(log, "Loading existing library " << so_file_path); SharedLibraryPtr lib(new SharedLibrary(so_file_path)); libraries[hashed_key] = lib; return lib; } /// Достигнуто ли min_count_to_compile? if (count >= min_count_to_compile) { /// Значение min_count_to_compile, равное нулю, обозначает необходимость синхронной компиляции. /// Есть ли свободные потоки. if (min_count_to_compile == 0 || pool.active() < pool.size()) { /// Обозначает, что библиотека в процессе компиляции. libraries[hashed_key] = nullptr; LOG_INFO(log, "Compiling code " << file_name << ", key: " << key); if (min_count_to_compile == 0) { { ext::unlock_guard<std::mutex> unlock(mutex); compile(hashed_key, file_name, additional_compiler_flags, get_code, on_ready); } return libraries[hashed_key]; } else { pool.schedule([=] { try { compile(hashed_key, file_name, additional_compiler_flags, get_code, on_ready); } catch (...) { tryLogCurrentException("Compiler"); } }); } } else LOG_INFO(log, "All threads are busy."); } return nullptr; }