Designing a resize function for a queue

480 Views Asked by At

I'm currently trying to design a public API for a queue data structure and resize function to change its size. My first intention was to do it in the following way:

typedef struct queue queue;

/**
 * Resizes a given queue.
 *
 * Changes the size of the queue passed as a parameter. 
 * The content of the resized queue prior to the lesser
 * of new and old sizes is left unchanged. 
 *
 * Returns:
 *  0 - on success
 * -1 - on error and the content of the original queue is left unchanged
 */
int queue_resize(queue * queue_ptr, size_t new_size);

The problem is I read the contract to realloc and it was the following:

The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object could not be allocated.

Is it a common approach for reallocation functions to return a new object and reclaim the old one? So in such a case I should have redesigned the int queue_resize(queue *queue_ptr, size_t); to make queue * queue_resize(queue *queue_ptr, size_t); with the corresponding contract changes.

2

There are 2 best solutions below

6
bitmask On BEST ANSWER

realloc must be able to move the allocated space to a different address for it to be able to work. Imagine the memory directly after the currently allocated memory was already in use. Without relocation you could not create a contiguous sequence.

Typically your queue will look something like this

typedef struct queue {
  some_type* data_member;
  size_t size;
  size_t capacity;
  // .. perhaps more
} queue;

So when you have a queue_resize function you can just pass a queue* and the new size. What you pass to realloc is not the queue* but its data_member. Since you already have a pointer to the queue object, you can just update the pointer of data_member if realloc chooses to change it.

In this case returning a new queue* object is not necessary, because the memory footprint of queue never changes. Nor do you have to pass a queue** or anything of the sort.

0
Marichyasana On

Previous answers/comments do not address what to do with the data. Consider what is done in Java when the Java run-time discovers that the Array needs to be bigger. E.g. you try to append an element to an already full Array.

  • a new Array is allocated with the desired size; this includes setting up the meta data
  • a lock has to be set so the old Array doesn't change
  • all data is copied from the existing Array to the new Array; includes updating meta data; note that both Arrays need to exist at the same time for this
  • the original Array is removed (not sure of the right word here.)
  • the lock is removed
  • If you just fiddle with pointers, you will loose the data.
  • You can easily copy the data using standard methods such as Add() and Remove()