سؤال

مشكلة في عبارة:

لطلبي، ولدي الطبقة التي تقرأ من منفذ تسلسلي. ويستخدم الأوليات ويندوز للتعامل مع منفذ COM وكان موضوع القراءة غير متزامن. أحاول تحويل هذا بعيدا عن الأوليات ويندوز باستخدام مكتبات تفعيل مثل Boost.Asio وBoost.Thread.

في ميناء ويندوز، وكان لي موضوع IO عدة متغيرات CEvent MFC، كل منها يمثل رسالة: قراءة المطلوبة، كتابة طلب، قراءة الانتهاء من كتابة الانتهاء، IO ملغاة. وقد انتظرت هذه على مع WaitForMultipleObjects.

والمشكلة لدي هي أن Boost.Thread يبدو أن نظائرها للا CEvent ولا WaitForMultipleObjects. أقرب جئت هو عن طريق تجاهل هذه استبدال والأحداث مع مجموعة من القيم المنطقية، ومن ثم استخدام condition_variable، التي لديها وظيفتها notify_all () يسمى كلما التغييرات منطقية.

ولكن، دفعة :: يختلف condition_variable في اتجاه واحد الحرجة من CEvent: إذا كان يشير الى CEvent في حين لم يتم انتظرت على، ثم الانتظار المقبل على أنه نجح على الفور. مع دفعة :: condition_variable، أي إعلام يتم تجاهل وظيفة إذا لم يكن الانتظار.

وهذا يعني أن هناك دائما فجوة بين التحقق من والأعلام وتنتظر condition_variable التي إخطارا يمكن أن تضيع. يؤدي هذا موضوع معطلا.

لا أحد يعرف من حل لهذه المشكلة؟

مشكلة في التعليمات البرمجية:

// Old IO Thread
CEvent msg_cancel;
CEvent msg_read_req;
CEvent msg_write_req;
CEvent msg_read_comp;
CEvent msg_write_comp;

CEvent events[] = { 
    msg_cancel, 
    msg_read_req, 
    msg_write_req,
    msg_read_comp,
    msg_write_comp
};

bool cancel = false;

while (!cancel)
{
    switch(WaitForMultipleObjects(5, events, false, INFINITE))
    {
        case WAIT_OBJECT_0 :
            // msg_cancel
            cancel = true;
            break;

        ...
     }
}

وكيف لمحاكاة ذلك في Boost.Thread؟

هل كانت مفيدة؟

المحلول

وكما قلت، لتشبه الحدث ويندوز على غرار ما تحتاجه شرط متغير بالإضافة إلى العلم منطقية. بالطبع يمكنك الجمع بين عدة أعلام منطقية في واحدة إذا كان يلبي احتياجاتك.

ولكن المشكلة التي ذكرتها (المتغيرات حالة عدم الحصول على دولة active حيث الانتظار سيعود فورا) وعادة ما تحل بهذه الطريقة:

condition-variable
mutex

main-thread:
  lock(mutex) { start condition-signaling-thread }
  while(some predicate) {
    condition-variable.wait(mutex)
    do-stuff
  }

condition-signaling-thread:
  loop:      
    lock(mutex) {
      do-whatever
    }
    condition-variable.notify();

وخلال وجود الخيط الثاني إلى الانتظار حتى يتم مقفلة مزامنة بواسطة الخيط الذي سيتم التعامل مع حالة يمكنك التأكد من أن يتم التعامل مع كل حالة. (ملاحظة: في جافا إعلام الأسلوب () ليتم استدعاؤها داخل القفل، التي، اعتمادا على تفاصيل التنفيذ، يمكن أن يؤدي إلى أداء أسوأ في حال القيام به في C ++، ولكن يضمن أن مبرمج لديه على الأقل مرة واحدة التفكير حول كيفية مزامنة اطلاق النار من حالة مع المتلقي).

والسبب boost.thread لا تقدم الأحداث على غرار ويندوز (وPOSIX-الإشارات، راجع للشغل) هو أن هؤلاء البدائيون تجعل من السهل جدا أن المسمار. إذا كنت لا تخطط لميناء طلبك إلى منصة أخرى، والتكيف مع التطبيق الخاص بك لهذا نمط مختلف قد لا يكون يستحق كل هذا العناء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top