לדלג לתוכן

פתרון מיפוי קבצים ושיתוף דפים

השינוי הפרטי לערך תשע אינו מיועד לכתיבה אל הקובץ. ה־shared view מחזיק את הערך שבע, וה־flush שלו מתייחס לשינוי המשותף. כדי לבדוק את הקובץ אחרי סיום פותחים אותו לקריאה חדשה ובודקים את הבית הראשון, בלי להשתמש ב־pointer ל־view שכבר הוסר.

סגירת mapping handle מחייבת איפוס מצב הבעלים כדי שה־destructor לא יסגור אותו שוב. אפשר להוסיף פעולת reset מפורשת או להשתמש בעטיפה הכללית מהפרקים הקודמים. ה־views עדיין דורשים UnmapViewOfFile.

החשבון הכללי של החלון מתחיל בבדיקת סוף הקובץ. רק אחריה מחשבים alignment וגודל view.

#include <limits>
#include <stdexcept>

if (offset > file_size || length > file_size - offset)
    throw std::out_of_range("window outside file");
const auto aligned = offset / granularity * granularity;
const auto delta64 = offset - aligned;
if (delta64 > std::numeric_limits<SIZE_T>::max() ||
    length > std::numeric_limits<SIZE_T>::max() -
             static_cast<SIZE_T>(delta64))
    throw std::length_error("view too large");
const SIZE_T delta = static_cast<SIZE_T>(delta64);
const SIZE_T mapped_size = delta + static_cast<SIZE_T>(length);

הקטע מניח ש־offset, file_size ו־length מיוצגים ב־64 ביט ללא סימן, וש־granularity אינו אפס ונלקח מהמערכת. אפס אורך דורש החלטה נפרדת, מפני שב־MapViewOfFile גודל אפס אינו בהכרח בקשה ל־view ריק אלא מיפוי עד סוף האובייקט.

בעל החלון שומר base לצורך unmap ו־data שמצביע ל־base ועוד delta לצורך קריאה. הוא אינו מוסר ownership של data לפונקציית free. תצוגה שנמסרת למשתמש היא borrowing ותלויה בבעלים.

מדיניות פשוטה לפרויקט היא קובץ immutable למשך חיי החלון, עם share flags שמונעים פתיחות כתיבה מתחרות לפי החוזה. מערכת שצריכה עדכונים במקביל חייבת פורמט וסנכרון נוספים, למשל גרסה שנבדקת לפני ואחרי קריאת רשומה והגדרה של retry.

הפתרון אינו מתייחס ל־volatile כסנכרון בין processes. הסימון בניסוי רק שומר גישות לצורך תצפית. תקשורת אמיתית דורשת פרוטוקול פרסום ואישור חיים שנלמד בהמשך.