|
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