Extend the id reference count storage to use an overflow hash map for the ids
used more than 254 times. This allows to use the same id an arbitrarily large
number of times.
Closes #13618.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@69682
c3d73ce0-8a6f-49c7-b76d-
6d57e0e08775
- Added wxDataViewCustomRenderer::ActivateCell().
- Add "checked" property for toolbar tool elements in XRC.
- Allow customization of the locations where persistent settings are stored.
- Added wxDataViewCustomRenderer::ActivateCell().
- Add "checked" property for toolbar tool elements in XRC.
- Allow customization of the locations where persistent settings are stored.
+- Restore support for reusing ids more than 254 times (Armel Asselin).
#include "wx/intl.h"
#endif //WX_PRECOMP
#include "wx/intl.h"
#endif //WX_PRECOMP
+#include "wx/hashmap.h"
+
// Not needed, included in defs.h
// #include "wx/windowid.h"
// Not needed, included in defs.h
// #include "wx/windowid.h"
// meanwhile
static const wxUint8 ID_FREE = 0;
static const wxUint8 ID_STARTCOUNT = 1;
// meanwhile
static const wxUint8 ID_FREE = 0;
static const wxUint8 ID_STARTCOUNT = 1;
-static const wxUint8 ID_MAXCOUNT = 254;
+static const wxUint8 ID_COUNTTOOLARGE = 254;
static const wxUint8 ID_RESERVED = 255;
static const wxUint8 ID_RESERVED = 255;
+// we use a two level count, most IDs will be used less than ID_COUNTTOOLARGE-1
+// thus we store their count directly in this array, however when the same ID
+// is reused a great number of times (more than or equal to ID_COUNTTOOLARGE),
+// the hash map stores the actual count
wxUint8 gs_autoIdsRefCount[wxID_AUTO_HIGHEST - wxID_AUTO_LOWEST + 1] = { 0 };
wxUint8 gs_autoIdsRefCount[wxID_AUTO_HIGHEST - wxID_AUTO_LOWEST + 1] = { 0 };
+// NB: this variable is allocated (again) only when an ID gets at least
+// ID_COUNTTOOLARGE refs, and is freed when the latest entry in the map gets
+// freed. The cell storing the count for an ID is freed only when its count
+// gets to zero (not when it goes below ID_COUNTTOOLARGE, so as to avoid
+// degenerate cases)
+wxLongToLongHashMap *gs_autoIdsLargeRefCount = NULL;
+
// this is an optimization used until we wrap around wxID_AUTO_HIGHEST: if this
// value is < wxID_AUTO_HIGHEST we know that we haven't wrapped yet and so can
// allocate the ids simply by incrementing it
// this is an optimization used until we wrap around wxID_AUTO_HIGHEST: if this
// value is < wxID_AUTO_HIGHEST we know that we haven't wrapped yet and so can
// allocate the ids simply by incrementing it
wxT("invalid id range"));
winid -= wxID_AUTO_LOWEST;
wxT("invalid id range"));
winid -= wxID_AUTO_LOWEST;
- return gs_autoIdsRefCount[winid];
+ int refCount = gs_autoIdsRefCount[winid];
+ if (refCount == ID_COUNTTOOLARGE)
+ refCount = (*gs_autoIdsLargeRefCount)[winid];
+ return refCount;
}
// Increase the count for an id
}
// Increase the count for an id
winid -= wxID_AUTO_LOWEST;
winid -= wxID_AUTO_LOWEST;
- wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_MAXCOUNT, wxT("id count at max"));
wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_FREE, wxT("id should first be reserved"));
if(gs_autoIdsRefCount[winid] == ID_RESERVED)
wxCHECK_RET(gs_autoIdsRefCount[winid] != ID_FREE, wxT("id should first be reserved"));
if(gs_autoIdsRefCount[winid] == ID_RESERVED)
gs_autoIdsRefCount[winid] = ID_STARTCOUNT;
gs_autoIdsRefCount[winid] = ID_STARTCOUNT;
+ }
+ else if (gs_autoIdsRefCount[winid] >= ID_COUNTTOOLARGE-1)
+ {
+ if (gs_autoIdsRefCount[winid] == ID_COUNTTOOLARGE-1)
+ {
+ // we need to allocate a cell, and maybe the hash map itself
+ if (!gs_autoIdsLargeRefCount)
+ gs_autoIdsLargeRefCount = new wxLongToLongHashMap;
+ (*gs_autoIdsLargeRefCount)[winid] = ID_COUNTTOOLARGE-1;
+
+ gs_autoIdsRefCount[winid] = ID_COUNTTOOLARGE;
+ }
+ ++(*gs_autoIdsLargeRefCount)[winid];
+ }
gs_autoIdsRefCount[winid]++;
gs_autoIdsRefCount[winid]++;
wxLogTrace(wxTRACE_WINDOWID, wxT("Increasing ref count of ID %d to %d"),
wxLogTrace(wxTRACE_WINDOWID, wxT("Increasing ref count of ID %d to %d"),
- winid + wxID_AUTO_LOWEST, gs_autoIdsRefCount[winid]);
+ winid + wxID_AUTO_LOWEST, GetIdRefCount(winid + wxID_AUTO_LOWEST));
}
// Decrease the count for an id
}
// Decrease the count for an id
wxFAIL_MSG(wxT("reserve id being decreased"));
gs_autoIdsRefCount[winid] = ID_FREE;
}
wxFAIL_MSG(wxT("reserve id being decreased"));
gs_autoIdsRefCount[winid] = ID_FREE;
}
+ else if(gs_autoIdsRefCount[winid] == ID_COUNTTOOLARGE)
+ {
+ long &largeCount = (*gs_autoIdsLargeRefCount)[winid];
+ --largeCount;
+ if (largeCount == 0)
+ {
+ gs_autoIdsLargeRefCount->erase (winid);
+ gs_autoIdsRefCount[winid] = ID_FREE;
+
+ if (gs_autoIdsLargeRefCount->empty())
+ wxDELETE (gs_autoIdsLargeRefCount);
+ }
+ }
else
gs_autoIdsRefCount[winid]--;
wxLogTrace(wxTRACE_WINDOWID, wxT("Decreasing ref count of ID %d to %d"),
else
gs_autoIdsRefCount[winid]--;
wxLogTrace(wxTRACE_WINDOWID, wxT("Decreasing ref count of ID %d to %d"),
- winid + wxID_AUTO_LOWEST, gs_autoIdsRefCount[winid]);
+ winid + wxID_AUTO_LOWEST, GetIdRefCount(winid + wxID_AUTO_LOWEST));
}
#else // wxUSE_AUTOID_MANAGEMENT
}
#else // wxUSE_AUTOID_MANAGEMENT