Thread: queues and pointers

  1. #1
    Registered User
    Join Date
    Oct 2009
    Posts
    48

    queues and pointers

    Hi, let me preface by saying that I am a C programmer who is working on his first C++ project.

    I am having a few issues which I cannot resolve. I may not be tackling my problem correctly so I am open to suggestions on other ways to do this as well as how to fix it.

    My problem is that I am trying to use the queue template to store pointers to objects. The object is called Instruction and here is the code for my class that contains the queue
    Code:
    //* Declaration
    class Queue
    {
        public:
            Queue(uint sz);
            ~Queue();
            virtual void push(Instruction *instr);
            virtual Instruction *pop();
            virtual bool empty() const;
            virtual uint size() const;
            virtual uint count() const;
            virtual Instruction *front() const;
        private:
            queue<Instruction*> data;
            uint size_v;
            uint count_v;
            uint front_v;
            uint back_v;
    };
    
    //* Definition
    Queue::Queue(uint sz) : size_v(sz), count_v(0), front_v(0), back_v(0) {  }
    
    void Queue::push(Instruction *instr)
    {
        if (count_v != size_v)
        {
            data.push(instr);
            ++count_v;
        }
    
        return;
    }
    
    Instruction *Queue::pop()
    {
        if (count_v != 0)
        {
            --count_v;
    
            return data.pop();
        }
        else
        {
            return NULL;
        }
    }
    
    inline bool Queue::empty() const
    {
        return (count_v == 0);
    }
    
    inline uint Queue::size() const
    {
        return size_v;
    }
    
    inline uint Queue::count() const
    {
        return count_v;
    }
    
    inline Instruction *Queue::front() const
    {
        return data.front();
    }
    
    Queue::~Queue()
    {
        if (count_v)
        {
            std::cout << "~Queue: " << count_v << " items remaining" << std::endl;
    
            while (count_v-- > 0)
            {
                delete data.pop;
            }
        }
    }
    Why I need to use pointers to Instructions is that I need to have multiple Queues that point to the same instructions. If I have two Queue objects the contain the same Instruction, they both need to be able to modify the same object and not a copy.

    EDIT: Here is the output when compiling
    Code:
    error: ISO C++ forbids declaration of ‘queue’ with no type

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Why not just use a std::queue<Instruction*> directly instead of wrapping your own Queue class around it? The error is probably because you just wrote queue instead of std::queue (and remember to #include <queue>).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Oct 2009
    Posts
    48
    Thanks, that worked.

    The reason that I am making my own class is that I need to limit the size of the queue and be able to tell if it is full.

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    The reason that I am making my own class is that I need to limit the size of the queue and be able to tell if it is full.
    Ah, so the maximum size varies at run time for each queue? If it is fixed at compile time, then you can get away with just writing a function to extend the interface of the queue.

    There is a problem with your current Queue implementation in that you state that there is shared ownership ("multiple Queues that point to the same instruction"), but the Queue destructor destroys the Instruction objects left in the queue. This could result in double deletion. If you have access to a TR1 implementation, you could use a std::tr1::shared_ptr<Instruction> instead of a pointer to Instruction, and this would take care of the shared ownership problem (or you could use Boost's shared_ptr, which is roughly if not exactly the same). If not, then you either need to designate some "registry" of Instruction objects that has sole ownership of the Instruction objects, or you need to implement shared ownership yourself, e.g., via reference counting.

    I also notice that Queue has a number of virtual member functions. Is Queue supposed to be a polymorphic base class? If so, it should have a virtual destructor, but it looks like Queue should not be a base class.

    Also, I suggest that you maintain the std::queue interface: pop() should return void, not an Instruction*. As an alternative to wrapping a std::queue, you could use private inheritance, e.g.,:
    Code:
    class InstructionQueue : private std::queue<Instruction*>
    {
    public:
        using std::queue<Instruction*>::value_type;
        using std::queue<Instruction*>::size_type;
        using std::queue<Instruction*>::empty;
        using std::queue<Instruction*>::size;
        using std::queue<Instruction*>::pop;
        using std::queue<Instruction*>::front;
        using std::queue<Instruction*>::back;
    
        explicit InstructionQueue(size_type max_size) : max_size(max_size) {}
    
        void push(Instruction* const instruction)
        {
            if (size() < max_size)
            {
                std::queue<Instruction*>::push(instruction);
            }
        }
    private:
        size_type max_size;
    };
    However, the comparison operators would not be supplied by this trick since they are non-members.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Oct 2009
    Posts
    48
    Yes, the size is determined at runtime.

    Thanks for the info. I have never heard of Boost but I took a look at an example and I think that is the best route for me.

    About Queue, I am experimenting with the hierarchy still. I need multiple FIFO queues that point to the same Instruction object as well as a list that points to the same instructions but that I can get and remove instructions from this list in any order. This is a simulator for a computer architecture class so the queue is the reorder buffer (ROB) and must maintain the order and the list is the scheduling queue and must be able to remove any instruction from any position and has additional data associated with each instruction. My plan was to have the scheduling queue inherit Queue, but I am now second guessing that.

    Also, private inheritance is probably what I want, so I will try that.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by BdON003
    My plan was to have the scheduling queue inherit Queue, but I am now second guessing that.
    It does not look like you need to use run time polymorphism, so it does seem like you should not use public inheritance.

    Quote Originally Posted by BdON003
    Also, private inheritance is probably what I want, so I will try that.
    I am just offering it as an alternative; what you currently have with composition is well and good, and in fact the use of private inheritance is less common, perhaps because the wrapper class would would have member functions renamed to express the domain knowledge better, but in this case it appears that you want to use the same names.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with FIFO queue
    By Martin_T in forum C Programming
    Replies: 10
    Last Post: 11-08-2009, 10:30 AM
  2. Queue's and linked lists
    By Saggio in forum C++ Programming
    Replies: 3
    Last Post: 10-22-2007, 07:14 AM
  3. Data structs and pointers
    By vegaaces in forum C Programming
    Replies: 2
    Last Post: 04-30-2005, 12:50 PM
  4. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  5. Pointer validity check
    By Carlos in forum Windows Programming
    Replies: 6
    Last Post: 12-11-2003, 03:40 AM

Tags for this Thread