2012-10-12 13 views
5

के रूप में एक सदस्य फ़ंक्शन का उपयोग करें मेरे पास एक ऑब्जेक्ट है जो कुछ अंतहीन लूप में काम करता है। main() ऑब्जेक्ट को तुरंत चालू करता है और run() विधि को कॉल करता है। चूंकि मैं धागे का उपयोग नहीं करना चाहता, इसलिए मुझे अपना ऑब्जेक्ट बंद करने के लिए एक समाधान की आवश्यकता है। नीचे आप देखते हैं कि मैं किसके साथ आया हूं।सिग्नल सिग्नल: सिग्नल हैंडलर

struct Foo 
{ 
    void run() 
    { 
     running = 1; 
     while (running) 
      do_something_useful(); 

     std::cout << "Execution stopped." << std::endl; 
    } 

    bool running; 

    void catch_signal(int signal) 
    { 
     std::cout << "Caught signal " << signal << std::endl; 
     if(signal == SIGTERM) 
      running = false; 
    } 

}; 

जैसा कि आप देखते हैं, मुझे सिग्नल को असंकालिक रूप से भेजने की आवश्यकता है। इसलिए, मैं सिग्नल हैंडलर और sigaction का उपयोग करता हूं। main के नीचे मैं उपयोग करने की कल्पना कर सकता हूं।

int main(int argc, char** argv) 
{ 
    Foo foo; 
    struct sigaction sigIntHandler; 

    boost::function< void (int) > f; 
    f = std::bind1st(
     std::mem_fun(&Foo::catch_signal), &foo); 
    f(5); // this call works 

    sigIntHandler.sa_handler = f;   // compiler complains, "cannot assign ..." 
    sigemptyset(&sigIntHandler.sa_mask); 
    sigIntHandler.sa_flags = 0; 
    sigaction(SIGTERM, &sigIntHandler, NULL); 
    s.run(); 

} 

क्या मैं अब उम्मीद करेंगे: कार्यक्रम चलाता है जब तक मैं SIGTERM जो पकड़ा जाता है और मेरे वस्तु का कारण यात्रा रोकने के लिए और मुख्य पर लौटने के लिए होगा भेजें।

मैं अब दो प्रश्न हैं:

(क) कोड आप एक लाइन के साथ "संकलक शिकायत" चिह्नित देखने में, संदेश है

boost::function<void(int)> cannot be converted to __sighandler_t {aka void (*)(int)} 

क्या मैं बनाने के लिए बदलने की जरूरत है की तरह इस काम? मुझे लगता है कि fvoid f(int) जैसा है, सिग्नल हैंडलर कुछ उदाहरणों में किए गए कार्यों की तरह है।

(बी) आप में से उन लोगों के लिए जो आश्चर्य करते हैं कि "वह लड़का क्या कर रहा है?": क्या आपको कोई सलाह है कि इस तरह की चीज़ को बेहतर तरीके से कैसे हल किया जाए?

+0

जिज्ञासा से बाहर, आप धागे का उपयोग क्यों नहीं करना चाहते हैं?हालांकि मैंने बूस्ट का उपयोग नहीं किया है, मेरी धारणा है कि यह कॉलबैक फ़ंक्शन प्रदान करने की अपेक्षा कर रहा है। – M4rc

+0

'थू में' फू :: रन() '' शुरू करने की तरह, 'मुख्य' में सिग्नल को पकड़ना और मुख्य कॉल sth। '' thread.terminate() '' की तरह? हां, एक संभावना होगी, लेकिन मैंने सोचा कि यह इसके लिए बहुत अधिक होगा। –

+0

यह निश्चित रूप से एक तरीका है। दूसरी बात यह है कि (सोचने के मेरे sedated miasma में) यह है कि आप जिस भी जानकारी की जरूरत है उसके साथ एक संरचना हो सकती है, इसे थ्रेड के रूप में पंजीकृत करें, ताकि आप इसमें सामान्य सामान्य कार्यों के साथ लूप चला सकें, और सिग्नल हैंडलर चल रहा हो अपने स्वयं के धागे पर, फिर आप यह देखने के लिए कि क्या कोई घटना हुई है, और यदि ऐसा है तो क्या घटना और उपयुक्त प्रतिक्रिया है, तो आप केवल मूल्य को पकड़ लें। – M4rc

उत्तर

7
  • मुझे यह काम करने के लिए बदलने की क्या ज़रूरत है? मुझे लगता है कि एफ शून्य एफ (int) की तरह है, जैसे सिग्नल हैंडलर कुछ उदाहरणों में काम करता है।

संकलक, प्रकार के बारे में शिकायत इसलिए आप एक समारोह सूचक, नहीं प्रकार boost::function<void(int)> की एक वस्तु पारित करने के लिए की जरूरत है। इस प्रकार के एक वैश्विक चर बनाना, और एक समारोह जो कहता है इस वस्तु काम करेगा जोड़ने:

boost::function<void(int)> myCb; 
void CallCb(int value) 
{ 
    myCb(value); 
} 

int main(int argc, char** argv) 
{ 
    Foo foo; 
    struct sigaction sigIntHandler; 

    myCb = std::bind1st(
     std::mem_fun(&Foo::catch_signal), &foo); 
    f(5); // this call works 

    sigIntHandler.sa_handler = CallCb; 
    sigemptyset(&sigIntHandler.sa_mask); 
    sigIntHandler.sa_flags = 0; 
    sigaction(SIGTERM, &sigIntHandler, NULL); 
    s.run(); 

} 
  • आप कैसे बात की बेहतर इस तरह हल करने के लिए किसी भी सलाह है?

वास्तव में नहीं। विचार ठीक है। मैं सिर्फ सी ++ 11 लैम्ब्डा के बजाय

+1

विशेष रूप से यह इंगित करने के लिए धन्यवाद कि 'f'' एक फ़ंक्शन नहीं है बल्कि एक ऑब्जेक्ट जिसे मैंने नहीं सोचा था। –

+0

क्या आप एक उदाहरण दे सकते हैं कि आप इसे सी ++ 11 लैम्ब्डा के साथ कैसे करेंगे? – Azmisov

2

बहुत कम है कि आप सिग्नल हैंडलर में पोर्टेबल कर सकते हैं। असल में, आप किसी ऑब्जेक्ट में एक मान संग्रहीत कर सकते हैं जिसका प्रकार sig_atomic_t है। cout में डालने के लिए, उदाहरण के लिए, काम नहीं करना है। यदि आपके पास सी ++ 11 है तो आप परमाणु प्रकार या स्पष्ट बाड़ का उपयोग करके थोड़ा और कर सकते हैं, लेकिन मानक लाइब्रेरी में किसी भी अन्य कॉल को समझदार कुछ भी करने की आवश्यकता नहीं है।

तो, जो भी कहा गया है, उसके साथ आप क्या कर सकते हैं, एक फ़ंक्शन लिखना (या तो एक नि: शुल्क फ़ंक्शन या स्थिर सदस्य फ़ंक्शन (लेकिन सी ++ लिंकेज के साथ यहां एक सूक्ष्म समस्या है: औपचारिक रूप से एक स्थिर सदस्य फ़ंक्शन काम नहीं करेगा , लेकिन व्यवहार में यह हमेशा करता है)) जो सदस्य फ़ंक्शन को कॉल करता है, जो बदले में running से false सेट करता है (मान लीजिए कि आपने running से sig_atomic_t का प्रकार बदल दिया है)।

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