2012-07-26 12 views
9

मैं मूल थ्रेड पूल के रूप में boost::asio::io_service का उपयोग कर रहा हूं। कुछ थ्रेड io_service में जोड़े जाते हैं, मुख्य धागा हैंडलर पोस्ट करना शुरू करता है, कार्यकर्ता धागे हैंडलर चलाना शुरू करते हैं, और सब कुछ खत्म हो जाता है। अब तक सब ठीक है; मुझे सिंगल थ्रेडेड कोड पर एक अच्छा स्पीडअप मिलता है।बूस्ट एशिया के साथ पोस्ट कतार आकार पर सीमा निर्धारित करना?

हालांकि, मुख्य धागे में लाखों चीजें पोस्ट करने के लिए हैं। और यह सिर्फ उन्हें पोस्ट करना जारी रखता है, कार्यकर्ता थ्रेड से उन्हें बहुत तेज़ कर सकते हैं। मैं राम सीमाओं को हिट नहीं करता हूं, लेकिन अभी भी इतनी मूर्खतापूर्ण है कि इतनी सारी चीजें हैं। मैं क्या करना चाहता हूं, हैंडलर कतार के लिए एक निश्चित आकार है, और कतार पूर्ण होने पर पोस्ट() ब्लॉक है।

मुझे बूस्ट एएसआईओ दस्तावेज़ों में इसके लिए कोई विकल्प नहीं दिख रहा है। क्या यह संभव है?

उत्तर

0

आप घटनाओं को रखने और अपने मुख्य में देरी करने के लिए स्ट्रैंड ऑब्जेक्ट का उपयोग कर सकते हैं? क्या आपका काम सभी काम पोस्ट होने के बाद बाहर निकल रहा है? यदि ऐसा है तो आप कार्य ऑब्जेक्ट का उपयोग कर सकते हैं जो आपके io_service बंद होने पर आपको अधिक नियंत्रण देगा।

आप हमेशा धागे की स्थिति की जांच कर सकते हैं और यह तब तक प्रतीक्षा कर सकता है जब तक कि कोई भी मुक्त न हो या ऐसा कुछ न हो।

// लिंक

http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/reference/io_service__strand.html

http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/reference/io_service.html

//example from the second link 
boost::asio::io_service io_service; 
boost::asio::io_service::work work(io_service); 

आशा है कि यह मदद करता है।

+0

समस्या यह नहीं है कि 'io_service' कार्य पूरा करने से पहले बंद हो जाता है --- हम' io_service 'को गर्वपूर्वक बंद करने के लिए' कार्य 'ऑब्जेक्ट को हटाने के बारे में जानते हैं। समस्या यह है कि 'io_service' बहुत सारे कार्यों को जमा करने देता है। हम असाइन किए गए कार्यों की संख्या को ऐसे तरीके से सीमित करना चाहते हैं जिसमें कार्यों को बनाने वाले थ्रेड के हिस्से पर मतदान शामिल न हो, इसलिए हमारे प्रश्न के बारे में हमारा सवाल है कि 'मतदान() 'को ब्लॉक करने के लिए बनाया जा सकता है या नहीं। – uckelman

2

मैं हैंडलर कतार आकार को ठीक करने के लिए सेमफोर का उपयोग कर रहा हूं।

void Schedule(boost::function<void()> function) 
{ 
    semaphore.wait(); 
    io_service.post(boost::bind(&TaskWrapper, function)); 
} 

void TaskWrapper(boost::function<void()> &function) 
{ 
    function(); 
    semaphore.post(); 
} 
1

आप किसी अन्य लैम्ब्डा जो "में प्रगति" कार्यों की गिनती की देखभाल करेंगे में अपने लैम्ब्डा लपेट कर सकते हैं, और फिर अगर वहाँ भी कई में प्रगति कार्य हैं पोस्ट करने से पहले इंतजार: निम्नलिखित कोड इस समाधान को वर्णन ।

उदाहरण:

#include <atomic> 
#include <chrono> 
#include <future> 
#include <iostream> 
#include <mutex> 
#include <thread> 
#include <vector> 
#include <boost/asio.hpp> 

class ThreadPool { 
    using asio_worker = std::unique_ptr<boost::asio::io_service::work>; 
    boost::asio::io_service service; 
    asio_worker service_worker; 
    std::vector<std::thread> grp; 
    std::atomic<int> inProgress = 0; 
    std::mutex mtx; 
    std::condition_variable busy; 
public: 
    ThreadPool(int threads) : service(), service_worker(new asio_worker::element_type(service)) { 
    for (int i = 0; i < threads; ++i) { 
     grp.emplace_back([this] { service.run(); }); 
    } 
    } 

    template<typename F> 
    void enqueue(F && f) { 
    std::unique_lock<std::mutex> lock(mtx); 
    // limit queue depth = number of threads 
    while (inProgress >= grp.size()) { 
     busy.wait(lock); 
    } 
    inProgress++; 
    service.post([this, f = std::forward<F>(f)]{ 
     try { 
     f(); 
     } 
     catch (...) { 
     inProgress--; 
     busy.notify_one(); 
     throw; 
     } 
     inProgress--; 
     busy.notify_one(); 
    }); 
    } 

    ~ThreadPool() { 
    service_worker.reset(); 
    for (auto& t : grp) 
     if (t.joinable()) 
     t.join(); 
    service.stop(); 
    } 
}; 

int main() { 
    std::unique_ptr<ThreadPool> pool(new ThreadPool(4)); 
    for (int i = 1; i <= 20; ++i) { 
    pool->enqueue([i] { 
     std::string s("Hello from task "); 
     s += std::to_string(i) + "\n"; 
     std::cout << s; 
     std::this_thread::sleep_for(std::chrono::seconds(1)); 
    }); 
    } 
    std::cout << "All tasks queued.\n"; 
    pool.reset(); // wait for all tasks to complete 
    std::cout << "Done.\n"; 
} 

आउटपुट:

Hello from task 3 
Hello from task 4 
Hello from task 2 
Hello from task 1 
Hello from task 5 
Hello from task 7 
Hello from task 6 
Hello from task 8 
Hello from task 9 
Hello from task 10 
Hello from task 11 
Hello from task 12 
Hello from task 13 
Hello from task 14 
Hello from task 15 
Hello from task 16 
Hello from task 17 
Hello from task 18 
All tasks queued. 
Hello from task 19 
Hello from task 20 
Done. 
0

हो सकता है कि इतना है कि एक बार कार्यकर्ता धागे व्यस्त हो वे मुख्य थ्रेड और प्रणाली आत्म सीमा भूखा मुख्य थ्रेड की प्राथमिकता कम करने की कोशिश।