summaryrefslogtreecommitdiff
path: root/sql/sql_list.h
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_list.h')
-rw-r--r--sql/sql_list.h89
1 files changed, 75 insertions, 14 deletions
diff --git a/sql/sql_list.h b/sql/sql_list.h
index ba61a931e04..2e068f7f961 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -1,3 +1,5 @@
+#ifndef INCLUDES_MYSQL_SQL_LIST_H
+#define INCLUDES_MYSQL_SQL_LIST_H
/* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
@@ -25,16 +27,16 @@ class Sql_alloc
public:
static void *operator new(size_t size) throw ()
{
- return (void*) sql_alloc((uint) size);
+ return sql_alloc(size);
}
static void *operator new[](size_t size)
{
- return (void*) sql_alloc((uint) size);
+ return sql_alloc(size);
}
static void *operator new[](size_t size, MEM_ROOT *mem_root) throw ()
- { return (void*) alloc_root(mem_root, (uint) size); }
+ { return alloc_root(mem_root, size); }
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
- { return (void*) alloc_root(mem_root, (uint) size); }
+ { return alloc_root(mem_root, size); }
static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); }
static void operator delete(void *ptr, MEM_ROOT *mem_root)
{ /* never called */ }
@@ -63,21 +65,24 @@ public:
pointer.
*/
-class list_node :public Sql_alloc
+
+/**
+ list_node - a node of a single-linked list.
+ @note We never call a destructor for instances of this class.
+*/
+
+struct list_node :public Sql_alloc
{
-public:
list_node *next;
void *info;
list_node(void *info_par,list_node *next_par)
:next(next_par),info(info_par)
- {}
+ {}
list_node() /* For end_of_list */
- {
- info=0;
- next= this;
- }
- friend class base_list;
- friend class base_list_iterator;
+ {
+ info= 0;
+ next= this;
+ }
};
@@ -93,12 +98,28 @@ public:
inline void empty() { elements=0; first= &end_of_list; last=&first;}
inline base_list() { empty(); }
+ /**
+ This is a shallow copy constructor that implicitly passes the ownership
+ from the source list to the new instance. The old instance is not
+ updated, so both objects end up sharing the same nodes. If one of
+ the instances then adds or removes a node, the other becomes out of
+ sync ('last' pointer), while still operational. Some old code uses and
+ relies on this behaviour. This logic is quite tricky: please do not use
+ it in any new code.
+ */
inline base_list(const base_list &tmp) :Sql_alloc()
{
elements= tmp.elements;
first= tmp.first;
last= elements ? tmp.last : &first;
}
+ /**
+ Construct a deep copy of the argument in memory root mem_root.
+ The elements themselves are copied by pointer. If you also
+ need to copy elements by value, you should employ
+ list_copy_and_replace_each_value after creating a copy.
+ */
+ base_list(const base_list &rhs, MEM_ROOT *mem_root);
inline base_list(bool error) { }
inline bool push_back(void *info)
{
@@ -185,6 +206,15 @@ public:
elements+= list->elements;
}
}
+ /**
+ Swap two lists.
+ */
+ inline void swap(base_list &rhs)
+ {
+ swap_variables(list_node *, first, rhs.first);
+ swap_variables(list_node **, last, rhs.last);
+ swap_variables(uint, elements, rhs.elements);
+ }
inline list_node* last_node() { return *last; }
inline list_node* first_node() { return first;}
inline void *head() { return first->info; }
@@ -349,6 +379,8 @@ template <class T> class List :public base_list
public:
inline List() :base_list() {}
inline List(const List<T> &tmp) :base_list(tmp) {}
+ inline List(const List<T> &tmp, MEM_ROOT *mem_root) :
+ base_list(tmp, mem_root) {}
inline bool push_back(T *a) { return base_list::push_back(a); }
inline bool push_back(T *a, MEM_ROOT *mem_root)
{ return base_list::push_back(a, mem_root); }
@@ -424,7 +456,7 @@ struct ilink
}
static void operator delete(void* ptr_arg, size_t size)
{
- my_free((gptr)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
+ my_free((uchar*)ptr_arg, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
}
inline ilink()
@@ -547,3 +579,32 @@ public:
I_List_iterator(I_List<T> &a) : base_ilist_iterator(a) {}
inline T* operator++(int) { return (T*) base_ilist_iterator::next(); }
};
+
+/**
+ Make a deep copy of each list element.
+
+ @note A template function and not a template method of class List
+ is employed because of explicit template instantiation:
+ in server code there are explicit instantiations of List<T> and
+ an explicit instantiation of a template requires that any method
+ of the instantiated class used in the template can be resolved.
+ Evidently not all template arguments have clone() method with
+ the right signature.
+
+ @return You must query the error state in THD for out-of-memory
+ situation after calling this function.
+*/
+
+template <typename T>
+inline
+void
+list_copy_and_replace_each_value(List<T> &list, MEM_ROOT *mem_root)
+{
+ /* Make a deep copy of each element */
+ List_iterator<T> it(list);
+ T *el;
+ while ((el= it++))
+ it.replace(el->clone(mem_root));
+}
+
+#endif // INCLUDES_MYSQL_SQL_LIST_H