KiCad PCB EDA Suite
Loading...
Searching...
No Matches
footprint_info_impl.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) 2011 Jean-Pierre Charras, <[email protected]>
5 * Copyright (C) 2013-2016 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software: you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22
23#include <footprint_info_impl.h>
24
26#include <footprint.h>
27#include <footprint_info.h>
29#include <kiway.h>
30#include <lib_id.h>
31#include <progress_reporter.h>
32#include <string_utils.h>
33#include <thread_pool.h>
34
35
37{
38 FOOTPRINT_LIBRARY_ADAPTER* adapter = m_owner->GetAdapter();
39 wxCHECK( adapter, /* void */ );
40
41 try
42 {
43 std::unique_ptr<FOOTPRINT> footprint( adapter->LoadFootprint( m_nickname, m_fpname, false ) );
44
45 if( footprint == nullptr ) // Should happen only with malformed/broken libraries
46 {
47 m_pad_count = 0;
49 }
50 else
51 {
52 m_pad_count = footprint->GetPadCount( DO_NOT_INCLUDE_NPTH );
53 m_unique_pad_count = footprint->GetUniquePadCount( DO_NOT_INCLUDE_NPTH );
54 m_keywords = footprint->GetKeywords();
55 m_doc = footprint->GetLibDescription();
56 }
57 }
58 catch( const IO_ERROR& ioe )
59 {
60 // Store error in the owner's error list for later display
61 if( m_owner )
62 m_owner->PushError( std::make_unique<IO_ERROR>( ioe ) );
63
64 m_pad_count = 0;
66 }
67
68 m_loaded = true;
69}
70
71
73{
74 std::unique_lock<std::mutex> lock( m_loadInProgress );
75
76 m_list.clear();
78}
79
80
82 const wxString& aLibName,
83 const std::function<void( const std::vector<LIB_TREE_ITEM*>& )>& aCallback )
84{
85 std::unique_lock<std::mutex> lock( m_loadInProgress );
86
87 std::vector<LIB_TREE_ITEM*> libList;
88 const auto& fullList = GetList();
89
90 FOOTPRINT_INFO_IMPL dummy( aLibName, wxEmptyString );
91 std::unique_ptr<FOOTPRINT_INFO> dummyPtr( &dummy );
92
93 auto libBounds = std::equal_range( fullList.begin(), fullList.end(), dummyPtr,
94 []( const std::unique_ptr<FOOTPRINT_INFO>& a, const std::unique_ptr<FOOTPRINT_INFO>& b )
95 {
96 if( !a || !b )
97 return false;
98
99 return StrNumCmp( a->GetLibNickname(), b->GetLibNickname(), false ) < 0;
100 } );
101
102 dummyPtr.release();
103
104 for( auto i = libBounds.first; i != libBounds.second; ++i )
105 {
106 if( *i )
107 libList.push_back( i->get() );
108 }
109
110 aCallback( libList );
111}
112
113
114bool FOOTPRINT_LIST_IMPL::CatchErrors( const std::function<void()>& aFunc )
115{
116 try
117 {
118 aFunc();
119 }
120 catch( const IO_ERROR& ioe )
121 {
122 m_errors.move_push( std::make_unique<IO_ERROR>( ioe ) );
123 return false;
124 }
125 catch( const std::exception& se )
126 {
127 // This is a round about way to do this, but who knows what THROW_IO_ERROR()
128 // may be tricked out to do someday, keep it in the game.
129 try
130 {
131 THROW_IO_ERROR( se.what() );
132 }
133 catch( const IO_ERROR& ioe )
134 {
135 m_errors.move_push( std::make_unique<IO_ERROR>( ioe ) );
136 }
137
138 return false;
139 }
140
141 return true;
142}
143
144
146 PROGRESS_REPORTER* aProgressReporter )
147{
148 std::unique_lock<std::mutex> lock( m_loadInProgress );
149
150 m_adapter = aAdapter;
151
152 // AsyncLoad() must be called before BlockUntilLoaded() to ensure library loading is started.
153 // This is necessary when the footprint chooser is opened from contexts that don't preload
154 // footprint libraries (e.g., eeschema).
155 m_adapter->AsyncLoad();
156 m_adapter->BlockUntilLoaded();
157
158 long long int generatedTimestamp = 0;
159
160 if( !CatchErrors( [&]()
161 {
162 generatedTimestamp = aAdapter->GenerateTimestamp( aNickname );
163 } ) )
164 {
165 return false;
166 }
167
168 if( generatedTimestamp == m_list_timestamp )
169 return true;
170
171 // Disable KIID generation: not needed for library parts; sometimes very slow
172 KIID_NIL_SET_RESET reset_kiid;
173
174 m_progress_reporter = aProgressReporter;
175
176 m_cancelled = false;
177
178 // Clear data before reading files
179 m_errors.clear();
180 m_list.clear();
181 m_queue.clear();
182
183 if( aNickname )
184 {
185 m_queue.push( *aNickname );
186 }
187 else
188 {
189 for( const wxString& nickname : aAdapter->GetLibraryNames() )
190 m_queue.push( nickname );
191 }
192
194 {
195 m_progress_reporter->SetMaxProgress( (int) m_queue.size() );
196 m_progress_reporter->Report( _( "Loading footprints..." ) );
197 }
198
200
202 m_progress_reporter->AdvancePhase();
203
204 if( m_cancelled )
205 m_list_timestamp = 0; // God knows what we got before we were canceled
206 else
207 m_list_timestamp = generatedTimestamp;
208
209 return m_errors.empty();
210}
211
212
214{
215 // Parse the footprints in parallel.
216
219 size_t num_elements = m_queue.size();
220 std::vector<std::future<size_t>> returns( num_elements );
221
222 auto fp_thread =
223 [ this, &queue_parsed ]() -> size_t
224 {
225 // Each thread pool worker needs its own KIID_NIL_SET_RESET since g_createNilUuids
226 // is thread_local. This prevents generating real UUIDs for temporary footprint data.
227 KIID_NIL_SET_RESET reset_kiid;
228
229 wxString nickname;
230
231 if( m_cancelled || !m_queue.pop( nickname ) )
232 return 0;
233
234 std::vector<wxString> fpnames;
235
237 [&]()
238 {
239 fpnames = m_adapter->GetFootprintNames( nickname );
240 } );
241
242 for( wxString fpname : fpnames )
243 {
245 [&]()
246 {
247 auto* fpinfo = new FOOTPRINT_INFO_IMPL( this, nickname, fpname );
248 queue_parsed.move_push( std::unique_ptr<FOOTPRINT_INFO>( fpinfo ) );
249 } );
250
251 if( m_cancelled )
252 return 0;
253 }
254
256 m_progress_reporter->AdvanceProgress();
257
258 return 1;
259 };
260
261 for( size_t ii = 0; ii < num_elements; ++ii )
262 returns[ii] = tp.submit_task( fp_thread );
263
264 for( const std::future<size_t>& ret : returns )
265 {
266 std::future_status status = ret.wait_for( std::chrono::milliseconds( 250 ) );
267
268 while( status != std::future_status::ready )
269 {
271 m_progress_reporter->KeepRefreshing();
272
273 status = ret.wait_for( std::chrono::milliseconds( 250 ) );
274 }
275 }
276
277 std::unique_ptr<FOOTPRINT_INFO> fpi;
278
279 while( queue_parsed.pop( fpi ) )
280 m_list.push_back( std::move( fpi ) );
281
282 std::sort( m_list.begin(), m_list.end(),
283 []( std::unique_ptr<FOOTPRINT_INFO> const& lhs,
284 std::unique_ptr<FOOTPRINT_INFO> const& rhs ) -> bool
285 {
286 if( !lhs || !rhs )
287 return false;
288
289 return *lhs < *rhs;
290 } );
291}
292
293
virtual void load() override
lazily load stuff not filled in by constructor. This may throw IO_ERRORS.
wxString m_doc
Footprint description.
wxString m_fpname
Module name.
wxString m_keywords
Footprint keywords.
unsigned m_unique_pad_count
Number of unique pads.
unsigned m_pad_count
Number of pads.
FOOTPRINT_LIST * m_owner
provides access to FP_LIB_TABLE
wxString m_nickname
library as known in FP_LIB_TABLE
An interface to the global shared library manager that is schematic-specific and linked to one projec...
FOOTPRINT * LoadFootprint(const wxString &aNickname, const wxString &aName, bool aKeepUUID)
Load a FOOTPRINT having aName from the library given by aNickname.
long long GenerateTimestamp(const wxString *aNickname)
Generates a filesystem timestamp / hash value for library(ies)
bool ReadFootprintFiles(FOOTPRINT_LIBRARY_ADAPTER *aAdapter, const wxString *aNickname=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr) override
Read all the footprints provided by the combination of aTable and aNickname.
void WithFootprintsForLibrary(const wxString &aLibName, const std::function< void(const std::vector< LIB_TREE_ITEM * > &)> &aCallback)
Execute a callback with thread-safe access to the footprints for a library.
std::atomic_bool m_cancelled
SYNC_QUEUE< wxString > m_queue
bool CatchErrors(const std::function< void()> &aFunc)
Call aFunc, pushing any IO_ERRORs and std::exceptions it throws onto m_errors.
PROGRESS_REPORTER * m_progress_reporter
SYNC_QUEUE< std::unique_ptr< IO_ERROR > > m_errors
some can be PARSE_ERRORs also
std::vector< std::unique_ptr< FOOTPRINT_INFO > > m_list
FOOTPRINT_LIBRARY_ADAPTER * m_adapter
no ownership
const std::vector< std::unique_ptr< FOOTPRINT_INFO > > & GetList() const
Was forced to add this by modview_frame.cpp.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
RAII class to safely set/reset nil KIIDs for use in footprint/symbol loading.
Definition kiid.h:242
std::vector< wxString > GetLibraryNames() const
Returns a list of library nicknames that are available (skips any that failed to load)
A progress reporter interface for use in multi-threaded environments.
Synchronized, locking queue.
Definition sync_queue.h:32
bool pop(T &aReceiver)
Pop a value if the queue into the provided variable.
Definition sync_queue.h:63
void move_push(T &&aValue)
Move a value onto the queue.
Definition sync_queue.h:50
#define _(s)
@ DO_NOT_INCLUDE_NPTH
Definition footprint.h:73
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
std::vector< FAB_LAYER_COLOR > dummy
thread_pool & GetKiCadThreadPool()
Get a reference to the current thread pool.
static thread_pool * tp
BS::priority_thread_pool thread_pool
Definition thread_pool.h:31