Boost logo

Boost Users :

From: Eric Colleu (ecolleu_at_[hidden])
Date: 2006-06-22 05:15:58


Hi,

I'm using boost 1.33.1 on multi-processor plateform (2 Pentium4 3.2 GHz)
and Windows XP SP2 (compiled with MinGW).
I wrote a MessageQueue class which use boost::mutex and boost::condition
to wait for message and notify message reception (see code below)
I made a little test that create 2 boost::thread sending and receiving
messages in 2 queues.
The access violation is produced in the "WaitForSingleObject" method
called by "condition_impl::do_wait"
Have you ever meet this problem?

Eric Colleu

------messageQueue.cpp-----START
#include <iostream>
#include "messageQueue.hpp"

namespace util
{
    MessageQueue::MessageQueue(void)
    : m_mutex()
    , m_condition()
    , m_queue()
    , m_cancel(false)
    {
    }
   
    MessageQueue::~MessageQueue(void) throw()
    {
    }

    void MessageQueue::push(MessageHandle message)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        m_queue.push(message);
        m_condition.notify_all();
    }
   
    MessageHandle MessageQueue::pop(const boost::xtime& delay)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        while (m_queue.size() == 0)
        {
            if (!m_condition.timed_wait(lock, delay))
            {
                throw MsgTimeout("timeout in pop message");
            }
        }
        if(m_cancel) {
            m_cancel = false;
            throw MsgWaitCancelled("Wait Event cancelled");
        }
        MessageHandle msg = m_queue.front();
        m_queue.pop();
        return msg;
    }

    MessageHandle MessageQueue::pop(void)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        while (m_queue.size() == 0 && ! m_cancel) {
            m_condition.wait(lock);
        }
        if(m_cancel) {
            m_cancel = false;
            throw MsgWaitCancelled("Wait Event cancelled");
        }
        MessageHandle msg(m_queue.front());
        m_queue.pop();
        return msg;
    }

    int MessageQueue::size(void)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        return m_queue.size();
    }

    void MessageQueue::cancel_wait(void)
    {
        boost::mutex::scoped_lock lock(m_mutex);
        m_cancel = true;
        m_condition.notify_all();
    }
   
}

------messageQueue.cpp-----END

------messageQueue.hpp-----START
#if defined(CORE_UTIL_QUEUE_MESSAGEQUEUE_CYCLE)
    #error Header cyclic inclusion detected.
#endif // defined(CORE_UTIL_QUEUE_MESSAGEQUEUE_CYCLE)
#define CORE_UTIL_QUEUE_MESSAGEQUEUE_CYCLE

#if !defined(CORE_UTIL_QUEUE_MESSAGEQUEUE_HPP)
    #define CORE_UTIL_QUEUE_MESSAGEQUEUE_HPP
// ===================================================================

#include <queue>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include "core/exceptions.hpp"
#include "message.hpp"
namespace util
{
    /** File d'attente de messages.
     * Cette classe fonctionne comme une FIFO, et permet de
     * faire une attente bloquante d'un message.
     */
    class MessageQueue
    {
    public:

        MessageQueue(void);
        virtual ~MessageQueue(void) throw();

        /** Empile un message en fin de liste.
         * @param message Le message a ajouter.
         */
        void push(boost::shared_ptr<Message> message);

        /** Attend un message pendant un temps déterminé.
         * @param delay Temps d'attente du message.
         * @return Le message si un message a été reçu
         * @throws MsgTimeout Si aucun message n'a été empilé pendant le
temps défini en paramètre.
         * @throws MsgWaitCancelled Si l'attente a été interrompue par
un cancel_wait.
         */
        MessageHandle pop(const boost::xtime& delay);
        /** Attend un message infiniment.
         * @return Le message si un message a été reçu
        * @throws MsgWaitCancelled Si l'attente a été interrompue par un
cancel_wait.
         */
        MessageHandle pop(void);
        /** Retourne la taille de la file d'attente.
         * @return le nombre d'éléments restant dans la file d'attente.
         */
        int size(void);
        /** Interrompt une attente de message. */
        void cancel_wait(void);
    private:
        boost::mutex m_mutex;
        boost::condition m_condition;
        std::queue<MessageHandle > m_queue;
        bool m_cancel;
    };
}

// ===================================================================
#endif // !defined CORE_UTIL_QUEUE_MESSAGEQUEUE_HPP
#undef CORE_UTIL_QUEUE_MESSAGEQUEUE_CYCLE

------messageQueue.hpp-----END
------message.hpp-----START
#if defined(CORE_UTIL_QUEUE_MESSAGE_CYCLE)
#error Header cyclic inclusion detected.
#endif // defined(CORE_UTIL_QUEUE_MESSAGE_CYCLE)
#define CORE_UTIL_QUEUE_MESSAGE_CYCLE

#if !defined(CORE_UTIL_QUEUE_MESSAGE_HPP)
#define CORE_UTIL_QUEUE_MESSAGE_HPP
// ===================================================================
#include <string>
#include <boost/shared_ptr.hpp>

namespace util
{
    /**
     * La classe Message représente les message transittant dans les
MessageQueue,
     * entre le gestionnaire (device::AbstractDeviceManager) et la pile
de communication
     * (stack_manager::SimpleStack).
     * Ces messages peuvent être des requêtes, réponses ou événements.
     */
    class Message
    {
        public:
            Message(std::string id, bool is_event) : m_id(id),
m_isEvent(is_event) {};
            virtual ~Message(void) throw() {};

            /** Indique si le message est un événement.
             * @return
             * - true : s'il s'agit d'un événement
             * - false sinon.
             */
            bool isEvent(void) {return m_isEvent;};
            /** Retourne l'identifiant du message.
             * @return une chaîne de caractère représentant
l'identifiant du message.
             */
            std::string getId(void) {return m_id;};
            /** Encode les données à transmettre à la pile de
communication sous forme d'une chaîne.
             */
            virtual std::string encode(void) = 0;
            virtual void decode(void) = 0;
           
        protected:
            std::string m_id;
        private:
            bool m_isEvent;
    };
    /** Pointeur sur un Message. */
    typedef boost::shared_ptr<Message> MessageHandle;
}

// ===================================================================
#endif // !defined CORE_UTIL_QUEUE_MESSAGE_HPP
#undef CORE_UTIL_QUEUE_MESSAGE_CYCLE

------message.hpp-----END




Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net