KiCad PCB EDA Suite
symbol_async_loader.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2021 Jon Evans <[email protected]>
5 * Copyright (C) 2021-2022 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
21#include <thread>
22
23#include <core/wx_stl_compat.h>
24#include <symbol_async_loader.h>
25#include <symbol_lib_table.h>
26#include <progress_reporter.h>
27
28
29SYMBOL_ASYNC_LOADER::SYMBOL_ASYNC_LOADER( const std::vector<wxString>& aNicknames,
30 SYMBOL_LIB_TABLE* aTable, bool aOnlyPowerSymbols,
31 std::unordered_map<wxString, std::vector<LIB_SYMBOL*>>* aOutput,
32 PROGRESS_REPORTER* aReporter ) :
33 m_nicknames( aNicknames ),
34 m_table( aTable ),
35 m_onlyPowerSymbols( aOnlyPowerSymbols ),
36 m_output( aOutput ),
37 m_reporter( aReporter ),
38 m_nextLibrary( 0 )
39{
40 wxASSERT( m_table );
41 m_threadCount = std::max<size_t>( 1, std::thread::hardware_concurrency() );
42
43 m_returns.resize( m_threadCount );
44}
45
46
47
49{
50 Join();
51}
52
53
55{
56 for( size_t ii = 0; ii < m_threadCount; ++ii )
57 m_returns[ii] = std::async( std::launch::async, &SYMBOL_ASYNC_LOADER::worker, this );
58}
59
60
62{
63 for( size_t ii = 0; ii < m_threadCount; ++ii )
64 {
65 if( !m_returns[ii].valid() )
66 continue;
67
68 m_returns[ii].wait();
69
70 const std::vector<LOADED_PAIR>& ret = m_returns[ii].get();
71
72 if( m_output && !ret.empty() )
73 {
74 for( const LOADED_PAIR& pair : ret )
75 {
76 // Don't show libraries that had no power symbols
77 if( m_onlyPowerSymbols && pair.second.empty() )
78 continue;
79
80 // *Do* show empty libraries in the normal case
81 m_output->insert( pair );
82 }
83 }
84 }
85
86 return true;
87}
88
89
91{
92 return m_nextLibrary.load() >= m_nicknames.size();
93}
94
95
96std::vector<SYMBOL_ASYNC_LOADER::LOADED_PAIR> SYMBOL_ASYNC_LOADER::worker()
97{
98 std::vector<LOADED_PAIR> ret;
99
100 bool onlyPower = m_onlyPowerSymbols;
101
102 for( size_t libraryIndex = m_nextLibrary++; libraryIndex < m_nicknames.size();
103 libraryIndex = m_nextLibrary++ )
104 {
105 const wxString& nickname = m_nicknames[libraryIndex];
106
107 if( m_reporter )
108 m_reporter->AdvancePhase( wxString::Format( _( "Loading library %s..." ), nickname ) );
109
111 break;
112
113 LOADED_PAIR pair( nickname, {} );
114
115 try
116 {
117 m_table->LoadSymbolLib( pair.second, nickname, onlyPower );
118 ret.emplace_back( std::move( pair ) );
119 }
120 catch( const IO_ERROR& ioe )
121 {
122 wxString msg = wxString::Format( _( "Error loading symbol library %s.\n\n%s\n" ),
123 nickname, ioe.What() );
124
125 std::lock_guard<std::mutex> lock( m_errorMutex );
126 m_errors += msg;
127 }
128 }
129
130 return ret;
131}
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
Definition: ki_exception.h:76
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:30
A progress reporter interface for use in multi-threaded environments.
virtual bool IsCancelled() const =0
virtual void AdvancePhase()=0
Use the next available virtual zone of the dialog progress bar.
std::vector< LOADED_PAIR > worker()
< Worker job that loads libraries and returns a list of pairs of <nickname, loaded parts>
bool Done()
Returns a string containing any errors generated during the load.
std::vector< std::future< std::vector< LOADED_PAIR > > > m_returns
void Start()
Spins up threads to load all the libraries in m_nicknames.
std::unordered_map< wxString, std::vector< LIB_SYMBOL * > > * m_output
Progress reporter (may be null)
bool m_onlyPowerSymbols
Handle to map that will be filled with the loaded parts per library.
bool Join()
Finalizes the threads and combines the output into the target output map.
SYMBOL_LIB_TABLE * m_table
True if we are loading only power symbols.
SYMBOL_ASYNC_LOADER(const std::vector< wxString > &aNicknames, SYMBOL_LIB_TABLE *aTable, bool aOnlyPowerSymbols=false, std::unordered_map< wxString, std::vector< LIB_SYMBOL * > > *aOutput=nullptr, PROGRESS_REPORTER *aReporter=nullptr)
Constructs a loader for symbol libraries.
PROGRESS_REPORTER * m_reporter
std::pair< wxString, std::vector< LIB_SYMBOL * > > LOADED_PAIR
std::vector< wxString > m_nicknames
Handle to the symbol library table being loaded into.
std::atomic< size_t > m_nextLibrary
void LoadSymbolLib(std::vector< LIB_SYMBOL * > &aAliasList, const wxString &aNickname, bool aPowerSymbolsOnly=false)
#define _(s)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200