use std::sort() instead of qsort() to implement wxArrayString::Sort(), this makes it thread-safe without any extra hacks and also makes the code simpler

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@55317 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2008-08-27 19:40:20 +00:00
parent 0d0b57acec
commit eaf6da0746
2 changed files with 46 additions and 72 deletions

View File

@@ -15,9 +15,6 @@
#include "wx/defs.h"
#include "wx/string.h"
WXDLLIMPEXP_BASE int wxCMPFUNC_CONV wxStringSortAscending(wxString*, wxString*);
WXDLLIMPEXP_BASE int wxCMPFUNC_CONV wxStringSortDescending(wxString*, wxString*);
#if wxUSE_STL
#include "wx/dynarray.h"
@@ -177,7 +174,7 @@ public:
// sort array elements in alphabetical order (or reversed alphabetical
// order if reverseOrder parameter is true)
void Sort(bool reverseOrder = false);
// sort array elements using specified comparaison function
// sort array elements using specified comparison function
void Sort(CompareFunction compareFunction);
void Sort(CompareFunction2 compareFunction);
@@ -299,8 +296,6 @@ protected:
private:
void Grow(size_t nIncrement = 0); // makes array bigger if needed
void DoSort(); // common part of all Sort() variants
size_t m_nSize, // current size of the array
m_nCount; // current number of elements

View File

@@ -21,7 +21,11 @@
#endif
#include "wx/arrstr.h"
#include "wx/thread.h"
#include "wx/beforestd.h"
#include <algorithm>
#include <functional>
#include "wx/afterstd.h"
// ============================================================================
// ArrayString
@@ -138,7 +142,7 @@ void wxArrayString::Grow(size_t nIncrement)
pNew[j] = m_pItems[j];
// delete old memory (but do not release the strings!)
wxDELETEA(m_pItems);
delete [] m_pItems;
m_pItems = pNew;
}
@@ -163,7 +167,7 @@ void wxArrayString::Clear()
// dtor
wxArrayString::~wxArrayString()
{
wxDELETEA(m_pItems);
delete [] m_pItems;
}
void wxArrayString::reserve(size_t nSize)
@@ -385,74 +389,61 @@ void wxArrayString::assign(const_iterator first, const_iterator last)
// sorting
// ----------------------------------------------------------------------------
// we can only sort one array at a time with the quick-sort based
// implementation
#if wxUSE_THREADS
// need a critical section to protect access to gs_compareFunction and
// gs_sortAscending variables
static wxCriticalSection gs_critsectStringSort;
#endif // wxUSE_THREADS
// function to use for string comparaison
static wxArrayString::CompareFunction gs_compareFunction = NULL;
// if we don't use the compare function, this flag tells us if we sort the
// array in ascending or descending order
static bool gs_sortAscending = true;
// function which is called by quick sort
extern "C" int wxC_CALLING_CONV // LINKAGEMODE
wxStringCompareFunction(const void *first, const void *second)
// we need an adaptor as our predicates use qsort() convention and so return
// negative, null or positive value depending on whether the first item is less
// than, equal to or greater than the other one while we need a real boolean
// predicate now that we use std::sort()
struct wxSortPredicateAdaptor
{
wxString *strFirst = (wxString *)first;
wxString *strSecond = (wxString *)second;
if ( gs_compareFunction ) {
return gs_compareFunction(*strFirst, *strSecond);
wxSortPredicateAdaptor(wxArrayString::CompareFunction compareFunction)
: m_compareFunction(compareFunction)
{
}
else {
// maybe we should use wxStrcoll
int result = strFirst->Cmp(*strSecond);
return gs_sortAscending ? result : -result;
bool operator()(const wxString& first, const wxString& second) const
{
return (*m_compareFunction)(first, second) < 0;
}
}
// sort array elements using passed comparaison function
wxArrayString::CompareFunction m_compareFunction;
};
void wxArrayString::Sort(CompareFunction compareFunction)
{
wxCRIT_SECT_LOCKER(lockCmpFunc, gs_critsectStringSort);
wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") );
wxASSERT( !gs_compareFunction ); // must have been reset to NULL
gs_compareFunction = compareFunction;
DoSort();
// reset it to NULL so that Sort(bool) will work the next time
gs_compareFunction = NULL;
std::sort(m_pItems, m_pItems + m_nCount,
wxSortPredicateAdaptor(compareFunction));
}
extern "C"
struct wxSortPredicateAdaptor2
{
typedef int (wxC_CALLING_CONV * wxStringCompareFn)(const void *first,
const void *second);
}
wxSortPredicateAdaptor2(wxArrayString::CompareFunction2 compareFunction)
: m_compareFunction(compareFunction)
{
}
bool operator()(const wxString& first, const wxString& second) const
{
return (*m_compareFunction)(const_cast<wxString *>(&first),
const_cast<wxString *>(&second)) < 0;
}
wxArrayString::CompareFunction2 m_compareFunction;
};
void wxArrayString::Sort(CompareFunction2 compareFunction)
{
qsort(m_pItems, m_nCount, sizeof(wxString), (wxStringCompareFn)compareFunction);
std::sort(m_pItems, m_pItems + m_nCount,
wxSortPredicateAdaptor2(compareFunction));
}
void wxArrayString::Sort(bool reverseOrder)
{
Sort(reverseOrder ? wxStringSortDescending : wxStringSortAscending);
}
void wxArrayString::DoSort()
{
wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") );
qsort(m_pItems, m_nCount, sizeof(wxString), wxStringCompareFunction);
if ( reverseOrder )
std::sort(m_pItems, m_pItems + m_nCount, std::greater<wxString>());
else // normal sort
std::sort(m_pItems, m_pItems + m_nCount);
}
bool wxArrayString::operator==(const wxArrayString& a) const
@@ -471,18 +462,6 @@ bool wxArrayString::operator==(const wxArrayString& a) const
#endif // !wxUSE_STL
int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2)
{
return s1->Cmp(*s2);
}
int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2)
{
return -s1->Cmp(*s2);
}
// ===========================================================================
// wxJoin and wxSplit
// ===========================================================================