פתרון מנהל האובייקטים ומרחב השמות¶
לאחר DuplicateHandle קיימות שתי הפניות לאותו event. סגירת first מורידה הפניה אחת, אך second עדיין מאפשרת שימוש לפי הזכויות שקיבלה. מצב האיתות שייך לאובייקט, ולא למשתנה שמחזיק את המספר.
ביצירת event שני ללא שם מתקבלים שני אובייקטים. איתות לראשון אינו משנה את מצב השני, ולכן המתנה לשני עם timeout אפס מחזירה WAIT_TIMEOUT כל עוד לא סומן בנפרד.
התוכנית השנייה בניסוי השם יכולה להיות התוכנית המלאה הבאה. מעבירים לה את השם שהראשונה הדפיסה, ומשאירים את הראשונה חיה וממתינה.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <cstdio>
int wmain(int argc, wchar_t** argv) {
if (argc != 2) return 1;
HANDLE event = OpenEventW(EVENT_MODIFY_STATE, FALSE, argv[1]);
if (!event) {
std::printf("open error=%lu\n", GetLastError());
return 2;
}
const BOOL success = SetEvent(event);
const DWORD error = success ? 0 : GetLastError();
CloseHandle(event);
if (!success) std::printf("set error=%lu\n", error);
return success ? 0 : 3;
}
הזכות EVENT_MODIFY_STATE מספיקה לאיתות; התוכנית השנייה אינה מבקשת זכות המתנה מפני שאינה ממתינה. העיקרון הוא לבקש את הזכויות הדרושות לפעולה, ולא תמיד גישה מרבית.
בתוכנית הראשונה מדפיסים את השם לפני המתנה עם timeout מוגדר, ובודקים את כל תוצאות ההמתנה. סגירת ה־handle של השנייה אינה משמידה את האירוע כל עוד הראשונה עדיין מחזיקה בו.
המספר של handle הוא ערך שהמערכת מפרשת בהקשר טבלת handles. קבלת אותו מספר בתהליך אחר אינה מעידה על אותה רשומה. גם באותו תהליך, שימוש חוזר בערך אחרי סגירה יכול להפנות לאובייקט אחר, ולכן בדיקת מספר שווה לערך ישן אינה הוכחת זהות.
מדיניות דחייה על ERROR_ALREADY_EXISTS מתאימה לניסוי שבו אנחנו דורשים אובייקט חדש. מערכת שצריכה להיפגש עם אובייקט קיים חייבת להגדיר מי יוצר אותו, אילו הרשאות יש לו ואיך מוודאים שמדובר בישות המצופה. ההחלטה מגיעה לפני פעולת CreateEvent, ולא אחרי שהאובייקט כבר שימש להעברת מידע.