1
0
Fork 0
arangodb/lib/BasicsC/skip-list.h

246 lines
10 KiB
C

////////////////////////////////////////////////////////////////////////////////
/// @brief generic skip list implementation
///
/// @file
///
/// DISCLAIMER
///
/// Copyright 2014 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Max Neunhoeffer
/// @author Copyright 2014, ArangoDB GmbH, Cologne, Germany
/// @author Copyright 2013-2013, triAGENS GmbH, Cologne, Germany
////////////////////////////////////////////////////////////////////////////////
#ifndef ARANGODB_BASICS_C_SKIP__LIST_H
#define ARANGODB_BASICS_C_SKIP__LIST_H 1
#include "BasicsC/common.h"
#ifdef __cplusplus
extern "C" {
#endif
// We will probably never see more than 2^48 documents in a skip list
#define TRI_SKIPLIST_MAX_HEIGHT 48
// -----------------------------------------------------------------------------
// --SECTION-- SKIP LIST
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
// --SECTION-- public types
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief type of a skiplist node
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_skiplist_node_s {
struct TRI_skiplist_node_s** next;
int height;
void *doc;
} TRI_skiplist_node_t;
////////////////////////////////////////////////////////////////////////////////
/// @brief two possibilities for comparison, see below
////////////////////////////////////////////////////////////////////////////////
typedef enum {
TRI_CMP_PREORDER,
TRI_CMP_TOTORDER
}
TRI_cmp_type_e;
////////////////////////////////////////////////////////////////////////////////
/// @brief type of a function pointer to a comparison function for a skiplist.
///
/// The last argument is called preorder. If true then the comparison
/// function must implement a preorder (reflexive and transitive).
/// If preorder is false, then a proper total order must be
/// implemented by the comparison function. The proper total order
/// must refine the preorder in the sense that a < b in the proper order
/// implies a <= b in the preorder.
/// The first argument is a data pointer which may contain arbitrary
/// infrastructure needed for the comparison. See cmpdata field in the
/// skiplist type.
/// The cmp_key_elm variant compares a key with an element using the preorder.
/// The first argument is a data pointer as above, the second is a pointer
/// to the key and the third is a pointer to an element.
////////////////////////////////////////////////////////////////////////////////
typedef int (*TRI_skiplist_cmp_elm_elm_t)(void*, void*, void*, TRI_cmp_type_e);
typedef int (*TRI_skiplist_cmp_key_elm_t)(void*, void*, void*);
////////////////////////////////////////////////////////////////////////////////
/// @brief Type of a pointer to a function that is called whenever a
/// document is removed from a skiplist.
////////////////////////////////////////////////////////////////////////////////
typedef void (*TRI_skiplist_free_func_t)(void*);
////////////////////////////////////////////////////////////////////////////////
/// @brief type of a skiplist
////////////////////////////////////////////////////////////////////////////////
typedef struct TRI_skiplist_s {
TRI_skiplist_node_t* start;
TRI_skiplist_cmp_elm_elm_t cmp_elm_elm;
TRI_skiplist_cmp_key_elm_t cmp_key_elm;
void* cmpdata; // will be the first argument
TRI_skiplist_free_func_t free;
bool unique; // indicates whether multiple entries that
// are equal in the preorder are allowed in
uint64_t nrUsed;
size_t _memoryUsed;
} TRI_skiplist_t;
// -----------------------------------------------------------------------------
// --SECTION-- constructors and destructors
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief creates a new skiplist
///
/// Returns NULL if allocation fails and a pointer to the skiplist
/// otherwise.
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_t* TRI_InitSkipList (TRI_skiplist_cmp_elm_elm_t cmp_elm_elm,
TRI_skiplist_cmp_key_elm_t cmp_key_elm,
void *cmpdata,
TRI_skiplist_free_func_t freefunc,
bool unique);
////////////////////////////////////////////////////////////////////////////////
/// @brief frees a skiplist and all its documents
////////////////////////////////////////////////////////////////////////////////
void TRI_FreeSkipList (TRI_skiplist_t* sl);
// -----------------------------------------------------------------------------
// --SECTION-- public methods
// -----------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
/// @brief return the start node
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_node_t* TRI_SkipListStartNode (TRI_skiplist_t* sl);
////////////////////////////////////////////////////////////////////////////////
/// @brief return the successor node or NULL if last node
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_node_t* TRI_SkipListNextNode (TRI_skiplist_node_t* node);
////////////////////////////////////////////////////////////////////////////////
/// @brief inserts a new document into a skiplist
///
/// Comparison is done using proper order comparison. If the skiplist
/// is unique then no two documents that compare equal in the preorder
/// can be inserted. Returns 0 if all is well, -1 if allocation failed
/// and -2 if the unique constraint would have been violated by the
/// insert. In the latter two cases nothing is inserted.
////////////////////////////////////////////////////////////////////////////////
int TRI_SkipListInsert (TRI_skiplist_t *sl, void *doc);
////////////////////////////////////////////////////////////////////////////////
/// @brief removes a document from a skiplist
///
/// Comparison is done using proper order comparison. Returns 0 if all
/// is well and -1 if the document was not found. In the latter two
/// cases nothing is inserted.
////////////////////////////////////////////////////////////////////////////////
int TRI_SkipListRemove (TRI_skiplist_t *sl, void *doc);
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the number of entries in the skiplist.
////////////////////////////////////////////////////////////////////////////////
uint64_t TRI_SkipListGetNrUsed (TRI_skiplist_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief returns the memory used by the index
////////////////////////////////////////////////////////////////////////////////
size_t TRI_SkipListMemoryUsage (TRI_skiplist_t const*);
////////////////////////////////////////////////////////////////////////////////
/// @brief looks up doc in the skiplist using the proper order
/// comparison.
///
/// Only comparisons using the proper order are done using cmp_elm_elm.
/// Returns NULL if doc is not in the skiplist.
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_node_t* TRI_SkipListLookup (TRI_skiplist_t *sl, void *doc);
////////////////////////////////////////////////////////////////////////////////
/// @brief finds the last document that is less to doc in the preorder
/// comparison or the start node if none is.
///
/// Only comparisons using the preorder are done using cmp_elm_elm.
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_node_t* TRI_SkipListLeftLookup (TRI_skiplist_t *sl, void *doc);
////////////////////////////////////////////////////////////////////////////////
/// @brief finds the last document that is less or equal to doc in
/// the preorder comparison or the start node if none is.
///
/// Only comparisons using the preorder are done using cmp_elm_elm.
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_node_t* TRI_SkipListRightLookup (TRI_skiplist_t *sl, void *doc);
////////////////////////////////////////////////////////////////////////////////
/// @brief finds the last document whose key is less to key in the preorder
/// comparison or the start node if none is.
///
/// Only comparisons using the preorder are done using cmp_key_elm.
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_node_t* TRI_SkipListLeftKeyLookup (TRI_skiplist_t *sl, void *key);
////////////////////////////////////////////////////////////////////////////////
/// @brief finds the last document that is less or equal to doc in
/// the preorder comparison or the start node if none is.
///
/// Only comparisons using the preorder are done using cmp_key_elm.
////////////////////////////////////////////////////////////////////////////////
TRI_skiplist_node_t* TRI_SkipListRightKeyLookup (TRI_skiplist_t *sl, void *key);
#ifdef __cplusplus
}
#endif
#endif
// -----------------------------------------------------------------------------
// --SECTION-- END-OF-FILE
// -----------------------------------------------------------------------------
// Local Variables:
// mode: outline-minor
// outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @page\\|// --SECTION--\\|/// @\\}"
// End: