mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 02:46:29 +01:00 
			
		
		
		
	 dbfee9fc2b
			
		
	
	
	dbfee9fc2b
	
	
	
		
			
			Partial commit of the greater MDEV-34348 scope. MDEV-34348: MariaDB is violating clang-16 -Wcast-function-type-strict The functions queue_compare, qsort2_cmp, and qsort_cmp2 all had similar interfaces, and were used interchangable and unsafely cast to one another. This patch consolidates the functions all into the qsort_cmp2 interface. Reviewed By: ============ Marko Mäkelä <marko.makela@mariadb.com>
		
			
				
	
	
		
			180 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			180 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (c) 2010, 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 Foundation; version 2 of the License.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
 | |
| 
 | |
| #ifndef BOUNDED_QUEUE_INCLUDED
 | |
| #define BOUNDED_QUEUE_INCLUDED
 | |
| 
 | |
| #include "my_base.h"
 | |
| #include <my_sys.h>
 | |
| #include "queues.h"
 | |
| #include <string.h>
 | |
| 
 | |
| class Sort_param;
 | |
| 
 | |
| /**
 | |
|   A priority queue with a fixed, limited size.
 | |
| 
 | |
|   This is a wrapper on top of QUEUE and the queue_xxx() functions.
 | |
|   It keeps the top-N elements which are inserted.
 | |
| 
 | |
|   Elements of type Element_type are pushed into the queue.
 | |
|   For each element, we call a user-supplied keymaker_function,
 | |
|   to generate a key of type Key_type for the element.
 | |
|   Instances of Key_type are compared with the user-supplied compare_function.
 | |
| 
 | |
|   The underlying QUEUE implementation needs one extra element for replacing
 | |
|   the lowest/highest element when pushing into a full queue.
 | |
|  */
 | |
| template<typename Element_type, typename Key_type>
 | |
| class Bounded_queue
 | |
