22

I notice the thread of similar question: Limit size of Queue<T> in .NET? That's exactly what I want to do, but I am not using .net but GNU C++. I have no reference to the base class in GNU C++, so java like super.***() or .net like base.***() will not work. I have been trying to inherit from queue class but it turns out in vain.

What I want to do: specify the size of the queue, and automatically dequeue when the queue is full. To be specific: if the maximum size of my queue is 2, when I push the 3rd item, the 1st item will be automatically popped out before pushing the new item.

How to implement such a queue?

Thanks.

Community
  • 1
  • 1
Lily
  • 5,542
  • 17
  • 53
  • 73
  • 1
    You need to explain what you mean by "automatic dequeue" - do you mean discard things at the queue's head? –  Aug 13 '09 at 16:23
  • @Neil: I was about to ask the very same question, but then I first clikced on the linked posting. `:)` – sbi Aug 13 '09 at 22:03

4 Answers4

15

Make a new class that encapsulates the queue and enforce a size limit in the new class.

Brian Ensink
  • 10,796
  • 3
  • 46
  • 60
  • 2
    do you mean: creating a new class with a member variable queue? – Lily Aug 13 '09 at 16:32
  • @Lily, I believe that is what he is getting at. This is fairly straightforward simply because a queue only really has two important mutators, push_back, pop_front. And in your case if it automatically dequeues you might only need push_back as a public member. – DeusAduro Aug 13 '09 at 16:35
  • 3
    I disagree with this solution, since it prevents using this queue where a std lib queue is expected (like this: `template< typename T, class C> void f(std::queue&)`). OTOH, using `std::queue with a different underlying container will allow to use that queue with sufficiently generic code that expects std lib queues. – sbi Aug 14 '09 at 08:17
15

I know you said "automatic", but, to keep things simple: Encapsulate just the Enqueue()ing in a local function (no, not clean OO, but it works):

Queue<T> myQueue = new Queue<T>();

void addToMyQueue(T param)
{
   myQueue.Enqueue(param); //or push(param)
   if (myQueue.Count > LIMIT)
      myQueue.Dequeue(); //or pop()
}

void main()
{
   addToMyQueue(param);
}
Engineer
  • 7,543
  • 7
  • 57
  • 96
  • 1
    It is a standard queue and it fulfills the purpose (i.e. fixed size of queue). I say this is the most clean solution. – wmac May 12 '13 at 05:04
  • By the way this is more likely to be Java's format. The class is queue and initialization does not need new, only queue myQueue; will suffice and you need to use push, pop and size instead of those methods. – wmac May 13 '13 at 03:08
8

It sounds like boost::circuclar_buffer does what you're looking for:

Writing to a Full Buffer

There are several options how to cope with the case if a data source produces more data than can fit in the fixed-sized buffer:

  1. Inform the data source to wait until there is room in the buffer (e.g. by throwing an overflow exception).
  2. If the oldest data is the most important, ignore new data from the source until there is room in the buffer again.
  3. If the latest data is the most important, write over the oldest data.
  4. Let the producer to be responsible for checking the size of the buffer prior writing into it.

It is apparent that the circular_buffer implements the third option. But it may be less apparent it does not implement any other option - especially the first two. One can get an impression that the circular_buffer should implement first three options and offer a mechanism of choosing among them. This impression is wrong. The circular_buffer was designed and optimized to be circular (which means overwriting the oldest data when full). If such a controlling mechanism had been enabled, it would just complicate the matters and the usage of the circular_buffer would be probably less straightforward.

Michael Burr
  • 311,791
  • 49
  • 497
  • 724
0

Assuming that by Queue<T> you mean std::queue<T>: A queue is just an adapter for some underlying container that's passed at compile-time. You could use a container that already does what you want. The best fit seems to be a circular buffer, if you can find one that supports the operations necessary for std::queue (I think that's push_back(), pop_front(), and size(), but I haven't checked).

sbi
  • 204,536
  • 44
  • 236
  • 426