Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 71303
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 10, 20262026-05-10T19:52:00+00:00 2026-05-10T19:52:00+00:00

Edit: The code here still has some bugs in it, and it could do

  • 0

Edit: The code here still has some bugs in it, and it could do better in the performance department, but instead of trying to fix this, for the record I took the problem over to the Intel discussion groups and got lots of great feedback, and if all goes well a polished version of Atomic float will be included in a near future release of Intel’s Threading Building Blocks

Ok here’s a tough one, I want an Atomic float, not for super-fast graphics performance, but to use routinely as data-members of classes. And I don’t want to pay the price of using locks on these classes, because it provides no additional benefits for my needs.

Now with intel’s tbb and other atomic libraries I’ve seen, integer types are supported, but not floating points. So I went on and implemented one, and it works… but I’m not sure if it REALLY works, or I’m just very lucky that it works.

Anyone here knows if this is not some form of threading heresy?

typedef unsigned int uint_32;    struct AtomicFloat   {     private:     tbb::atomic<uint_32> atomic_value_;      public:     template<memory_semantics M>     float fetch_and_store( float value )      {         const uint_32 value_ = atomic_value_.tbb::atomic<uint_32>::fetch_and_store<M>((uint_32&)value);         return reinterpret_cast<const float&>(value_);     }      float fetch_and_store( float value )      {         const uint_32 value_ = atomic_value_.tbb::atomic<uint_32>::fetch_and_store((uint_32&)value);         return reinterpret_cast<const float&>(value_);     }      template<memory_semantics M>     float compare_and_swap( float value, float comparand )      {         const uint_32 value_ = atomic_value_.tbb::atomic<uint_32>::compare_and_swap<M>((uint_32&)value,(uint_32&)compare);         return reinterpret_cast<const float&>(value_);     }      float compare_and_swap(float value, float compare)     {         const uint_32 value_ = atomic_value_.tbb::atomic<uint_32>::compare_and_swap((uint_32&)value,(uint_32&)compare);         return reinterpret_cast<const float&>(value_);     }      operator float() const volatile // volatile qualifier here for backwards compatibility      {         const uint_32 value_ = atomic_value_;         return reinterpret_cast<const float&>(value_);     }      float operator=(float value)     {         const uint_32 value_ = atomic_value_.tbb::atomic<uint_32>::operator =((uint_32&)value);         return reinterpret_cast<const float&>(value_);     }      float operator+=(float value)     {         volatile float old_value_, new_value_;         do         {             old_value_ = reinterpret_cast<float&>(atomic_value_);             new_value_ = old_value_ + value;         } while(compare_and_swap(new_value_,old_value_) != old_value_);         return (new_value_);     }      float operator*=(float value)     {         volatile float old_value_, new_value_;         do         {             old_value_ = reinterpret_cast<float&>(atomic_value_);             new_value_ = old_value_ * value;         } while(compare_and_swap(new_value_,old_value_) != old_value_);         return (new_value_);     }      float operator/=(float value)     {         volatile float old_value_, new_value_;         do         {             old_value_ = reinterpret_cast<float&>(atomic_value_);             new_value_ = old_value_ / value;         } while(compare_and_swap(new_value_,old_value_) != old_value_);         return (new_value_);     }      float operator-=(float value)     {         return this->operator+=(-value);     }      float operator++()      {         return this->operator+=(1);     }      float operator--()      {         return this->operator+=(-1);     }      float fetch_and_add( float addend )      {         return this->operator+=(-addend);     }      float fetch_and_increment()      {         return this->operator+=(1);     }      float fetch_and_decrement()      {         return this->operator+=(-1);     }    }; 

Thanks!

Edit: changed size_t to uint32_t as Greg Rogers suggested, that way its more portable

Edit: added listing for the entire thing, with some fixes.

More Edits: Performance wise using a locked float for 5.000.000 += operations with 100 threads on my machine takes 3.6s, while my atomic float even with its silly do-while takes 0.2s to do the same work. So the >30x performance boost means its worth it, (and this is the catch) if its correct.

Even More Edits: As Awgn pointed out my fetch_and_xxxx parts were all wrong. Fixed that and removed parts of the API I’m not sure about (templated memory models). And implemented other operations in terms of operator += to avoid code repetition

Added: Added operator *= and operator /=, since floats wouldn’t be floats without them. Thanks to Peterchen’s comment that this was noticed

Edit: Latest version of the code follows (I’ll leave the old version for reference though)

  #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 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. 2026-05-10T19:52:00+00:00Added an answer on May 10, 2026 at 7:52 pm

    I would seriously advise against public inheritance. I don’t know what the atomic implementation is like, but im assuming it has overloaded operators that use it as the integral type, which means that those promotions will be used instead of your float in many (maybe most?) cases.

    I don’t see any reason why that wouldn’t work, but like you I have to way to prove that…

    One note: your operator float() routine does not have load-acquire semantics, and shouldn’t it be marked const volatile (or definitely at least const)?

    EDIT: If you are going to provide operator–() you should provide both prefix/postfix forms.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Ask A Question

Stats

  • Questions 116k
  • Answers 116k
  • Best Answers 0
  • User 1
  • Popular
  • Answers
  • Editorial Team

    How to approach applying for a job at a company ...

    • 7 Answers
  • Editorial Team

    How to handle personal stress caused by utterly incompetent and ...

    • 5 Answers
  • Editorial Team

    What is a programmer’s life like?

    • 5 Answers
  • Editorial Team
    Editorial Team added an answer In most regex implementations you can shorten \.\.\. using \.{3}… May 11, 2026 at 10:39 pm
  • Editorial Team
    Editorial Team added an answer I vote OrderedDictionary, for the following reasons: "Indexed" is never… May 11, 2026 at 10:39 pm
  • Editorial Team
    Editorial Team added an answer Disclaimer: Don't use this in real code. This is just… May 11, 2026 at 10:39 pm

Related Questions

Casus: How to edit and advance with the same code, from several distanced locations
Google maps is an impressive display of what you can do with JavaScript and
I'm using castle windsor for a pet-project I'm working on. I'm starting to notice
I have checked 100% I am closing all handles on a file I recently

Trending Tags

analytics british company computer developers django employee employer english facebook french google interview javascript language life php programmer programs salary

Top Members

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.