| {
 | |
| public:
 | |
|   Bounded_queue()
 | |
|   {
 | |
|     memset(&m_queue, 0, sizeof(m_queue));
 | |
|   }
 | |
| 
 | |
|   ~Bounded_queue()
 | |
|   {
 | |
|     delete_queue(&m_queue);
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|      Function for making sort-key from input data.
 | |
|      @param param Sort parameters.
 | |
|      @param to    Where to put the key.
 | |
|      @param from  The input data.
 | |
|   */
 | |
|   typedef uint (*keymaker_function)(Sort_param *param,
 | |
|                                     Key_type *to,
 | |
|                                     Element_type *from,
 | |
|                                     bool packing_keys);
 | |
| 
 | |
|   /**
 | |
|     Initialize the queue.
 | |
| 
 | |
|     @param max_elements   The size of the queue.
 | |
|     @param max_at_top     Set to true if you want biggest element on top.
 | |
|            false: We keep the n largest elements.
 | |
|                   pop() will return the smallest key in the result set.
 | |
|            true:  We keep the n smallest elements.
 | |
|                   pop() will return the largest key in the result set.
 | |
|     @param compare_length Length of the data (i.e. the keys) used for sorting.
 | |
|     @param keymaker       Function which generates keys for elements.
 | |
|     @param sort_param     Sort parameters.
 | |
|     @param sort_keys      Array of pointers to keys to sort.
 | |
| 
 | |
|     @retval 0 OK, 1 Could not allocate memory.
 | |
| 
 | |
|     We do *not* take ownership of any of the input pointer arguments.
 | |
|    */
 | |
|   int init(ha_rows max_elements, bool max_at_top,
 | |
|            size_t compare_length,
 | |
|            keymaker_function keymaker, Sort_param *sort_param,
 | |
|            Key_type **sort_keys);
 | |
| 
 | |
|   /**
 | |
|     Pushes an element on the queue.
 | |
|     If the queue is already full, we discard one element.
 | |
|     Calls keymaker_function to generate a key for the element.
 | |
| 
 | |
|     @param element        The element to be pushed.
 | |
|    */
 | |
|   void push(Element_type *element);
 | |
| 
 | |
|   /**
 | |
|     Removes the top element from the queue.
 | |
| 
 | |
|     @retval Pointer to the (key of the) removed element.
 | |
| 
 | |
|     @note This function is for unit testing, where we push elements into to the
 | |
|           queue, and test that the appropriate keys are retained.
 | |
|           Interleaving of push() and pop() operations has not been tested.
 | |
|    */
 | |
|   Key_type **pop()
 | |
|   {
 | |
|     // Don't return the extra element to the client code.
 | |
|     if (queue_is_full((&m_queue)))
 | |
|       queue_remove(&m_queue, 0);
 | |
|     DBUG_ASSERT(m_queue.elements > 0);
 | |
|     if (m_queue.elements == 0)
 | |
|       return NULL;
 | |
|     return reinterpret_cast<Key_type**>(queue_remove(&m_queue, 0));
 | |
|   }
 | |
| 
 | |
|   /**
 | |
|     The number of elements in the queue.
 | |
|    */
 | |
|   uint num_elements() const { return m_queue.elements; }
 | |
| 
 | |
|   /**
 | |
|     Is the queue initialized?
 | |
|    */
 | |
|   bool is_initialized() const { return m_queue.max_elements > 0; }
 | |
| 
 | |
| private:
 | |
|   Key_type         **m_sort_keys;
 | |
|   size_t             m_compare_length;
 | |
|   keymaker_function  m_keymaker;
 | |
|   Sort_param        *m_sort_param;
 | |
|   st_queue           m_queue;
 | |
| };
 | |
| 
 | |
| 
 | |
| template<typename Element_type, typename Key_type>
 | |
| int Bounded_queue<Element_type, Key_type>::init(ha_rows max_elements,
 | |
|                                                 bool max_at_top,
 | |
|                                                 size_t compare_length,
 | |
|                                                 keymaker_function keymaker,
 | |
|                                                 Sort_param *sort_param,
 | |
|                                                 Key_type **sort_keys)
 | |
| {
 | |
|   DBUG_ASSERT(sort_keys != NULL);
 | |
| 
 | |
|   m_sort_keys=      sort_keys;
 | |
|   m_compare_length= compare_length;
 | |
|   m_keymaker=       keymaker;
 | |
|   m_sort_param=     sort_param;
 | |
|   // init_queue() takes an uint, and also does (max_elements + 1)
 | |
|   if (max_elements >= (UINT_MAX - 1))
 | |
|     return 1;
 | |
|   // We allocate space for one extra element, for replace when queue is full.
 | |
|   return init_queue(&m_queue, (uint) max_elements + 1,
 | |
|                     0, max_at_top,
 | |
|                     get_ptr_compare(compare_length),
 | |
|                     &m_compare_length, 0, 0);
 | |
| }
 | |
| 
 | |
| 
 | |
| template<typename Element_type, typename Key_type>
 | |
| void Bounded_queue<Element_type, Key_type>::push(Element_type *element)
 | |
| {
 | |
|   DBUG_ASSERT(is_initialized());
 | |
|   if (queue_is_full((&m_queue)))
 | |
|   {
 | |
|     // Replace top element with new key, and re-order the queue.
 | |
|     Key_type **pq_top= reinterpret_cast<Key_type **>(queue_top(&m_queue));
 | |
|     (void)(*m_keymaker)(m_sort_param, *pq_top, element, false);
 | |
|     queue_replace_top(&m_queue);
 | |
|   } else {
 | |
|     // Insert new key into the queue.
 | |
|     (*m_keymaker)(m_sort_param, m_sort_keys[m_queue.elements],
 | |
|                   element, false);
 | |
|     queue_insert(&m_queue,
 | |
|                  reinterpret_cast<uchar*>(&m_sort_keys[m_queue.elements]));
 | |
|   }
 | |
| }
 | |
| 
 | |
| #endif  // BOUNDED_QUEUE_INCLUDED
 |