פתרון המתנה וקריאות APC¶
ה־callback פועל ב־thread הנוכחי, והקריאות למונה נעשות לפני ואחרי ההמתנה באותו thread. אין שתי גישות בו זמנית מ־threads שונים. עם זאת, קריאה חוזרת לרכיב באמצע פעולה יכולה להפר אינווריאנט גם בלי data race.
אפשר להוסיף בתחילת wait_with_deadline את הענף הבא. הוא ממשיך אחרי APC ואינו הופך אותו להצלחה של ההמתנה לאובייקט.
if (timeout_ms == INFINITE) {
for (;;) {
const DWORD result = WaitForSingleObjectEx(event, INFINITE, TRUE);
if (result != WAIT_IO_COMPLETION) return result;
}
}
ב־timeout אפס הפונקציה בודקת את המצב הנוכחי בלי להמתין לעתיד. אירוע מסומן יכול להחזיר הצלחה גם כאשר deadline הגיע. זו בחירת חוזה שצריך לתעד; קוד שדורש איסור מוחלט על הצלחה אחרי deadline צריך להגדיר אחרת את נקודת ההכרעה.
| תוצאה | פירוש |
|---|---|
| הצלחת אובייקט | התנאי הרלוונטי התקיים, ולעיתים גם נצרכה יחידה או הועברה בעלות |
| פקיעת זמן | ההמתנה הסתיימה בלי קבלת התנאי במסגרת החוזה |
| השלמת APC | הופעלה פעולה מתאימה במהלך המתנה alertable; האובייקט המקורי לא בהכרח מסומן |
| בעלות נטושה | התקבל mutex שבעליו הסתיים בלי שחרור רגיל; המצב המוגן דורש טיפול |
| כשל המתנה | יש לאסוף מיד את GetLastError לפי חוזה הפעולה |
כשל reentrancy אפשרי כאשר רשימה כבר שינתה מונה אבל עדיין לא קישרה את האיבר החדש, ואז הקוד נכנס להמתנה alertable. פעולת callback שסורקת את הרשימה רואה מצב לא עקבי. התיקון יכול להיות הוצאת ההמתנה אל מחוץ לשלב העדכון והעברת callback לתור עבודה מוגדר.
ה־context נשאר נחוץ כל עוד callback יכול להגיע אליו. הצלחת queue היא אישור שהבקשה נרשמה, לא אישור שהיא הסתיימה. אם אין מנגנון ביטול ו־drain מתאים, צריך לבנות בעלות שמחזיקה את המצב עד נקודת סיום ידועה.