سأتحدث اليوم باختصار عن كيفية تطبيق إشارة على أساس كائن التزامن "حدث".
أولا الذهاب من خلال التعاريف.
1. ما هو التزامن ولماذا هو مطلوب؟
من الواضح ، يمكننا تنفيذ مجموعة من الإجراءات بعدة طرق. أبسط - بالتتابع وبالتوازي. يمكن تحقيق التنفيذ الموازي لبعض الإجراءات من خلال تشغيل العديد من مؤشرات الترابط. الفكرة بسيطة: قم بتعيين إجراء أولي (أو غير ذلك) لكل مؤشر ترابط وتشغيله بترتيب معين. بشكل عام ، يمكننا إطلاقها جميعًا في نفس الوقت - بالطبع ، سوف نحقق مكاسب في الوقت المناسب. هذا أمر مفهوم: إنه شيء واحد إخراج 10000 كلمة واحدة تلو الأخرى ، وشيء آخر لإخراج في وقت واحد ، على سبيل المثال ، 100 كلمة. كسب الوقت 100 مرة (زائد أو ناقص ، باستثناء التأخير ، وما إلى ذلك). لكن المهمة الأصلية قد تنطوي على تسلسل صارم من الإجراءات.
على سبيل المثال:
- فتح الملف
- اكتب النص للملف
- أغلق الملف
تم أخذ مثال الدفيئة بشكل خاص (من الواضح أنه لا توجد حاجة إلى التوازي هنا ، كل شيء يمكن القيام به ببساطة بالتتابع) ، ولكن كمهمة تدريب ستعمل تمامًا ، والأهم من ذلك ، أن الحاجة إلى التنفيذ المتسق تظهر بوضوح في مثالها. أو هنا مثال آخر ، مختلف قليلاً:
- توليد ثلاث سلاسل من الأرقام العشوائية
- عرضها بالتتابع
هنا ، يمكن تنفيذ النقطة الأولى في وقت واحد بثلاثة مؤشرات ترابط مختلفة ، ولكن يجب أن يتم تنفيذ النقطة الأخيرة بالتسلسل ، وفقط بعد تحديد النقطة الأولى.
بشكل عام ، يمكن أن تكون مهام التوازي مختلفة تمامًا وهناك حاجة إلى أداة لمزامنة مؤشرات الترابط.
2. أدوات لمزامنة الصفحات
يقوم Windows.h بتنفيذ عدد كبير من أدوات المزامنة العادية (ما يسمى بـ "كائنات المزامنة"). من بين أهمها: المنطقة الحرجة ، الحدث ، الموتكس ، الإشارة. نعم ، بالنسبة للإشارة يوجد بالفعل تطبيق في windows.h. "فلماذا البرنامج؟" حسنًا ، أولاً ، للحصول على شعور أفضل لكيفية عملها. وثانيا ، الممارسة الإضافية لـ C ++ لم توقف أي شخص حتى الآن :)
بالنظر إلى أننا سوف نستخدم الأحداث ، سنشرح ما هو وكيفية استخدامها.
تستخدم الأحداث لإخطار المواضيع المعلقة. هذا هو ، في الواقع ، هذه بعض الإشارات للتدفق - يمكن تشغيلها أو لا بعد. من المعنى الحقيقي لهذا الكائن ، يترتب على ذلك أنه يحتوي على حالة إشارة وقدرة على ضبطه (إعادة ضبط / "تشغيل").
لذلك ، بعد توصيل windows.h ، يمكننا إنشاء حدث باستخدام:
HANDLE CreateEvent ( LPSECURITY_ATTRIBUTES lpEventAttributes,
إذا نجحت الوظيفة ، فسيتم إرجاع مؤشر الحدث. إذا تعذر إنشاء الكائن ، فسيتم إرجاع NULL.
لتغيير حالة الحدث للإشارة ، نستخدم الوظيفة:
BOOL SetEvent ( HANDLE hEvent
إذا نجحت ، فسوف تُرجع قيمة غير صفرية.
الآن عن الإشارة. تم تصميم الإشارة للسيطرة على عدد مؤشرات الترابط قيد التشغيل في وقت واحد. لنفترض أن لدينا 1000 مؤشر ترابط ، ولكن 2 فقط يمكن أن تعمل في وقت واحد ، وهذا هو نوع التعديل الذي يحدث بمساعدة إشارة. وما هي الوظائف التي يتم تنفيذها للعمل مع كائن المزامنة هذا؟
لإنشاء إشارة ، مشابهة للأحداث:
HANDLE CreateSemaphore ( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
إذا نجح ، نحصل على مؤشر إلى الإشارة ، وإذا فشل ، سنحصل على NULL.
يتغير عداد الإشارة بشكل مستمر (مؤشر الترابط قيد التشغيل ويظهر مكان شاغر) ، لذلك يجب تغيير حالة الإشارة بشكل دوري. يتم ذلك باستخدام هذه الوظيفة:
BOOL ReleaseSemaphore ( HANDLE hSemaphore,
إذا نجحت ، فإن قيمة الإرجاع ليست صفراً.
يستحق أيضًا الانتباه إلى الوظيفة:
DWORD WaitForSingleObject( HANDLE hHandle,
من بين القيم التي تم إرجاعها ، نحن مهتمون بشكل خاص بـ 2: WAIT_OBJECT_0 - يعني أن حالة كائننا هي إشارة ؛ WAIT_TIMEOUT - لم ننتظر حالة الإشارة من الكائن في الوقت المخصص.
3. المهمة نفسها
في المجموع ، مهمتنا هي كتابة نظائرنا على وظائف منتظمة. لن نقوم بتعقيد المهمة كثيرًا ، وسوف نجعل "التنفيذ في التقريب الأول". الشيء الرئيسي هو الحفاظ على الخصائص الكمية للإشارة القياسية. يمكن العثور على الكود مع التعليقات على
جيثب .
نظرًا لبساطة المهمة نفسها ، لن نعقد هذه المقالة بشكل خاص ، ولكن قد يكون مفيدًا لشخص ما :)