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/defs.h"
#include "wx/string.h" #include "wx/string.h"
WXDLLIMPEXP_BASE int wxCMPFUNC_CONV wxStringSortAscending(wxString*, wxString*);
WXDLLIMPEXP_BASE int wxCMPFUNC_CONV wxStringSortDescending(wxString*, wxString*);
#if wxUSE_STL #if wxUSE_STL
#include "wx/dynarray.h" #include "wx/dynarray.h"
@@ -177,7 +174,7 @@ public:
// sort array elements in alphabetical order (or reversed alphabetical // sort array elements in alphabetical order (or reversed alphabetical
// order if reverseOrder parameter is true) // order if reverseOrder parameter is true)
void Sort(bool reverseOrder = false); 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(CompareFunction compareFunction);
void Sort(CompareFunction2 compareFunction); void Sort(CompareFunction2 compareFunction);
@@ -299,8 +296,6 @@ protected:
private: private:
void Grow(size_t nIncrement = 0); // makes array bigger if needed 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 size_t m_nSize, // current size of the array
m_nCount; // current number of elements m_nCount; // current number of elements

View File

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