Эта реализация C++ для Атомарного сейфа плавающего?

Ваше состояние обновляется при изменении формы ввода.

handleFields = e => this.setState({ [e.target.name]: 'e.target.value' });

Состояние не является статическим объектом.

Вам придется вручную обновить значения полей.

resetForm = () => {
    this.setState({fullName: "", email: "", message: ""})
}
15
задан 9 revs 21 November 2008 в 01:27
поделиться

8 ответов

Я серьезно отговорил бы от общедоступного наследования. Я не знаю то, на что похожа атомарная реализация, но я предполагаю, что она перегрузила операторы, которые используют ее в качестве целочисленного типа, который означает, что те продвижения будут использоваться вместо Вашего плавания во многих (возможно, большинство?) случаи.

Я не вижу оснований, почему это не работало бы, но как Вы я имею к способу доказать это...

Одно примечание: Ваш operator float() стандартная программа не имеет загрузки - получают семантику, и разве это не должна быть отмеченная энергозависимая константа (или определенно по крайней мере, константа)?

Править: Если Вы собираетесь обеспечить оператор - () необходимо обеспечить обе формы префикса/постфикса.

5
ответ дан 1 December 2019 в 04:47
поделиться

Хотя размер uint32_t может быть эквивалентен размеру плавания на данной дуге, путем иного толкования броску от одного в другой Вы неявно предполагаете, что атомарные инкременты, декременты и все другие операции на битах семантически эквивалентны на обоих типах, которые не являются в действительности. Я сомневаюсь, что это работает как ожидалось.

1
ответ дан 1 December 2019 в 04:47
поделиться

Похоже, что Ваша реализация принимает это sizeof(size_t) == sizeof(float). Это всегда будет верно для Ваших целевых платформ?

И я не сказал бы что ересь поточной обработки так как кастинг ереси.:)

3
ответ дан 1 December 2019 в 04:47
поделиться

Это - состояние кода как есть теперь после переговоров по платам Intel, но все еще не был полностью проверен для работы правильно во всех сценариях.

  #include <tbb/atomic.h>
  typedef unsigned int      uint_32;
  typedef __TBB_LONG_LONG       uint_64;

  template<typename FLOATING_POINT,typename MEMORY_BLOCK>
  struct atomic_float_
  {
    /*  CRC Card -----------------------------------------------------
    |   Class:          atmomic float template class
    |
    |   Responsability: handle integral atomic memory as it were a float,
    |                   but partially bypassing FPU, SSE/MMX, so it is
    |                   slower than a true float, but faster and smaller
    |                   than a locked float.
    |                       *Warning* If your float usage is thwarted by
    |                   the A-B-A problem this class isn't for you
    |                       *Warning* Atomic specification says we return,
    |                   values not l-values. So  (i = j) = k doesn't work.
    |
    |   Collaborators:  intel's tbb::atomic handles memory atomicity
    ----------------------------------------------------------------*/
    typedef typename atomic_float_<FLOATING_POINT,MEMORY_BLOCK> self_t;

    tbb::atomic<MEMORY_BLOCK> atomic_value_;

    template<memory_semantics M>
    FLOATING_POINT fetch_and_store( FLOATING_POINT value ) 
    {
        const MEMORY_BLOCK value_ = 
            atomic_value_.tbb::atomic<MEMORY_BLOCK>::fetch_and_store<M>((MEMORY_BLOCK&)value);
        //atomic specification requires returning old value, not new one
        return reinterpret_cast<const FLOATING_POINT&>(value_);
    }

    FLOATING_POINT fetch_and_store( FLOATING_POINT value ) 
    {
        const MEMORY_BLOCK value_ = 
            atomic_value_.tbb::atomic<MEMORY_BLOCK>::fetch_and_store((MEMORY_BLOCK&)value);
        //atomic specification requires returning old value, not new one
        return reinterpret_cast<const FLOATING_POINT&>(value_);
    }

    template<memory_semantics M>
    FLOATING_POINT compare_and_swap( FLOATING_POINT value, FLOATING_POINT comparand ) 
    {
        const MEMORY_BLOCK value_ = 
            atomic_value_.tbb::atomic<MEMORY_BLOCK>::compare_and_swap<M>((MEMORY_BLOCK&)value,(MEMORY_BLOCK&)compare);
        //atomic specification requires returning old value, not new one
        return reinterpret_cast<const FLOATING_POINT&>(value_);
    }

    FLOATING_POINT compare_and_swap(FLOATING_POINT value, FLOATING_POINT compare)
    {
        const MEMORY_BLOCK value_ = 
            atomic_value_.tbb::atomic<MEMORY_BLOCK>::compare_and_swap((MEMORY_BLOCK&)value,(MEMORY_BLOCK&)compare);
        //atomic specification requires returning old value, not new one
        return reinterpret_cast<const FLOATING_POINT&>(value_);
    }

    operator FLOATING_POINT() const volatile // volatile qualifier here for backwards compatibility 
    {
        const MEMORY_BLOCK value_ = atomic_value_;
        return reinterpret_cast<const FLOATING_POINT&>(value_);
    }

    //Note: atomic specification says we return the a copy of the base value not an l-value
    FLOATING_POINT operator=(FLOATING_POINT rhs) 
    {
        const MEMORY_BLOCK value_ = atomic_value_.tbb::atomic<MEMORY_BLOCK>::operator =((MEMORY_BLOCK&)rhs);
        return reinterpret_cast<const FLOATING_POINT&>(value_);
    }

    //Note: atomic specification says we return an l-value when operating among atomics
    self_t& operator=(self_t& rhs) 
    {
        const MEMORY_BLOCK value_ = atomic_value_.tbb::atomic<MEMORY_BLOCK>::operator =((MEMORY_BLOCK&)rhs);
        return *this;
    }

    FLOATING_POINT& _internal_reference() const
    {
        return reinterpret_cast<FLOATING_POINT&>(atomic_value_.tbb::atomic<MEMORY_BLOCK>::_internal_reference());
    }

    FLOATING_POINT operator+=(FLOATING_POINT value)
    {
        FLOATING_POINT old_value_, new_value_;
        do
        {
            old_value_ = reinterpret_cast<FLOATING_POINT&>(atomic_value_);
            new_value_ = old_value_ + value;
        //floating point binary representation is not an issue because
        //we are using our self's compare and swap, thus comparing floats and floats
        } while(self_t::compare_and_swap(new_value_,old_value_) != old_value_);
        return (new_value_); //return resulting value
    }

    FLOATING_POINT operator*=(FLOATING_POINT value)
    {
        FLOATING_POINT old_value_, new_value_;
        do
        {
            old_value_ = reinterpret_cast<FLOATING_POINT&>(atomic_value_);
            new_value_ = old_value_ * value;
        //floating point binary representation is not an issue becaus
        //we are using our self's compare and swap, thus comparing floats and floats
        } while(self_t::compare_and_swap(new_value_,old_value_) != old_value_);
        return (new_value_); //return resulting value
    }

    FLOATING_POINT operator/=(FLOATING_POINT value)
    {
        FLOATING_POINT old_value_, new_value_;
        do
        {
            old_value_ = reinterpret_cast<FLOATING_POINT&>(atomic_value_);
            new_value_ = old_value_ / value;
        //floating point binary representation is not an issue because
        //we are using our self's compare and swap, thus comparing floats and floats
        } while(self_t::compare_and_swap(new_value_,old_value_) != old_value_);
        return (new_value_); //return resulting value
    }

    FLOATING_POINT operator-=(FLOATING_POINT value)
    {
        return this->operator+=(-value); //return resulting value
    }

    //Prefix operator
    FLOATING_POINT operator++()
    {
        return this->operator+=(1); //return resulting value
    }

    //Prefix operator
    FLOATING_POINT operator--() 
    {
        return this->operator+=(-1); //return resulting value
    }

    //Postfix operator
    FLOATING_POINT operator++(int)
    {
        const FLOATING_POINT temp = this;
        this->operator+=(1);
        return temp//return resulting value
    }

    //Postfix operator
    FLOATING_POINT operator--(int) 
    {
        const FLOATING_POINT temp = this;
        this->operator+=(1);
        return temp//return resulting value
    }

    FLOATING_POINT fetch_and_add( FLOATING_POINT addend ) 
    {
        const FLOATING_POINT old_value_ = atomic_value_;
        this->operator+=(addend);
        //atomic specification requires returning old value, not new one as in operator x=
        return old_value_; 
    }

    FLOATING_POINT fetch_and_increment() 
    {
        const FLOATING_POINT old_value_ = atomic_value_;
        this->operator+=(+1);
        //atomic specification requires returning old value, not new one as in operator x=
        return old_value_; 
    }

    FLOATING_POINT fetch_and_decrement() 
    {
        const FLOATING_POINT old_value_ = atomic_value_;
        this->operator+=(-1);
        //atomic specification requires returning old value, not new one as in operator x=
        return old_value_; 
    }
  };

  typedef atomic_float_<float,uint_32> AtomicFloat;
  typedef atomic_float_<double,uint_64> AtomicDouble;
