अलावा तथ्य यह है कि आप अपने विशिष्ट मामले में निर्माता से फेंक क्योंकि pthread_mutex_lock
actually returns an EINVAL if your mutex has not been initialized और आप lock
करने के लिए कॉल के बाद फेंक कर सकते हैं के रूप में std::mutex
में किया जाता है की जरूरत नहीं है से:
void
lock()
{
int __e = __gthread_mutex_lock(&_M_mutex);
// EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may)
if (__e)
__throw_system_error(__e);
}
तो में कंस्ट्रक्टर्स से सामान्य फेंक ठीक निर्माण के दौरान अधिग्रहण त्रुटियों के लिए है, और आरए II (संसाधन-प्राप्ति-है-प्रारंभ) प्रोग्रामिंग प्रतिमान के अनुपालन में।
चेक इन बयानों पर इस example on RAII
void write_to_file (const std::string & message) {
// mutex to protect file access (shared across threads)
static std::mutex mutex;
// lock mutex before accessing file
std::lock_guard<std::mutex> lock(mutex);
// try to open file
std::ofstream file("example.txt");
if (!file.is_open())
throw std::runtime_error("unable to open file");
// write message to file
file << message << std::endl;
// file will be closed 1st when leaving scope (regardless of exception)
// mutex will be unlocked 2nd (from lock destructor) when leaving
// scope (regardless of exception)
}
फोकस:
static std::mutex mutex
std::lock_guard<std::mutex> lock(mutex);
std::ofstream file("example.txt");
पहला कथन आरएआईआई और noexcept
है।में (2) यह स्पष्ट है कि lock_guard
पर RAII लागू किया गया है और यह वास्तव में throw
कर सकता है, जबकि (3) ofstream
में RAII नहीं लगता है, क्योंकि ऑब्जेक्ट्स को is_open()
पर कॉल करके चेक किया जाना चाहिए जो failbit
ध्वज को चेक करता है।
पहली नज़र में ऐसा लगता है कि यह ओ पी कार्यान्वयन के विपरीत यह मानक तरीका और पहले मामले std::mutex
में प्रारंभ में फेंक नहीं है क्या पर दुविधा में पड़ा हुआ है, * *। दूसरे मामले में यह std::mutex::lock
से जो भी फेंक दिया गया है उसे फेंक देगा, और तीसरे में कोई फेंक नहीं होगा।
सूचना मतभेद:
(1) स्थिर घोषित किया जा सकता है, और वास्तव में एक सदस्य चर (2) वास्तव में एक सदस्य चर के रूप में घोषित करने की कभी नहीं की उम्मीद होगी के रूप में घोषित किया जाएगा (3) है सदस्य चर के रूप में घोषित होने की उम्मीद है, और अंतर्निहित संसाधन हमेशा उपलब्ध नहीं हो सकता है।
ये सभी रूप RAII हैं; इसे हल करने के लिए, किसी को RAII का विश्लेषण करना होगा।
- संसाधन: अपनी वस्तु
- अधिग्रहण (आवंटन): यदि आप बनाया जा रहा वस्तु
- प्रारंभ: अपने ऑब्जेक्ट को उसके अपरिवर्तनीय राज्य में है
यह प्रारंभ करने की आवश्यकता नहीं है और निर्माण पर सब कुछ कनेक्ट करें। उदाहरण के लिए जब आप एक नेटवर्क क्लाइंट ऑब्जेक्ट बनाते हैं तो आप इसे सृजन पर सर्वर से कनेक्ट नहीं करेंगे, क्योंकि यह असफलताओं के साथ धीमा संचालन है। इसके बजाय आप ऐसा करने के लिए connect
फ़ंक्शन लिखेंगे। दूसरी ओर आप बफर बना सकते हैं या बस अपना राज्य सेट कर सकते हैं।
इसलिए, आपकी समस्या आपके शुरुआती राज्य को परिभाषित करने के लिए उबलती है। यदि आपके मामले में आपकी प्रारंभिक स्थिति है mutex को प्रारंभ किया जाना चाहिए तो आपको कन्स्ट्रक्टर से फेंकना चाहिए। इसके विपरीत यह ठीक है कि शुरूआत न करें (जैसा कि std::mutex
में किया गया है), और म्यूटेक्स के रूप में आपके इनविरिएंट स्टेट को परिभाषित करें। किसी भी हाल में अपरिवर्तनीय उसके सदस्य वस्तु के राज्य द्वारा जरूरी compromized नहीं है, Mutex
सार्वजनिक तरीकों Mutex::lock()
और Mutex::unlock()
के माध्यम से locked
और unlocked
के बीच mutex_
वस्तु mutates के बाद से।
class Mutex {
private:
int e;
pthread_mutex_t mutex_;
public:
Mutex(): e(0) {
e = pthread_mutex_init(&mutex_);
}
void lock() {
e = pthread_mutex_lock(&mutex_);
if(e == EINVAL)
{
throw MutexInitException();
}
else (e) {
throw MutexLockException();
}
}
// ... the rest of your class
};
संबंधित विषय पर एक और लिंक: http://www.writeulearn.com/exception-constructor/ –
ठीक है, यह किसी अन्य समारोह से जितना ज्यादा है, उतना ही ठीक है, यह कहा जा रहा है कि आपको देखभाल के साथ फेंकना चाहिए किसी भी समारोह से। – g24l
कुछ असंबंधित: क्यों नहीं अपने लॉक/अनलॉक विधियों को हटा रहा है, और सीधे म्यूटेक्स को कन्स्ट्रक्टर में लॉक करें और विनाशक में अनलॉक करें?इस तरह एक स्कोप में स्वचालित रूप से एक ऑटो वैरिएबल घोषित करना स्वचालित रूप से लॉक/अनलॉक, अपवादों, रिटर्न इत्यादि की देखभाल करने की कोई आवश्यकता नहीं है ... इसी तरह के कार्यान्वयन के लिए 'std :: lock_guard' देखें। –