2011-11-14 24 views
9

The description of AutoResetEvent in MSDNलिनक्स के तहत AutoResetEvent के लिए C++ समकक्ष क्या है?

मैं लिनक्स के तहत सी # से सी ++ में लागू एक थ्रेड पूल पोर्ट करने की कोशिश कर रहा हूं। मुझे नहीं पता कि मुझे कौन से फ़ंक्शंस का उपयोग करना चाहिए जिसका "AutoResetEvent" के समान व्यवहार हैं।

उत्तर

11

एक AutoResetEvent एक बाइनरी सेमाफोर करने के लिए सबसे समान है। लोग कहते हैं कि "सशर्त चर" गलत नहीं हैं, लेकिन इसी तरह की स्थितियों के बजाय, समान परिस्थितियों में हालत चर का उपयोग किया जाता है। आप शर्त चर के शीर्ष पर एक (बेनाम) AutoResetEvent लागू कर सकते हैं:

#include <pthread.h> 
#include <stdio.h> 

class AutoResetEvent 
{ 
    public: 
    explicit AutoResetEvent(bool initial = false); 

    ~AutoResetEvent(); 
    void Set(); 
    void Reset(); 

    bool WaitOne(); 

    private: 
    AutoResetEvent(const AutoResetEvent&); 
    AutoResetEvent& operator=(const AutoResetEvent&); // non-copyable 
    bool flag_; 
    pthread_mutex_t protect_; 
    pthread_cond_t signal_; 
}; 

AutoResetEvent::AutoResetEvent(bool initial) 
: flag_(initial) 
{ 
    pthread_mutex_init(&protect_, NULL); 
    pthread_cond_init(&signal_, NULL); 
} 

void AutoResetEvent::Set() 
{ 
    pthread_mutex_lock(&protect_); 
    flag_ = true; 
    pthread_mutex_unlock(&protect_); 
    pthread_cond_signal(&signal_); 
} 

void AutoResetEvent::Reset() 
{ 
    pthread_mutex_lock(&protect_); 
    flag_ = false; 
    pthread_mutex_unlock(&protect_); 
} 

bool AutoResetEvent::WaitOne() 
{ 
    pthread_mutex_lock(&protect_); 
    while(!flag_) // prevent spurious wakeups from doing harm 
    pthread_cond_wait(&signal_, &protect_); 
    flag_ = false; // waiting resets the flag 
    pthread_mutex_unlock(&protect_); 
    return true; 
} 

AutoResetEvent::~AutoResetEvent() 
{ 
    pthread_mutex_destroy(&protect_); 
    pthread_cond_destroy(&signal_); 
} 


AutoResetEvent event; 

void *otherthread(void *) 
{ 
    event.WaitOne(); 
    printf("Hello from other thread!\n"); 
    return NULL; 
} 


int main() 
{ 
    pthread_t h; 
    pthread_create(&h, NULL, &otherthread, NULL); 
    printf("Hello from the first thread\n"); 
    event.Set(); 

    pthread_join(h, NULL); 
    return 0; 
} 

यदि फिर भी, आप स्वत: रीसेट घटनाओं नामित की जरूरत है, आप की संभावना सेमाफोर को देखने के लिए चाहता हूँ, और एक से थोड़ा अधिक कठिन समय अनुवाद हो सकता है तुम्हारा कोड। किसी भी तरह से मैं आपके प्लेटफ़ॉर्म पर पर्थ्रेड के लिए प्रलेखन पर सावधान रहूंगा, हालत चर और ऑटो रीसेट ईवेंट समान नहीं हैं और वही व्यवहार नहीं करते हैं।

0

ठीक है, बाधाएं यह एक म्यूटेक्स की तरह हैं - आपके पास साझा संसाधनों के लिए कई कॉलर जा रहे हैं, लेकिन केवल एक को अनुमति है। म्यूटेक्स मामले में, कॉलर्स म्यूटेक्स (उदाहरण के लिए phtread_mutex_lock) प्राप्त करने का प्रयास करेंगे। , अपनी बात करें, फिर रिलीज करें (pthread_mutex_unlock) ताकि कुछ अन्य कॉलर अंदर जा सकें।

+1

नहीं, यह बिल्कुल म्यूटेक्स की तरह नहीं है। यह एक शर्त चर की तरह है। – Gabe

3

मुझे पूरा यकीन है कि आप हालत चर की तलाश में हैं। इस अन्य एसओ प्रश्न का स्वीकार्य उत्तर: Condition variables in C# - इसकी पुष्टि करने लगता है।

उदा। देखें POSIX धागे में स्थिति चर पर विवरण के लिए this tutorial

+1

माइक्रोसॉफ्ट "लाइब्रेरीज़", "प्लेटफार्म" और "भाषाओं" के बीच भेद को एक बड़े गड़बड़ी में धुंधला करना पसंद करता है जो आपको "माइक्रोसॉफ्ट खरीदने" के लिए मजबूर करता है। वास्तव में, .NET में "AutoResetEvent" कक्षा Win32 में आदिम "इवेंट" के आसपास एक रैपर है, और PThreads में "हालत चर" के समान है। लिनक्स के लिए PThreads जानें। लिनक्स के अलावा अन्य प्लेटफॉर्म पर PTHreads का उपयोग किया जा सकता है, और सी ++ के अलावा अन्य भाषाओं (सी, पायथन, इत्यादि) के साथ। – paulsm4

