سؤال

لذلك في الوقت نفسه ، نعلم أن القفل المزدوج كما هو لا يعمل في C ++ ، على الأقل ليس بطريقة محمولة.

لقد أدركت للتو أن لديّ تطبيق هش في Quadtree كسول أستخدمه لتتبع شعاع التضاريس. لذلك حاولت إيجاد طريقة لاستخدام التهيئة البطيئة بطريقة آمنة ، حيث لا أرغب في استخدام الذاكرة الرباعية وإعادة ترتيب أجزاء كبيرة من الخوارزميات المنفذة.

هذا اجتياز مستوحى من النمط في الصفحة 12 من C ++ ومخاطر القفل المزدوج, ، لكن يحاول القيام بذلك أرخص:

(pseudo code!)

struct Foo {
    bool childCreated[4];
    Mutex mutex[4];
    Foo child[4];

    void traverse (...) {
        ...
        if (!childCreated[c]) { 
            // get updated view
            #pragma flush childCreated[c]
            if (!childCreated[c]) { 
                ScopedLock sl (mutex[c]);
                if (!childCreated[c]) {
                    create (c);
                    #pragma flush childCreated[c]  
                    childCreated[c] = true;
                }
            }
        }
    }
}

يفترض أن #pragma flush سيكون بمثابة نقطة تسلسل صلبة حيث لن يُسمح للمترجمين والمعالجات بإعادة ترتيب العمليات عبرهم.

ما هي المشاكل التي تراها؟

تعديل: الإصدار 2 ، في محاولة لمراعاة إجابة VLADS (تقديم Flush الثالث):

(pseudo code!)

struct Foo {
    bool childCreated[4];
    Mutex mutex[4];
    Foo child[4];

    void traverse (...) {
        ...
        if (!childCreated[c]) { 
            // get updated view
            #pragma flush childCreated[c]
            if (!childCreated[c]) { 
                ScopedLock sl (mutex[c]);
                #pragma flush childCreated[c]
                if (!childCreated[c]) {
                    create (c);
                    #pragma flush childCreated[c]
                    childCreated[c] = true;
                }
            }
        }
    }
}

تعديل: الإصدار 3 ، أجد بطريقة ما معادلة إلى حد ما للإصدار 2 ، لأنني لا أستخدم الطفل نفسه بل علامة بدائية للتحقق من الصلاحية ، والاعتماد بشكل أساسي على حاجز الذاكرة بين إنشاء طفل والكتابة على هذا العلم.

(pseudo code!)

struct Foo {
    bool childCreated[4];
    Mutex mutex[4];
    Foo child[4];

    void traverse (...) {
        ...
        if (!childCreated[c]) { 
            ScopedLock sl (mutex[c]);
            #pragma flush childCreated[c]
            if (!childCreated[c]) {
                create (c);
                #pragma flush childCreated[c]
                childCreated[c] = true;
            }
        }
    }
}
هل كانت مفيدة؟

المحلول

يبدو أن نمطك غير صحيح. النظر في الحالة عندما يتم تنفيذ الموضوع رقم 1 حتى بعد الأول #pragma flush. ثم يتحول عنصر التحكم إلى الخيط رقم 2 ، والذي يمتد ويخلق أ c, ، يتم إعادة السيطرة قبل الثانية مباشرة #pragma flush. الآن يستيقظ الخيط الأول ، ويخلق الطفل من جديد.

تحرير: آسف ، خطأ: لن يكون من الممكن أخذ القفل.

تحرير 2: لا ، لا تزال صحيحة ، لأن القيمة لن يتم مسحها في الموضوع رقم 1

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top