You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
4.0 KiB

11 months ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2021 Jon Evans <jon@craftyjon.com>
  5. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <thread>
  21. #include <core/wx_stl_compat.h>
  22. #include <symbol_async_loader.h>
  23. #include <symbol_lib_table.h>
  24. #include <progress_reporter.h>
  25. SYMBOL_ASYNC_LOADER::SYMBOL_ASYNC_LOADER( const std::vector<wxString>& aNicknames,
  26. SYMBOL_LIB_TABLE* aTable, bool aOnlyPowerSymbols,
  27. std::unordered_map<wxString, std::vector<LIB_SYMBOL*>>* aOutput,
  28. PROGRESS_REPORTER* aReporter ) :
  29. m_nicknames( aNicknames ),
  30. m_table( aTable ),
  31. m_onlyPowerSymbols( aOnlyPowerSymbols ),
  32. m_output( aOutput ),
  33. m_reporter( aReporter ),
  34. m_nextLibrary( 0 )
  35. {
  36. wxASSERT( m_table );
  37. m_threadCount = std::max<size_t>( 1, std::thread::hardware_concurrency() );
  38. m_returns.resize( m_threadCount );
  39. }
  40. SYMBOL_ASYNC_LOADER::~SYMBOL_ASYNC_LOADER()
  41. {
  42. Join();
  43. }
  44. void SYMBOL_ASYNC_LOADER::Start()
  45. {
  46. for( size_t ii = 0; ii < m_threadCount; ++ii )
  47. m_returns[ii] = std::async( std::launch::async, &SYMBOL_ASYNC_LOADER::worker, this );
  48. }
  49. bool SYMBOL_ASYNC_LOADER::Join()
  50. {
  51. for( size_t ii = 0; ii < m_threadCount; ++ii )
  52. {
  53. if( !m_returns[ii].valid() )
  54. continue;
  55. m_returns[ii].wait();
  56. const std::vector<LOADED_PAIR>& ret = m_returns[ii].get();
  57. if( m_output && !ret.empty() )
  58. {
  59. for( const LOADED_PAIR& pair : ret )
  60. {
  61. // Don't show libraries that had no power symbols
  62. if( m_onlyPowerSymbols && pair.second.empty() )
  63. continue;
  64. // *Do* show empty libraries in the normal case
  65. m_output->insert( pair );
  66. }
  67. }
  68. }
  69. return true;
  70. }
  71. bool SYMBOL_ASYNC_LOADER::Done()
  72. {
  73. return m_nextLibrary.load() >= m_nicknames.size();
  74. }
  75. std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
  76. {
  77. std::vector<LOADED_PAIR> ret;
  78. bool onlyPower = m_onlyPowerSymbols;
  79. for( size_t libraryIndex = m_nextLibrary++; libraryIndex < m_nicknames.size();
  80. libraryIndex = m_nextLibrary++ )
  81. {
  82. const wxString& nickname = m_nicknames[libraryIndex];
  83. if( m_reporter )
  84. m_reporter->AdvancePhase( wxString::Format( _( "Loading library %s..." ), nickname ) );
  85. if( m_reporter && m_reporter->IsCancelled() )
  86. break;
  87. LOADED_PAIR pair( nickname, {} );
  88. try
  89. {
  90. m_table->LoadSymbolLib( pair.second, nickname, onlyPower );
  91. ret.emplace_back( std::move( pair ) );
  92. }
  93. catch( const IO_ERROR& ioe )
  94. {
  95. wxString msg = wxString::Format( _( "Error loading symbol library %s.\n\n%s\n" ),
  96. nickname, ioe.What() );
  97. std::lock_guard<std::mutex> lock( m_errorMutex );
  98. m_errors += msg;
  99. }
  100. catch( std::exception& e )
  101. {
  102. wxString msg = wxString::Format( _( "Error loading symbol library %s.\n\n%s\n" ),
  103. nickname, e.what() );
  104. std::lock_guard<std::mutex> lock( m_errorMutex );
  105. m_errors += msg;
  106. }
  107. }
  108. return ret;
  109. }