My Project
|
00001 /* Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; version 2 of the License. 00006 00007 This program is distributed in the hope that it will be useful, 00008 but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 GNU General Public License for more details. 00011 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software 00014 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ 00015 00016 #ifndef BOUNDED_QUEUE_INCLUDED 00017 #define BOUNDED_QUEUE_INCLUDED 00018 00019 #include <string.h> 00020 #include "my_global.h" 00021 #include "my_base.h" 00022 #include "my_sys.h" 00023 #include "queues.h" 00024 00025 class Sort_param; 00026 00041 template<typename Element_type, typename Key_type> 00042 class Bounded_queue 00043 { 00044 public: 00045 Bounded_queue() 00046 { 00047 memset(&m_queue, 0, sizeof(m_queue)); 00048 } 00049 00050 ~Bounded_queue() 00051 { 00052 delete_queue(&m_queue); 00053 } 00054 00061 typedef void (*keymaker_function)(Sort_param *param, 00062 Key_type *to, 00063 Element_type *from); 00064 00073 typedef int (*compare_function)(size_t *n, Key_type **a, Key_type **b); 00074 00095 int init(ha_rows max_elements, bool max_at_top, 00096 compare_function compare, size_t compare_length, 00097 keymaker_function keymaker, Sort_param *sort_param, 00098 Key_type **sort_keys); 00099 00107 void push(Element_type *element); 00108 00118 Key_type **pop() 00119 { 00120 // Don't return the extra element to the client code. 00121 if (queue_is_full((&m_queue))) 00122 queue_remove(&m_queue, 0); 00123 DBUG_ASSERT(m_queue.elements > 0); 00124 if (m_queue.elements == 0) 00125 return NULL; 00126 return reinterpret_cast<Key_type**>(queue_remove(&m_queue, 0)); 00127 } 00128 00132 uint num_elements() const { return m_queue.elements; } 00133 00137 bool is_initialized() const { return m_queue.max_elements > 0; } 00138 00139 private: 00140 Key_type **m_sort_keys; 00141 size_t m_compare_length; 00142 keymaker_function m_keymaker; 00143 Sort_param *m_sort_param; 00144 st_queue m_queue; 00145 }; 00146 00147 00148 template<typename Element_type, typename Key_type> 00149 int Bounded_queue<Element_type, Key_type>::init(ha_rows max_elements, 00150 bool max_at_top, 00151 compare_function compare, 00152 size_t compare_length, 00153 keymaker_function keymaker, 00154 Sort_param *sort_param, 00155 Key_type **sort_keys) 00156 { 00157 DBUG_ASSERT(sort_keys != NULL); 00158 00159 m_sort_keys= sort_keys; 00160 m_compare_length= compare_length; 00161 m_keymaker= keymaker; 00162 m_sort_param= sort_param; 00163 // init_queue() takes an uint, and also does (max_elements + 1) 00164 if (max_elements >= (UINT_MAX - 1)) 00165 return 1; 00166 if (compare == NULL) 00167 compare= 00168 reinterpret_cast<compare_function>(get_ptr_compare(compare_length)); 00169 00170 DBUG_EXECUTE_IF("bounded_queue_init_fail", 00171 DBUG_SET("+d,simulate_out_of_memory");); 00172 00173 // We allocate space for one extra element, for replace when queue is full. 00174 return init_queue(&m_queue, (uint) max_elements + 1, 00175 0, max_at_top, 00176 reinterpret_cast<queue_compare>(compare), 00177 &m_compare_length); 00178 } 00179 00180 00181 template<typename Element_type, typename Key_type> 00182 void Bounded_queue<Element_type, Key_type>::push(Element_type *element) 00183 { 00184 DBUG_ASSERT(is_initialized()); 00185 if (queue_is_full((&m_queue))) 00186 { 00187 // Replace top element with new key, and re-order the queue. 00188 Key_type **pq_top= reinterpret_cast<Key_type **>(queue_top(&m_queue)); 00189 (*m_keymaker)(m_sort_param, *pq_top, element); 00190 queue_replaced(&m_queue); 00191 } else { 00192 // Insert new key into the queue. 00193 (*m_keymaker)(m_sort_param, m_sort_keys[m_queue.elements], element); 00194 queue_insert(&m_queue, 00195 reinterpret_cast<uchar*>(&m_sort_keys[m_queue.elements])); 00196 } 00197 } 00198 00199 #endif // BOUNDED_QUEUE_INCLUDED