2011-10-27 19 views
5

मैं इस वेबसाइट से प्राप्त अवरुद्ध कतार उदाहरण का उपयोग कर रहा हूं, यह सोचकर कि यह बहुत अच्छा था। यह अवरुद्ध कतार boost :: mutex का उपयोग कर रही है। यह कुछ समय के लिए एक अपवाद फेंक है:बूस्ट म्यूटेक्स फेंकने (विषम?) अपवाद

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<boost::system::system_error> >' 

क्या(): खराब फ़ाइल डिस्क्रिप्टर

यहाँ अवरोधित करना कतार कोड है:

#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; 
    } 
    }; 
} 

किसी को भी देखा जा सकता है कि क्या गलत यहाँ हो रहा है? क्योंकि मैंने पूरे दिन व्यर्थ में इसे समझने की कोशिश की है। मुझे लगता है कि इसे देखने के लिए मुझे बाहरी आंख की जरूरत है। टिप्पणी के लिए देखो '// अपवाद यहां फेंक दिया गया है!' यह देखने के लिए कि वास्तव में समस्या कहां होती है।

संपादित करें 1:

संदर्भ: मैं आदेश में एक MySQL async आवरण बनाने के लिए इस अवरोधन कतार उपयोग कर रहा हूँ।

यहाँ मेरी 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_ 

है यहाँ 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)); 
    } 
} 
बाद में

:

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; 
}; 

उम्मीद है कि अधिक जानकारियां के लिए कुछ अनुरोध करने के लिए जवाब देंगे ..

अजीब बात:

अगर मैं पूल :: MySQL :: get_instance द्वारा हर _mysql की जगह() मैं दुर्घटना करने लगता नहीं है। लेकिन मुझे लगता है कि कोई त्रुटि कहीं अधिक महत्वपूर्ण है कि नीचे है ...

+0

क्या आप वाकई यह कोड चाहते हैं, और वह नहीं जिसे आपने पोस्ट नहीं किया था? –

+0

हां मुझे पूरा यकीन है कि अपवाद इस बिंदु से बिल्कुल फेंक रहा है। मैंने जीडीबी और बहुत सी std :: cout का उपयोग करने से पहले सुनिश्चित करने के लिए उपयोग किया है। – TheSquad

+0

यह अजीब बात है, क्योंकि मुझे नहीं लगता कि निर्माता एक अपवाद फेंक सकते हैं: http://www.boost.org/doc/libs/1_37_0/doc/html/boost/interprocess/scoped_lock.html#id2914282-bb –

उत्तर

0

अगर कतार पहले से ही नष्ट हो जाता है, लेकिन आप अपने put विधि कॉल करने की कोशिश इस अपवाद उत्पन्न किया जा सकता है। कतार विनाशक में ब्रेकपॉइंट (या प्रिंट स्टेटमेंट) डालने से इसे जांचें।

+0

यह नष्ट नहीं हुआ है क्योंकि यह एक ऑब्जेक्ट क्लास में विशेषता के रूप में एक वस्तु है। सच है कि आप उसे नहीं जानते थे। मैंने अपनी पोस्ट में बहुत अधिक जानकारी दी। – TheSquad

+0

@ एंडी टी: क्या यह वास्तव में अपवाद फेंक देगा? मुझे लगता है कि यह बजाय segfault होगा। – Atmocreations

+0

@Atmocreations यदि boost :: mutex कोड एक अमान्य स्थिति का पता लगाता है तो यह एक अपवाद फेंक सकता है। ऑब्जेक्ट पता अभी भी ऑब्जेक्ट हटा दिए जाने के बाद भी प्रक्रिया में मैप किए गए मान्य पते हो सकता है। यदि ऐसा है, तो कोई सीजी-गलती नहीं होगी। – selalerer

संबंधित मुद्दे