Sto usando un esempio di coda di blocco che ho ricevuto da questo sito Web, ritenendolo piuttosto carino. Questa coda di blocco utilizza boost :: mutex. E 'a volte un'eccezione:boost mutex lancio (dispari?) Eccezione
terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >'
cosa(): file descriptor Bad
Ecco il codice coda Blocco:
#include <boost/thread/mutex.hpp>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition_variable.hpp>
#include <exception>
#include <list>
#include <stdio.h>
struct BlockingQueueTerminate
: std::exception
{};
namespace tools {
template<class T>
class BlockingQueue
{
private:
boost::mutex mtx_;
boost::condition_variable cnd_;
std::list<T> q_;
unsigned blocked_;
bool stop_;
public:
BlockingQueue()
: blocked_()
, stop_()
{}
~BlockingQueue()
{
this->stop(true);
}
void stop(bool wait)
{
// tell threads blocked on BlockingQueue::pull() to leave
boost::mutex::scoped_lock lock(mtx_);
stop_ = true;
cnd_.notify_all();
if(wait) // wait till all threads blocked on the queue leave BlockingQueue::pull()
while(blocked_)
cnd_.wait(lock);
}
void put(T t)
{
boost::mutex::scoped_lock lock(mtx_); // The exception is thrown here !
q_.push_back(t);
cnd_.notify_one();
}
T pull()
{
boost::mutex::scoped_lock lock(mtx_);
++blocked_;
while(!stop_ && q_.empty())
cnd_.wait(lock);
--blocked_;
if(stop_) {
cnd_.notify_all(); // tell stop() this thread has left
throw BlockingQueueTerminate();
}
T front = q_.front();
q_.pop_front();
return front;
}
};
}
Chiunque può individuare cosa sta andando male qui? perché ho provato tutto il giorno a scoprirlo invano. Credo di aver bisogno di un occhio esterno per vederlo. Cerca il commento '// L'eccezione è lanciata qui!' per vedere dove si verifica esattamente il problema.
EDIT 1:
Il contesto: sto usando questa coda di blocco al fine di creare un involucro async MySQL.
Ecco la mia MySQL.hh
#ifndef MYSQL_HH_
# define MYSQL_HH_
# include <boost/asio.hpp>
# include <boost/thread.hpp>
# include <boost/function.hpp>
# include <mysql++/mysql++.h>
# include <queue>
# include "async_executor.hh"
# include "BlockingQueue.hh"
class t_mysql_event {
public:
t_mysql_event(std::string query, boost::function<void(mysqlpp::StoreQueryResult)> cb) :
m_query(query), m_store_cb(cb), m_store_bool(true) {}
t_mysql_event(std::string query, boost::function<void()> cb) :
m_query(query), m_exec_cb(cb), m_store_bool(false) {}
bool is_store_query() {
return m_store_bool;
}
std::string toString() {
return m_query;
}
std::string m_query;
boost::function<void(mysqlpp::StoreQueryResult)> m_store_cb;
boost::function<void()> m_exec_cb;
private:
bool m_store_bool;
};
namespace pools {
class MySQL {
public:
~MySQL() {}
static MySQL* create_instance(boost::asio::io_service& io);
static MySQL* get_instance();
void exec(std::string query, boost::function<void()> cb);
void store(std::string query, boost::function<void(mysqlpp::StoreQueryResult)> cb);
private:
MySQL(boost::asio::io_service& io) : executor(io, 100), parent_io(io), m_strand(io)
{
for (int i=0; i < 100; ++i) {
boost::thread(boost::bind(&MySQL::retreive, this));
}
}
void async_exec(std::string query, boost::function<void()> cb, mysqlpp::Connection& conn);
void async_store(std::string query, boost::function<void(mysqlpp::StoreQueryResult)> cb, mysqlpp::Connection& conn);
void retreive();
private:
tools::async_executor executor;
boost::asio::io_service& parent_io;
boost::asio::strand m_strand;
tools::BlockingQueue<t_mysql_event*> m_events;
std::queue<mysqlpp::Connection*> m_stack;
};
}
#endif //MYSQL_HH_
Ecco il MySQL.cc:
#include "MySQL.hh"
static pools::MySQL* _instance = 0;
namespace pools {
MySQL* MySQL::create_instance(boost::asio::io_service& io) {
if (!_instance)
_instance = new MySQL(io);
return _instance;
}
MySQL* MySQL::get_instance() {
if (!_instance) {
exit(1);
}
return _instance;
}
void MySQL::exec(std::string query, boost::function<void()> cb) {
m_events.put(new t_mysql_event(query, cb));
}
void MySQL::store(std::string query, boost::function<void(mysqlpp::StoreQueryResult)> cb) {
m_events.put(new t_mysql_event(query, cb));
}
void MySQL::retreive() {
mysqlpp::Connection conn("***", "***", "***", "***");
for(;;) {
t_mysql_event *event = m_events.pull();
if (event->is_store_query())
async_store(event->m_query, event->m_store_cb, conn);
else
async_exec(event->m_query, event->m_exec_cb, conn);
delete event;
}
}
void MySQL::async_exec(std::string query, boost::function<void()> cb, mysqlpp::Connection& conn) {
mysqlpp::Query db_q = conn.query(query.c_str());
db_q.exec();
parent_io.post(cb);
}
void MySQL::async_store(std::string query, boost::function<void(mysqlpp::StoreQueryResult)> cb, mysqlpp::Connection& conn) {
mysqlpp::Query db_q = conn.query(query.c_str());
mysqlpp::StoreQueryResult res = db_q.store();
parent_io.post(boost::bind(cb, res));
}
}
seguito:
class MyClass {
public:
MyClass() : _mysql(pools::MySQL::get_instance()) {}
startQueries();
private:
void Query1() {
std::stringstream query("");
query << "INSERT INTO Table1 ***";
_mysql->exec(query.str(),
boost::bind(&MyClass::Query2, this, _1));
}
void Query2() {
std::stringstream query("");
query << "INSERT INTO Table2 ***";
_mysql->exec(query.str(),
boost::bind(&MyClass::Query3, this, _1));
}
void Query3() {
std::stringstream query("");
query << "INSERT INTO Table3 ***";
_mysql->exec(query.str(),
boost::bind(&MyClass::done, this, _1));
}
void done() {}
pools::MySQL *_mysql;
};
Sperando che risponderà a qualche richiesta di più informazioni ..
Funny thing:
Se sostituisco ogni _mysql di pools :: MySQL :: get_instance(), non sembra che si verifichi un arresto anomalo. Ma ho il sospetto c'è un errore di gran lunga più importante di sotto di quello ...
Sei sicuro che sia questo codice e non quello che non hai pubblicato? –
Sì, sono abbastanza sicuro che l'eccezione derivi esattamente da questo punto. Ho usato gdb e un sacco di std :: cout per essere sicuro prima di chiedere. – TheSquad
Questo è strano, perché non penso che i costruttori possano lanciare un'eccezione: http://www.boost.org/doc/libs/1_37_0/doc/html/boost/interprocess/scoped_lock.html#id2914282-bb –