Added new module, m_oset, which provides a generic data structure, OSet,
which is a sorted set with no duplicates.  This is derived from
m_skiplist, which it will hopefully replace.  The interface has the
following improvements:

- Avoided all mention of how the data structure is implemented in the
  interface, so it could be replaced with another data structure without
  changing external code.
- Two kinds of comparison:  fast -- use the first word of each element
  for comparison;  slow -- use a custom function.  The custom function
  compares a key with an element, so non-overlapping interval lists can
  be supported easily.  m_skiplist only supports the slow variant, and it
  makes things almost 2x faster.
- Users pass in malloc() and free() functions, so m_oset.c it doesn't
  rely on any particular allocator.
- It has a Destroy() function which will deallocate all the nodes.
- It allows variable-sized nodes.
- No static constructor;  I needed the flexibility of being able to
  execute arbitrary code in the constructor.  This also means no type
  internals are exposed.

No part of Valgrind actually uses OSet yet, although I've privately
converted several data structures, and so I'm confident that the
interface is basically sound.  Some functions may be added later.
  
The implementation uses AVL trees, and has the following
characteristics:

- Lookup is much faster than for skiplists -- around 3x.  This is
  because the inner lookup loop is much tighter.
- Insertion and removal is similar speed to skiplists, maybe a little
  slower, but there's still some fat to be trimmed.
- The code is a bit longer and more complex than the skiplist code.

This was intended to replace the need for the VgHashTable type.  But my
experiments have shown that VgHashTable is really fast, faster than both
AVL trees and skiplists in all but extreme cases (eg. if the hashtable
becomes way too full):  insertion takes constant time, because you always
prepend to chains;  lookup depends on chain length, but the inner loop
is so tight that you need about 20 elements per chain before it gets
worse than the AVL tree;  removal is similar to lookup.  And because
insertion uses prepending, any locality in accesses will help things.  If
VgHashTable had its interface cleaned up to look like OSet's, and was made
to auto-resize when it got too full, it might be a better OSet (although
it's not sorted).

So, it's currently unclear exactly how the AVL tree OSet will be used.
The skiplist could be converted to the new interface (I have a 90%
complete version which I used in the comparison experiments).  If
VgHashTable was converted to the same interface (or as close as
possible) it would make direct comparison of important places (eg.
Memcheck's malloc_lists) simple.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4410 a5019735-40e9-0310-863c-91ae7b9d1cf9
4 files changed