Commit e842d711 authored by Dick Hollenbeck's avatar Dick Hollenbeck

FIX: make LEGACY_PLUGIN re-entrant. extern "C" strtok_r() put conditionally into libcommon.

parent 40d0a145
...@@ -77,6 +77,7 @@ macro(perform_feature_checks) ...@@ -77,6 +77,7 @@ macro(perform_feature_checks)
check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP) check_symbol_exists(strcasecmp "strings.h" HAVE_STRCASECMP)
check_symbol_exists(strncasecmp "string.h" HAVE_STRNCASECMP) check_symbol_exists(strncasecmp "string.h" HAVE_STRNCASECMP)
check_symbol_exists(strncasecmp "strings.h" HAVE_STRNCASECMP) check_symbol_exists(strncasecmp "strings.h" HAVE_STRNCASECMP)
check_symbol_exists( strtok_r "string.h" HAVE_STRTOKR )
# Some platforms define malloc and free in malloc.h instead of stdlib.h. # Some platforms define malloc and free in malloc.h instead of stdlib.h.
check_symbol_exists(malloc "stdlib.h" MALLOC_IN_STDLIB_H) check_symbol_exists(malloc "stdlib.h" MALLOC_IN_STDLIB_H)
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#cmakedefine HAVE_STRNCASECMP #cmakedefine HAVE_STRNCASECMP
#cmakedefine HAVE_STRTOKR // spelled odly to differ from wx's similar test
// Handle platform differences in math.h // Handle platform differences in math.h
#cmakedefine HAVE_MATH_H #cmakedefine HAVE_MATH_H
......
...@@ -149,6 +149,10 @@ set(COMMON_SRCS ...@@ -149,6 +149,10 @@ set(COMMON_SRCS
zoom.cpp zoom.cpp
) )
if( NOT HAVE_STRTOKR )
set( COMMON_SRCS ${COMMON_SRCS} strtok_r.c )
endif()
enable_language(C CXX ASM) enable_language(C CXX ASM)
set_source_files_properties(system/fcontext.s PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp") set_source_files_properties(system/fcontext.s PROPERTIES COMPILE_FLAGS "-x assembler-with-cpp")
......
...@@ -53,9 +53,20 @@ ...@@ -53,9 +53,20 @@
/* /*
wxString ToHTML( const IO_ERROR** aList, int aCount ) static wxString ToHTMLFragment( const IO_ERROR* aDerivative )
{ {
wxString msg = wxT( "<table>" ); @todo
1) change up IO_ERROR so it keeps linenumbers, source file name and
error message in separate strings.
2) Add a summarizing virtual member like
virtual wxString What()
to combine all portions of an IO_ERROR's text into a single wxString.
3) Do same for PARSE_ERROR.
4) Add a "reason or error category" to IO_ERROR and thereby also PARSE_ERROR?
msg += " msg += "
...@@ -175,11 +186,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames ) ...@@ -175,11 +186,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames )
#else // yes USE_FP_LIB_TABLE, by all means: #else // yes USE_FP_LIB_TABLE, by all means:
#if USE_WORKER_THREADS //---------------------------------------------------------------------
#define USE_WORKER_THREADS 1 // 1:yes, 0:no. use worker threads to load libraries
#define JOBZ 6 // no. libraries per worker thread. It takes about #define JOBZ 6 // no. libraries per worker thread. It takes about
// a second to load a GITHUB library, so assigning // a second to load a GITHUB library, so assigning
// this no. libraries to each thread should give a little // this no. libraries to each thread should give a little
...@@ -191,7 +197,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames ) ...@@ -191,7 +197,6 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( wxArrayString& aFootprintLibNames )
// in progress will still pile on for a bit. e.g. if 9 threads // in progress will still pile on for a bit. e.g. if 9 threads
// expect 9 greater than this. // expect 9 greater than this.
void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ ) void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ )
{ {
//DBG(printf( "%s: first:'%s' count:%d\n", __func__, (char*) TO_UTF8( *aNicknameList ), aJobZ );) //DBG(printf( "%s: first:'%s' count:%d\n", __func__, (char*) TO_UTF8( *aNicknameList ), aJobZ );)
...@@ -225,7 +230,7 @@ void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ ) ...@@ -225,7 +230,7 @@ void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ )
} }
catch( const PARSE_ERROR& pe ) catch( const PARSE_ERROR& pe )
{ {
// push_back is not thread safe, use the lock the MUTEX. // m_errors.push_back is not thread safe, lock its MUTEX.
MUTLOCK lock( m_errors_lock ); MUTLOCK lock( m_errors_lock );
++m_error_count; // modify only under lock ++m_error_count; // modify only under lock
...@@ -244,7 +249,7 @@ void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ ) ...@@ -244,7 +249,7 @@ void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ )
// worker threads. // worker threads.
catch( const std::exception& se ) catch( const std::exception& se )
{ {
// this is a round about way to do this, but who knows what THROW_IO_ERROR() // This is a round about way to do this, but who knows what THROW_IO_ERROR()
// may be tricked out to do someday, keep it in the game. // may be tricked out to do someday, keep it in the game.
try try
{ {
...@@ -261,8 +266,6 @@ void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ ) ...@@ -261,8 +266,6 @@ void FOOTPRINT_LIST::loader_job( const wxString* aNicknameList, int aJobZ )
} }
} }
#endif // USE_WORKER_THREADS ---------------------------------------------------
bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname ) bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* aNickname )
{ {
...@@ -275,120 +278,74 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a ...@@ -275,120 +278,74 @@ bool FOOTPRINT_LIST::ReadFootprintFiles( FP_LIB_TABLE* aTable, const wxString* a
m_errors.clear(); m_errors.clear();
m_list.clear(); m_list.clear();
std::vector< wxString > nicknames; if( aNickname )
// single footprint
loader_job( aNickname, 1 );
else
{
std::vector< wxString > nicknames;
if( !aNickname )
// do all of them // do all of them
nicknames = aTable->GetLogicalLibs(); nicknames = aTable->GetLogicalLibs();
else
// single footprint
nicknames.push_back( *aNickname );
#if USE_WORKER_THREADS #if USE_WORKER_THREADS
// Something which will not invoke a thread copy constructor, one of many ways obviously: // Something which will not invoke a thread copy constructor, one of many ways obviously:
typedef boost::ptr_vector< boost::thread > MYTHREADS; typedef boost::ptr_vector< boost::thread > MYTHREADS;
MYTHREADS threads; MYTHREADS threads;
// Give each thread JOBZ nicknames to process. The last portion of, or if the entire // Give each thread JOBZ nicknames to process. The last portion of, or if the entire
// size() is small, I'll do myself. // size() is small, I'll do myself.
for( unsigned i=0; i<nicknames.size(); ) for( unsigned i=0; i<nicknames.size(); )
{
if( m_error_count >= NTOLERABLE_ERRORS )
{ {
// abort the remaining nicknames. if( m_error_count >= NTOLERABLE_ERRORS )
retv = false; {
break; // abort the remaining nicknames.
} retv = false;
break;
}
int jobz = JOBZ; int jobz = JOBZ;
if( i + jobz >= nicknames.size() ) if( i + jobz >= nicknames.size() )
{ {
jobz = nicknames.size() - i; jobz = nicknames.size() - i;
// Only a little bit to do, I'll do it myself, on current thread.
loader_job( &nicknames[i], jobz );
}
else
{
// Delegate the job to a worker thread created here.
threads.push_back( new boost::thread( &FOOTPRINT_LIST::loader_job,
this, &nicknames[i], jobz ) );
}
// Only a little bit to do, I'll do it myself, on current thread. i += jobz;
// This is the path for a single footprint also.
loader_job( &nicknames[i], jobz );
} }
else
// Wait for all the worker threads to complete, it does not matter in what order
// we wait for them as long as a full sweep is made. Think of the great race,
// everyone must finish.
for( unsigned i=0; i<threads.size(); ++i )
{ {
// Delegate the job to a worker thread created here. threads[i].join();
threads.push_back( new boost::thread( &FOOTPRINT_LIST::loader_job,
this, &nicknames[i], jobz ) );
} }
#else
loader_job( &nicknames[0], nicknames.size() );
#endif
i += jobz; m_list.sort();
}
// Wait for all the worker threads to complete, it does not matter in what order
// we wait for them as long as a full sweep is made. Think of the great race,
// everyone must finish.
for( unsigned i=0; i<threads.size(); ++i )
{
threads[i].join();
} }
m_list.sort();
// The result of this function can be a blend of successes and failures, whose // The result of this function can be a blend of successes and failures, whose
// mix is given by the Count()s of the two lists. The return value indicates whether // mix is given by the Count()s of the two lists. The return value indicates whether
// an abort occurred, even true does not necessarily mean full success, although // an abort occurred, even true does not necessarily mean full success, although
// false definitely means failure. // false definitely means failure.
return retv; return retv;
#else
bool retv = true;
for( unsigned ii = 0; ii < nicknames.size(); ii++ )
{
const wxString& nickname = nicknames[ii];
try
{
wxArrayString fpnames = aTable->FootprintEnumerate( nickname );
for( unsigned i=0; i<fpnames.GetCount(); ++i )
{
std::auto_ptr<MODULE> m( aTable->FootprintLoad( nickname, fpnames[i] ) );
// we're loading what we enumerated, all must be there.
wxASSERT( m.get() );
FOOTPRINT_INFO* fpinfo = new FOOTPRINT_INFO();
fpinfo->SetNickname( nickname );
fpinfo->m_Module = fpnames[i];
fpinfo->m_padCount = m->GetPadCount( MODULE::DO_NOT_INCLUDE_NPTH );
fpinfo->m_KeyWord = m->GetKeywords();
fpinfo->m_Doc = m->GetDescription();
AddItem( fpinfo );
}
}
catch( const PARSE_ERROR& pe )
{
m_errors.push_back( new IO_ERROR( pe ) );
retv = false;
}
catch( const IO_ERROR& ioe )
{
m_errors.push_back( new IO_ERROR( ioe ) );
retv = false;
}
}
m_list.sort();
return retv;
#endif
} }
#endif // USE_FP_LIB_TABLE #endif // USE_FP_LIB_TABLE
......
...@@ -164,4 +164,9 @@ wxString GetIllegalFileNameWxChars(); ...@@ -164,4 +164,9 @@ wxString GetIllegalFileNameWxChars();
*/ */
bool ReplaceIllegalFileNameChars( std::string* aName ); bool ReplaceIllegalFileNameChars( std::string* aName );
#ifndef HAVE_STRTOKR
// common/strtok_r.c optionally:
extern "C" char* strtok_r( char* str, const char* delim, char** nextp );
#endif
#endif // KICAD_STRING_H_ #endif // KICAD_STRING_H_
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment