سؤال

اذا كان لدينا:

__int32 some_var = 0;

ما هي أفضل طريقة (إن وجدت) للاتصال InterlockedExchange, InterlockedIncrement وغيرها من الوظائف المتشابكة التي تتطلب LONG* إلى عن على some_var ?

منذ ذلك الحين ، هناك ضمان LONG هو 32 بت على أي نوافذ ، وربما يكون من الآمن فقط المرور (long*) some_var. ومع ذلك ، يبدو لي قبيحًا للغاية ولا يمكنني العثور على تأكيد بأنه آمن.

ملاحظة ، لا يمكنني تغيير النوع إلى long لأنه ليس محمولا. أحتاج بالضبط 32 بت.

تحديث: أظهرت بعض الأبحاث عن المكتبات التي توفر عمليات ذرية محمولة أنه لا يوجد أحد يزعج الصب. بعض الأمثلة:

وقت تشغيل Apache المحمول (أبريل):

typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_val_fn)
    (apr_uint32_t volatile *, 
     apr_uint32_t);

APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
{
#if (defined(_M_IA64) || defined(_M_AMD64))
    return InterlockedExchangeAdd(mem, val);
#elif defined(__MINGW32__)
    return InterlockedExchangeAdd((long *)mem, val);
#else
    return ((apr_atomic_win32_ptr_val_fn)InterlockedExchangeAdd)(mem, val);
#endif
}

Atomic_ops:

AO_INLINE AO_t
AO_fetch_and_sub1_full (volatile AO_t *p)
{
  return _InterlockedDecrement64((LONGLONG volatile *)p) + 1;
}
هل كانت مفيدة؟

المحلول

فقط افعل assert(sizeof(LONG) == sizeof(some_var)) والقلق فقط بشأن المشكلة عندما يفشل التأكيد. ياجني. طالما أن التأكيد يحتفظ به ، يمكنك استخدامه reinterpret_cast<LONG*>(&some_var).

نصائح أخرى

حسنًا ، إنها صخرة ومكان صعب. الزيادة الذرية هي تفاصيل تنفيذ المنصة الثقيلة. لهذا السبب يوجد typedef الطويل في المقام الأول. بعض نظام التشغيل المستقبلي 20 أو 50 عامًا من الآن قد يعيد تعريف هذا النوع. عندما ، على سبيل المثال ، 256 بت النوى شائعة والزيادات الذرية تعمل بشكل مختلف. من تعرف.

إذا كنت ترغب في كتابة رمز محمول حقًا ، فيجب عليك استخدام أنواع محمولة حقًا. مثل طويل. وسيكون عبء Microsoft لجعله يعمل ، بدلاً من لك.

سيكون عدد صحيح 32 بت لفترة طويلة قادمة ، أوصي بأن لا تقلق بشأن ذلك.

يمكنك أيضًا تغيير النوع إلى فترة طويلة ، تاركًا وراءه قابلية النقل ، لأن الأسرة "المتشابكة" بأكملها من العمليات الذرية هي أيضًا غير محمول.

بالمناسبة ، كملاحظة جانبية ، اعتقدت أن interlored دعمت زيادة عدد صحيح. ربما هذا فقط في .NET رغم ذلك.

نحن سوف، __int32 ليس نوعًا محمولًا أيضاً. لذا فإن اقتراحي لجعل المشكلة تختفي هو استخدام typedef. على Windows ، يمكنك القيام:

typedef LONG my_int32;

... ونقل مؤشرًا بأمان إلى هذا النوع InterlockedExchange(). على أنظمة أخرى ، استخدم كل ما هو نوع 32 بت هناك - على سبيل المثال ، إذا كان لديهم stdint.h, ، يمكنك ان تفعل:

typedef int32_t my_int32;

بشكل كافٍ ، هناك interlockedExchange - واجهة برمجة تطبيقات Windows التي تستغرق فترة طويلة* و _interlockedExchange برنامج التحويل البرمجي MSVC جوهري ، يستغرق فترة طويلة*.

لأنه تم استدعاء قابلية النقل ، قم أيضًا بربط صفحة على الجوهارات الذرية في مجلس التعاون الخليجي.

يتم أخذ النقطة بشكل جيد: MSVC يستخدم ILP32LLP64 نموذج البيانات لـ 32bit تبني و LLP64 لبناء 64 بت. توجد سلاسل الأدوات المستندة إلى GCC (مثل MINGW) لنظام التشغيل Windows وقد تنفذ طراز LP64 جيدًا - مما يؤدي إلى مسلية! الأحداث مثل "طويلة" هي 64 بايت ، ولكن منذ فترة طويلة 32.

إذا كنت متمسكًا بمجمومتي Microsoft ، فهذا ليس شيئًا تحتاج إلى القلق بشأنه.

لذلك ، في الختام: 1. يجب أن تكون القيمة التي يتم تمريرها مؤهلة مع "متقلبة". 2. نظرًا لأنك (أ) باستخدام كمية 32 بت (وهذا هو متطلباتك) و (ب) باستخدام شكل 32 بت صريح من واجهة برمجة تطبيقات interlockedxxx - فإنه آمن بنسبة 100 ٪ فقط للقيام باللوب الدموي والقيام به: interlockedIncrement ستعمل على قيمة 32 بت على جميع أحجام البتات ، سيكون متغيرك 32 نقطة بشكل صريح على جميع أحجام البتات - حتى مع استخدام نماذج البيانات المختلفة.

الممثلون آمنون ، لا تعقد الأشياء دون سبب.

هانز المارة لقد أعربت عنها بشكل جيد للغاية:

"الزيادة الذرية هي تفاصيل تنفيذ المنصة الثقيلة."

لهذا السبب توفر التطبيقات أحمالًا زائدة محددة من النوع.

atomic_ops هو أحد هذه المشروع.

من الناحية النظرية ، يمكن تنفيذ كل وظيفة متشابكة باستخدام الأقفال الكاملة-والتي تعتمد على تفاصيل النظام الأساسي :-)-ولكن هذا عبارة عن مبالغة حقيقية في الأداء للأنواع والوظائف المدعومة على منصة الأجهزة المستهدفة.

هناك بعض التوحيد الجاري في هذا الصدد ، راجع إجابة أسئلة مماثلة هنا و هنا كذلك.

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