2013-07-07 7 views
7

मैं एक काम बाद में निष्पादित करने के लिए शेड्यूल करने के लिए एक तरह से लागू करना चाहते हैं। इंटरफ़ेस जावास्क्रिप्ट के setTimeout(function, milliseconds) के समान होगा।सी ++ में देरी कार्यों

मेरे आवेदन में कुछ संसाधनों का धागा स्वामित्व है। दौड़ की स्थिति से बचने के लिए उन्हें हमेशा उसी धागे से एक्सेस किया जाना चाहिए। यदि अन्य धागे संसाधनों तक पहुंचना चाहते हैं तो उन्हें संसाधन थ्रेड पर कार्य ऑब्जेक्ट भेजना होगा।

तो दोनों समस्याओं मैं हल करने के लिए की जरूरत है:

  1. एक धागा
  2. देरी के लिए कोई कार्य प्रेषण मंगलाचरण

पहली समस्या जल्दी से एक ताला मुक्त कतार का उपयोग करके तय हो गई है उपभोग करने वाले पक्ष में संसाधन धागा है। (मैं टीबीबी के concurrent_bounded_queue का उपयोग करता हूं।) दूसरी समस्या हालांकि, मेरे लिए इतना स्पष्ट नहीं है। मैं दो रणनीतियों के बारे में सोच सकता हूं:

  1. प्रत्येक कार्य के लिए एक नया धागा प्रारंभ करें। यह धागा आवश्यक देरी सोएगा, फिर कार्य को समवर्ती कतार में प्रेषित करेगा।
  2. प्रारंभ केवल एक है जो एक पाश है कि अनुसूचित कार्यों iterates और उन्हें आह्वान करता है, तो उनके इंतज़ार कर समय समाप्त हो गया है चलाता है धागा।

मैंने दोनों दृष्टिकोणों के साथ प्रयोग किया है और मैं पहले पक्ष का पक्ष लेता हूं क्योंकि यह सरल और भरोसेमंद है, जबकि दूसरा सूक्ष्म बग के लिए अधिक प्रवण होता है। पहला दृष्टिकोण ओएस थ्रेड शेड्यूलर को यह प्रतिनिधि करता है।

हालांकि, पहला समाधान बहुत कम अल्पकालिक धागे बनाता है, जबकि मैं आमतौर पर धागे का पुन: उपयोग करने की सिफारिश सुनता हूं।

+0

समय पर निष्पादन के दूसरे दृष्टिकोण में कोई गारंटी नहीं है। कभी-कभी आपको दूसरे कार्य को निष्पादित करने से पहले एक कार्य को समाप्त करने की प्रतीक्षा करनी होगी। पहला दृष्टिकोण बेहतर है। –

+0

क्या धागे की संख्या वास्तव में बहुत अधिक होने जा रही है? कुछ हज़ारों हज़ारों की तरह? याद रखें कि सोते धागे 0 सीपीयू समय के करीब करीब उपभोग करते हैं। –

+0

@ BartekBanachewicz मेरे आवेदन में कई साथ-साथ निर्धारित कार्य नहीं होंगे। आमतौर पर वे हर एन मिलीसेकंड में एक क्रिया करेंगे। वे मरने से पहले खुद को पुन: स्थापित करके ऐसा करते हैं। – StackedCrooked

उत्तर

3

मैनुअल कार्यान्वयन नीचे की तरह कुछ हो जाएगा।

struct myrunnable { 
    uint64_t id_; 
    uint64_t stamp_; 
    std::function<void()> runnable_; 
    uint64_t id() { return id_; } 
    uint64_t stamp() { return stamp_; } 
    void execute() { if (runnable_) runnable_(); } 
}; 

typedef std::shared_ptr<myrunnable> task_t; 
// timestamp_cmp_t - a comparator by timestamp + incrementing task id 
typedef tbb::concurrent_blocking_queue<task_t> queue_t; 
typedef std::priority_queue<task, timestamp_cmp_t> schedule_t; 

uint64_t now(); // a wrapper around gettimeofday(), write yourself 

queue_t queue; // inbound concurrent blocking queue not bound in size 
schedule_t schedule; // priority queue, a scheduler 
// queue_t sink; // optional sink concurrent queue if you don't 
       // want to execute tasks in the scheduler thread context 

// now() - a wrapper around gettimeofday(), write yourself 
for(;;) { // "termination mark" comments below - exit points 
    while (!schedule.empty() && schedule.top().stamp() <= now()) { 
    task_t task = schedule.pop(); 
    task .execute(); 
    // alternatively sink.push(task) to offload scheduler thread 
    } 

    if (schedule.empty()) { 
    task_t task = queue.pop(); // block on the input queue 
    if (!task) return; // scheduler termination mark, empty task 
    schedule.push(task); 
    } else { 
    // Here we are driven by our latency/cpu balance requirements 
    // in this example we are ultra low latency and are just spinning CPU 
    // and on Linux such thread may need extra tuning to perform consistently. 
    // To pace it down one can use TBB's sleep_for() or select() system call 

    while (schedule.top().stamp() > now()) { 
     task_t task; 
     if (queue.try_pop(task)) { 
     if (!task) return; // scheduler termination mark, empty task 
     schedule.push(task); 
     } 
    } 
    } 
} 
+2

आप व्यस्त-प्रतीक्षा कर रहे हैं। यह वास्तव में अच्छा नहीं है। – SigTerm

+2

@ सिगटर्म - कस कताई लूप के ठीक ऊपर कोड में टिप्पणी स्पष्ट रूप से बताती है कि कताई, नॉप-आधारित कताई (टीबीबी :: sleep_for के माध्यम से), या सिस्टम के माध्यम से गहरी नींद सहित डेटा आने के कई तरीके हैं चयन() की तरह कॉल करें, जो 10ms से कम नहीं सो सकता, बीटीडब्ल्यू। आपको दुनिया को काले और सफेद रंग देखना बंद करना चाहिए :) – bobah

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