1
ответ дан 1 December 2019 в 04:47
поделиться

Я сильно сомневаюсь, что Вы получаете правильные значения в fetch_and_add и т.д., поскольку дополнение плавающее отличается от международного дополнения.

Вот то, что я получаю от них арифметику:

1   + 1    =  1.70141e+038  
100 + 1    = -1.46937e-037  
100 + 0.01 =  1.56743e+038  
23  + 42   = -1.31655e-036  

Так да, ориентированный на многопотоковое исполнение, но не, что Вы ожидаете.

свободные от блокировок алгоритмы (оператор + и т.д.) должны работать относительно атомарности (не проверили на сам алгоритм..)


Другое решение: Поскольку это - все дополнения и вычитания, Вы смогли приводить каждому потоку его собственный пример, затем добавлять результаты нескольких потоков.

1
ответ дан 1 December 2019 в 04:47
поделиться

От моего чтения того кода я действительно рассердился бы на такой компилятор как для произведения блока для этого, которое не было атомарным.

0
ответ дан 1 December 2019 в 04:47
поделиться

Имейте свой компилятор, генерируют ассемблерный код и смотрят на него. Если операция является больше, чем единственная инструкция ассемблера, то это не атомарная операция и требует, чтобы блокировки работали правильно в многопроцессорных системах.

К сожалению, я не уверен, что противоположное также верно - что операции единственной инструкции, как гарантируют, будут атомарными. Я не знаю детали многопроцессорной системы, программирующей вниз к тому уровню. Я мог изложить доводы для любого результата. (Если у кого-либо еще есть некоторая категорическая информация об этом, не стесняйтесь вмешиваться.)

0
ответ дан 1 December 2019 в 04:47
поделиться

Просто примечание о это (я хотел сделать комментарий, но, видимо, новым пользователям не разрешено комментировать): Использование reinterpret_cast в ссылках приводит к некорректному коду с gcc 4.1 -O3. Кажется, это исправлено в 4.4, потому что там это работает. Изменение reinterpret_casts на указатели, хотя и немного уродливее, работает в обоих случаях.

1
ответ дан 1 December 2019 в 04:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: