परिसर: मैं एआरएम एम्बेडेड (लगभग नंगे-धातु) वातावरण के साथ काम कर रहा हूं, जहां मेरे पास सी ++ 11 ( std::atomic<int>
उपलब्ध) भी नहीं है, इसलिए कृपया " बस मानक सी ++ का उपयोग करेंstd::atomic<int>
" जैसे उत्तरों से बचें : मैं नहीं कर सकता ।
इस एआरएम है कार्यान्वयन AtomicInt का सही? (मान लें कि एआरएम आर्किटेक्चर ARMv7-A है )
क्या आपको कुछ सिंक्रनाइज़ेशन समस्या दिखाई देती है? क्या यह volatile
आवश्यक / उपयोगी है?
// File: atomic_int.h
#ifndef ATOMIC_INT_H_
#define ATOMIC_INT_H_
#include <stdint.h>
class AtomicInt
{
public:
AtomicInt(int32_t init = 0) : atom(init) { }
~AtomicInt() {}
int32_t add(int32_t value); // Implement 'add' method in platform-specific file
int32_t sub(int32_t value) { return add(-value); }
int32_t inc(void) { return add(1); }
int32_t dec(void) { return add(-1); }
private:
volatile int32_t atom;
};
#endif
// File: arm/atomic_int.cpp
#include "atomic_int.h"
int32_t AtomicInt::add(int32_t value)
{
int32_t res, prev, tmp;
asm volatile(
"try: ldrex %1, [%3]\n" // prev = atom;
" add %0, %1, %4\n" // res = prev + value;
" strex %2, %0, [%3]\n" // tmp = outcome(atom = res); // may fail
" teq %2, #0\n" // if (tmp)
" bne try" // goto try; /* add failed: someone else modified atom -> retry */
: "=&r" (res), "=&r" (prev), "=&r" (tmp), "+mo" (atom) // output (atom is both in-out)
: "r" (value) // input
: "cc"); // clobbers (condition code register [CPSR] changed)
return prev; // safe return (local variable cannot be changed by other execution contexts)
}
इसके अलावा, मैं कुछ कोड पुन: उपयोग को प्राप्त करने की कोशिश कर रहा हूं, यही कारण है कि मैंने प्लेटफ़ॉर्म-विशिष्ट कोड ( add()
अंदर विधि arm/atomic_int.cpp
) को लागू करने के लिए सिर्फ एक मूल फ़ंक्शन को अलग कर दिया है ।
क्या यह atomic_int.h
वास्तव में पोर्टेबल है क्योंकि यह विभिन्न प्लेटफार्मों / आर्किटेक्चर / संकलक के पार है? क्या यह दृष्टिकोण संभव है ? ( संभव के साथ मेरा मतलब है कि हर मंच के लिए संभव हैadd()
कि सिर्फ विधि को लागू करके परमाणुता की गारंटी दी जाए )।
यहाँ एक ही फ़ंक्शन के संबंधित ARM GCC 8.3.1 कार्यान्वयन है। जाहिर है, एकमात्र वास्तविक अंतर dmb
पहले और बाद की उपस्थिति है । क्या वास्तव में मेरे मामले में उनकी ज़रूरत है? क्यों? क्या आपके पास एक उदाहरण है जहाँ मेरा AtomicInt
(बिना dmb
) विफल रहता है?
अद्यतन: निर्धारित कार्यान्वयन, get()
एटमॉसिटी और संरेखण मुद्दों को हल करने के लिए हटा दिया गया तरीका। अब add()
एक मानक की तरह व्यवहार करता है fetchAndAdd()
।
__ATOMIC_INT_H_
) होते हैं और वे नाम जो एक अंडरस्कोर के साथ शुरू होते हैं, उसके बाद कैपिटल लेटर लागू होता है। उन्हें अपने कोड में उपयोग न करें।
atomic
शायद सबसे अच्छा नहीं है जिसके साथ भ्रम की स्थिति से बचने के लिए उपयोग किया जाता है std::atomic
, हालांकि यह सवाल है कि आप किसी भी मामले में इसका उपयोग क्यों नहीं करेंगे।
__ATOMIC_INT_H_
पहचानकर्ता।
volatile
C ++ में कीवर्ड का मतलब चर के माध्यम से अनुकूलन नहीं है। तोget()
विधि से लाभ होता है। हालांकि, सामान्य तौर पर, अस्थिरता C ++ में घटने वाली है। यदि आपका सिस्टम 32-बिट डेटा को अंतर्निहित नहीं कर सकता है, तो आपके पास म्यूटेक्स - स्पिनलॉक का उपयोग करने के लिए बहुत कम विकल्प हैं।