summaryrefslogtreecommitdiff
path: root/storage/innobase/include/ut0vec.ic
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/include/ut0vec.ic')
-rw-r--r--storage/innobase/include/ut0vec.ic349
1 files changed, 324 insertions, 25 deletions
diff --git a/storage/innobase/include/ut0vec.ic b/storage/innobase/include/ut0vec.ic
index 34c858868ce..1255caee2d9 100644
--- a/storage/innobase/include/ut0vec.ic
+++ b/storage/innobase/include/ut0vec.ic
@@ -1,6 +1,6 @@
/*****************************************************************************
-Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
+Copyright (c) 2006, 2009, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -11,8 +11,8 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
-this program; if not, write to the Free Software Foundation, Inc., 59 Temple
-Place, Suite 330, Boston, MA 02111-1307 USA
+this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
@@ -23,21 +23,169 @@ A vector of pointers to data items
Created 4/6/2006 Osku Salerma
************************************************************************/
-/****************************************************************//**
-Get number of elements in vector.
-@return number of elements in vector */
+#define IB_VEC_OFFSET(v, i) (vec->sizeof_value * i)
+
+/********************************************************************
+The default ib_vector_t heap malloc. Uses mem_heap_alloc(). */
+UNIV_INLINE
+void*
+ib_heap_malloc(
+/*===========*/
+ ib_alloc_t* allocator, /* in: allocator */
+ ulint size) /* in: size in bytes */
+{
+ mem_heap_t* heap = (mem_heap_t*) allocator->arg;
+
+ return(mem_heap_alloc(heap, size));
+}
+
+/********************************************************************
+The default ib_vector_t heap free. Does nothing. */
+UNIV_INLINE
+void
+ib_heap_free(
+/*=========*/
+ ib_alloc_t* allocator UNIV_UNUSED, /* in: allocator */
+ void* ptr UNIV_UNUSED) /* in: size in bytes */
+{
+ /* We can't free individual elements. */
+}
+
+/********************************************************************
+The default ib_vector_t heap resize. Since we can't resize the heap
+we have to copy the elements from the old ptr to the new ptr.
+Uses mem_heap_alloc(). */
+UNIV_INLINE
+void*
+ib_heap_resize(
+/*===========*/
+ ib_alloc_t* allocator, /* in: allocator */
+ void* old_ptr, /* in: pointer to memory */
+ ulint old_size, /* in: old size in bytes */
+ ulint new_size) /* in: new size in bytes */
+{
+ void* new_ptr;
+ mem_heap_t* heap = (mem_heap_t*) allocator->arg;
+
+ new_ptr = mem_heap_alloc(heap, new_size);
+ memcpy(new_ptr, old_ptr, old_size);
+
+ return(new_ptr);
+}
+
+/********************************************************************
+Create a heap allocator that uses the passed in heap. */
+UNIV_INLINE
+ib_alloc_t*
+ib_heap_allocator_create(
+/*=====================*/
+ mem_heap_t* heap) /* in: heap to use */
+{
+ ib_alloc_t* heap_alloc;
+
+ heap_alloc = (ib_alloc_t*) mem_heap_alloc(heap, sizeof(*heap_alloc));
+
+ heap_alloc->arg = heap;
+ heap_alloc->mem_release = ib_heap_free;
+ heap_alloc->mem_malloc = ib_heap_malloc;
+ heap_alloc->mem_resize = ib_heap_resize;
+
+ return(heap_alloc);
+}
+
+/********************************************************************
+Free a heap allocator. */
+UNIV_INLINE
+void
+ib_heap_allocator_free(
+/*===================*/
+ ib_alloc_t* ib_ut_alloc) /* in: alloc instace to free */
+{
+ mem_heap_free((mem_heap_t*) ib_ut_alloc->arg);
+}
+
+/********************************************************************
+Wrapper around ut_malloc(). */
+UNIV_INLINE
+void*
+ib_ut_malloc(
+/*=========*/
+ ib_alloc_t* allocator UNIV_UNUSED, /* in: allocator */
+ ulint size) /* in: size in bytes */
+{
+ return(ut_malloc(size));
+}
+
+/********************************************************************
+Wrapper around ut_free(). */
+UNIV_INLINE
+void
+ib_ut_free(
+/*=======*/
+ ib_alloc_t* allocator UNIV_UNUSED, /* in: allocator */
+ void* ptr) /* in: size in bytes */
+{
+ ut_free(ptr);
+}
+
+/********************************************************************
+Wrapper aroung ut_realloc(). */
+UNIV_INLINE
+void*
+ib_ut_resize(
+/*=========*/
+ ib_alloc_t* allocator UNIV_UNUSED, /* in: allocator */
+ void* old_ptr, /* in: pointer to memory */
+ ulint old_size UNIV_UNUSED,/* in: old size in bytes */
+ ulint new_size) /* in: new size in bytes */
+{
+ return(ut_realloc(old_ptr, new_size));
+}
+
+/********************************************************************
+Create a ut allocator. */
+UNIV_INLINE
+ib_alloc_t*
+ib_ut_allocator_create(void)
+/*========================*/
+{
+ ib_alloc_t* ib_ut_alloc;
+
+ ib_ut_alloc = (ib_alloc_t*) ut_malloc(sizeof(*ib_ut_alloc));
+
+ ib_ut_alloc->arg = NULL;
+ ib_ut_alloc->mem_release = ib_ut_free;
+ ib_ut_alloc->mem_malloc = ib_ut_malloc;
+ ib_ut_alloc->mem_resize = ib_ut_resize;
+
+ return(ib_ut_alloc);
+}
+
+/********************************************************************
+Free a ut allocator. */
+UNIV_INLINE
+void
+ib_ut_allocator_free(
+/*=================*/
+ ib_alloc_t* ib_ut_alloc) /* in: alloc instace to free */
+{
+ ut_free(ib_ut_alloc);
+}
+
+/********************************************************************
+Get number of elements in vector. */
UNIV_INLINE
ulint
ib_vector_size(
/*===========*/
- const ib_vector_t* vec) /*!< in: vector */
+ /* out: number of elements in vector*/
+ const ib_vector_t* vec) /* in: vector */
{
return(vec->used);
}
/****************************************************************//**
-Get n'th element.
-@return n'th element */
+Get n'th element. */
UNIV_INLINE
void*
ib_vector_get(
@@ -47,9 +195,23 @@ ib_vector_get(
{
ut_a(n < vec->used);
- return(vec->data[n]);
+ return((byte*) vec->data + IB_VEC_OFFSET(vec, n));
}
+/********************************************************************
+Const version of the get n'th element.
+@return n'th element */
+UNIV_INLINE
+const void*
+ib_vector_get_const(
+/*================*/
+ const ib_vector_t* vec, /* in: vector */
+ ulint n) /* in: element index to get */
+{
+ ut_a(n < vec->used);
+
+ return((byte*) vec->data + IB_VEC_OFFSET(vec, n));
+}
/****************************************************************//**
Get last element. The vector must not be empty.
@return last element */
@@ -61,7 +223,7 @@ ib_vector_get_last(
{
ut_a(vec->used > 0);
- return(vec->data[vec->used - 1]);
+ return((byte*) ib_vector_get(vec, vec->used - 1));
}
/****************************************************************//**
@@ -74,9 +236,52 @@ ib_vector_set(
ulint n, /*!< in: element index to set */
void* elem) /*!< in: data element */
{
+ void* slot;
+
ut_a(n < vec->used);
- vec->data[n] = elem;
+ slot = ((byte*) vec->data + IB_VEC_OFFSET(vec, n));
+ memcpy(slot, elem, vec->sizeof_value);
+}
+
+/********************************************************************
+Reset the vector size to 0 elements. */
+UNIV_INLINE
+void
+ib_vector_reset(
+/*============*/
+ /* out: void */
+ ib_vector_t* vec) /* in: vector */
+{
+ vec->used = 0;
+}
+
+/********************************************************************
+Get the last element of the vector. */
+UNIV_INLINE
+void*
+ib_vector_last(
+/*===========*/
+ /* out: void */
+ ib_vector_t* vec) /* in: vector */
+{
+ ut_a(ib_vector_size(vec) > 0);
+
+ return(ib_vector_get(vec, ib_vector_size(vec) - 1));
+}
+
+/********************************************************************
+Get the last element of the vector. */
+UNIV_INLINE
+const void*
+ib_vector_last_const(
+/*=================*/
+ /* out: void */
+ const ib_vector_t* vec) /* in: vector */
+{
+ ut_a(ib_vector_size(vec) > 0);
+
+ return(ib_vector_get_const(vec, ib_vector_size(vec) - 1));
}
/****************************************************************//**
@@ -86,35 +291,129 @@ UNIV_INLINE
void*
ib_vector_pop(
/*==========*/
- ib_vector_t* vec) /*!< in/out: vector */
+ /* out: pointer to element */
+ ib_vector_t* vec) /* in: vector */
{
- void* elem;
+ void* elem;
ut_a(vec->used > 0);
- --vec->used;
- elem = vec->data[vec->used];
- ut_d(vec->data[vec->used] = NULL);
- UNIV_MEM_INVALID(&vec->data[vec->used], sizeof(*vec->data));
+ elem = ib_vector_last(vec);
+ --vec->used;
return(elem);
}
-/****************************************************************//**
-Free the underlying heap of the vector. Note that vec is invalid
-after this call. */
+/********************************************************************
+Append an element to the vector, if elem != NULL then copy the data
+from elem.*/
+UNIV_INLINE
+void*
+ib_vector_push(
+/*===========*/
+ /* out: pointer to the "new" element */
+ ib_vector_t* vec, /* in: vector */
+ const void* elem) /* in: element to add (can be NULL) */
+{
+ void* last;
+
+ if (vec->used >= vec->total) {
+ ib_vector_resize(vec);
+ }
+
+ last = (byte*) vec->data + IB_VEC_OFFSET(vec, vec->used);
+
+#ifdef UNIV_DEBUG
+ memset(last, 0, vec->sizeof_value);
+#endif
+
+ if (elem) {
+ memcpy(last, elem, vec->sizeof_value);
+ }
+
+ ++vec->used;
+
+ return(last);
+}
+
+/*******************************************************************//**
+Remove an element to the vector
+@return pointer to the "removed" element */
+UNIV_INLINE
+void*
+ib_vector_remove(
+/*=============*/
+ ib_vector_t* vec, /*!< in: vector */
+ const void* elem) /*!< in: value to remove */
+{
+ void* current;
+ void* next;
+ ulint i;
+
+ for (i = 0; i < vec->used; i++) {
+ current = ib_vector_get(vec, i);
+
+ if (*(void**) current == elem) {
+ if (i == vec->used - 1) {
+ return(ib_vector_pop(vec));
+ }
+
+ next = ib_vector_get(vec, i + 1);
+ memcpy(current, next, vec->sizeof_value
+ * (vec->used - i - 1));
+ }
+ }
+
+ --vec->used;
+
+ return(current);
+}
+
+/********************************************************************
+Sort the vector elements. */
+UNIV_INLINE
+void
+ib_vector_sort(
+/*===========*/
+ /* out: void */
+ ib_vector_t* vec, /* in: vector */
+ ib_compare_t compare)/* in: the comparator to use for sort */
+{
+ qsort(vec->data, vec->used, vec->sizeof_value, compare);
+}
+
+/********************************************************************
+Destroy the vector. Make sure the vector owns the allocator, e.g.,
+the heap in the the heap allocator. */
UNIV_INLINE
void
ib_vector_free(
/*===========*/
- ib_vector_t* vec) /*!< in, own: vector */
+ ib_vector_t* vec) /* in, own: vector */
{
- mem_heap_free(vec->heap);
+ /* Currently we only support two types of allocators, heap
+ and ut_malloc(), when the heap is freed all the elements are
+ freed too. With ut allocator, we need to free the elements,
+ the vector instance and the allocator separately. */
+
+ /* Only the heap allocator uses the arg field. */
+ if (vec->allocator->arg) {
+ mem_heap_free((mem_heap_t*) vec->allocator->arg);
+ } else {
+ ib_alloc_t* allocator;
+
+ allocator = vec->allocator;
+
+ allocator->mem_release(allocator, vec->data);
+ allocator->mem_release(allocator, vec);
+
+ ib_ut_allocator_free(allocator);
+ }
}
-/****************************************************************//**
+/********************************************************************
Test whether a vector is empty or not.
-@return TRUE if empty */
+@return TRUE if empty */
UNIV_INLINE
ibool
ib_vector_is_empty(