+0

बस सोच रहा है, क्या इसे बढ़ावा देने के लिए इसे कार्यान्वित करना आसान होगा: थ्रेड लाइब्रेरी? – derekhh

+0

@ डेरेख: मुझे "आसान" के बारे में पता नहीं है, हालत चर एक काफी सरल निर्माण हैं, लेकिन यदि आप पहले से ही बूस्ट :: थ्रेड का उपयोग कर रहे हैं (जो आईएमओ पूरी तरह से अच्छी पसंद है), हर तरह से इसकी स्थिति चर का उपयोग करें रैपर, यह आपके शेष कोड के साथ ठीक से फिट होगा: http://www.boost.org/doc/libs/1_47_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref –

2

आप आसानी से POSIX mutexes और हालत चर का उपयोग कर Win32 API ईवेंट ऑब्जेक्ट को पुन: कार्यान्वित कर सकते हैं।

हालांकि कुछ टिप्पणियों को ऊपर मुझे इस राज्य बनाने:

एक शर्त चर अनुरूप नहीं एक घटना वस्तु है। एक शर्त चर मूल रूप से किसी ईवेंट से अलग है जिसमें इसकी स्मृति या स्थिति नहीं है, इस अर्थ में कि अगर pthread_cond_signal या pthread_cond_broadcast पर कॉल करने वाले किसी भी स्थिति में कोई भी अवरुद्ध नहीं होता है, तो विशेष रूप से कुछ भी नहीं होगा यदि कोई धागा बाद में pthread_cond_wait के माध्यम से ब्लॉक करने के लिए आता है तो यह ब्लॉक होगा।

I'l एक त्वरित ऑटो रीसेट घटना कार्यान्वयन स्केच करने का प्रयास करें:

class event 
{ 
public: 
    event(): signalled_ (false) {} 

    void signal() 
    { 
    std::unique_lock<std::mutex> lock(mutex_); 
    signalled_ = true; 
    cond_.notify_one(); 
    } 

    void wait() 
    { 
    std::unique_lock<std::mutex> lock(mutex_); 

    while (!signalled_) 
     cond_.wait (lock); 
    signalled_ = false; 
    } 

protected: 
    std::mutex mutex_; 
    std::condition_variable cond_; 
    bool signalled_; 
}; 
1

सशर्त चर ऑटोरसेट इवेंट के बराबर नहीं हैं। वे मॉनीटर के बराबर हैं। अंतर महत्वपूर्ण है और यदि सही तरीके से उपयोग नहीं किया जाता है तो डेडलॉक्स का कारण बन सकता है:

एक सी # प्रोग्राम में दो थ्रेड ए और बी की कल्पना करें। एक कॉल WaitOne() और बी कॉल सेट()। यदि बी प्रतीक्षा करें() को प्रतीक्षा करें (ए) से कॉल तक पहुंचने से पहले, कोई समस्या नहीं है क्योंकि सेट() द्वारा AutoResetEvent() को भेजा गया सिग्नल लगातार है और यह एक WaitOne() निष्पादित होने तक सेट रहेगा।

अब सी में, दो धागे सी और डी सी कॉल प्रतीक्षा करें(), डी कॉल अधिसूचित()। यदि सी पहले से प्रतीक्षा कर रहा है जब डी कॉल अधिसूचित() सब कुछ ठीक है। यदि सी कॉल कॉल() से पहले प्रतीक्षा() तक पहुंचने के लिए सी प्रबंधित नहीं किया गया है, तो आपके पास डेडलॉक है क्योंकि सिग्नल खो जाता है अगर कोई इसका इंतजार नहीं कर रहा है और सशर्त चर की स्थिति अभी भी "अनसेट" है।

इस बारे में बहुत सावधान रहें।

1

बूस्ट का धागा/स्थिति प्रलेखन से उदाहरण बहुत सामान्य ManualResetEvent और AutoResetEvent उपयोग के समान है: http://www.boost.org/doc/libs/1_53_0/doc/html/thread/synchronization.html#thread.synchronization.condvar_ref

boost::condition_variable cond; 
boost::mutex mut; 
bool data_ready; 

void wait_for_data_to_process() 
{ 
    boost::unique_lock<boost::mutex> lock(mut); 
    while(!data_ready) 
    { 
     cond.wait(lock); 
    } 
} 

void prepare_data_for_processing() 
{ 
    { //scope for lock_guard 
     boost::lock_guard<boost::mutex> lock(mut); 
     data_ready=true; 
    } 
    cond.notify_one(); 
} 

नोट स्थिति प्रदान कि (मैं स्पष्टता के लिए कुछ छोटे संपादन करने के बाद) AutoResetEvent और ManualResetEvent के तंत्र को प्रतीक्षा/सूचित करें लेकिन काम करने के लिए एक म्यूटेक्स की आवश्यकता है।

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