לדלג לתוכן

פתרון פרויקט מוצר טבעי ומנוהל

הפתרון משאיר את exports הקיימים ואת משמעותם יציבים. פונקציה חדשה או שדה size מאפשרים לגלות הרחבה בלי לקרוא מעבר למבנה שהcaller הקצה. החוזה קובע מי מאתחל שדות, מה מותר להתעלם ממנו ומה מחייב דחייה של גרסה.

הwrapper מחזיק SafeHandle למשאב וroot לcallback context. אם start נכשל לפני שהnative קיבל בעלות, הוא מנקה מיד. אם start הצליח, cleanup עובר דרך cancel לפי צורך ואז join. השלמת Task אינה מספיקה להוכיח שהcallback כבר חזר.

הclient הישן מול DLL חדשה משתמש רק בחוזה הישן ומקבל אותה משמעות תוצאה. הclient החדש מול DLL ישנה בודק capability ומציג דחייה מוגדרת או fallback שנבדק. חסרון export לא מתגלה לראשונה אחרי שהמשתמש כבר התחיל עבודה שלא ניתן לבטל.

הבדיקה של layout משווה sizeof וoffset של כל שדה שנמסר בין השפות. היא כוללת bool, BOOL, pointer ורוחב אורך. מעבר בcompiler של צד אחד אינו מעיד על הצד השני, ובדיקה על x64 אינה מאמתת אוטומטית x86.

הדליפה המנוהלת נבדקת אחרי כמה מחזורי start, completion וDispose. מחפשים root שמחזיק delegate, state או owner ישן. אין מתקנים אותה באמצעות GC.Collect קבוע; מסירים את שרשרת הבעלות שכבר אינה נחוצה.

ההגשה מקשרת ABI, lifetime והפצה. אם DLL חדשה נפרסת לצד wrapper ישן, אותו צירוף חייב להופיע במטריצת הבדיקה. שינוי שמתקמפל אך מפר את אחת ההתחייבויות אינו upgrade תואם.