Intel® oneAPI Threading Building Blocks
Ask questions and share information about adding parallelism to your applications when using this threading library.

Patch to enable 64-bit atomics on MSVC 7.1

andysem
New Contributor III
204 Views

I'm not sure if it's already been proposed, but below I posted a patch that corrects include/tbb/atomic.h to make atomic template for 64-bit integers compatible with MSVC 7.1. There may be a more graceful solution, but I ended up with this to solve the problem for myself. I hope it will get into the distribution.

PS: The patch is against thetbb22_20090908oss release.

PPS: Sorry, I couldn't figure out how to attach files to the postings.

I'm not sure if it's already been proposed, but below I posted a patch that corrects include/tbb/atomic.h to make atomic template for 64-bit integers compatible with MSVC 7.1. There may be a more graceful solution, but I ended up with this to solve the problem for myself. I hope it will get into the distribution.

PS: The patch is against the tbb22_20090908oss release.

PPS: Sorry, I couldn't figure out how to attach files to the postings.




diff -ur tbb22_20090908oss/include/tbb/atomic.h TBB/include/tbb/atomic.h
--- tbb22_20090908oss/include/tbb/atomic.h2009-09-11 15:16:30 +0400
+++ TBB/include/tbb/atomic.h2009-10-22 12:27:00 +0400
@@ -211,6 +211,109 @@
}
};

+#if __TBB_WORDSIZE == 4
+// Plaforms with 32-bit hardware require special effort for 64-bit loads and stores.
+
+template<>
+struct atomic_impl< __TBB_LONG_LONG > {
+protected:
+ atomic_rep rep;
+private:
+ //! Union type used to convert type T to underlying integral type.
+ union converter {
+ __TBB_LONG_LONG value;
+ atomic_rep::word bits;
+ };
+public:
+ typedef __TBB_LONG_LONG value_type;
+
+ template
+ value_type fetch_and_store( value_type value ) {
+ converter u, w;
+ u.value = value;
+ w.bits = internal::atomic_traits::fetch_and_store(&rep.value,u.bits);
+ return w.value;
+ }
+
+ value_type fetch_and_store( value_type value ) {
+ return fetch_and_store<__TBB_full_fence>(value);
+ }
+
+ template
+ value_type compare_and_swap( value_type value, value_type comparand ) {
+ converter u, v, w;
+ u.value = value;
+ v.value = comparand;
+ w.bits = internal::atomic_traits::compare_and_swap(&rep.value,u.bits,v.bits);
+ return w.value;
+ }
+
+ value_type compare_and_swap( value_type value, value_type comparand ) {
+ return compare_and_swap<__TBB_full_fence>(value,comparand);
+ }
+
+ operator value_type() const volatile { // volatile qualifier here for backwards compatibility
+ return __TBB_Load8(&rep.value);
+ }
+
+protected:
+ value_type store_with_release( value_type rhs ) {
+ __TBB_Store8(&rep.value,rhs);
+ return rhs;
+ }
+};
+
+template<>
+struct atomic_impl< unsigned __TBB_LONG_LONG > {
+protected:
+ atomic_rep rep;
+private:
+ //! Union type used to convert type T to underlying integral type.
+ union converter {
+ unsigned __TBB_LONG_LONG value;
+ atomic_rep::word bits;
+ };
+public:
+ typedef unsigned __TBB_LONG_LONG value_type;
+
+ template
+ value_type fetch_and_store( value_type value ) {
+ converter u, w;
+ u.value = value;
+ w.bits = internal::atomic_traits::fetch_and_store(&rep.value,u.bits);
+ return w.value;
+ }
+
+ value_type fetch_and_store( value_type value ) {
+ return fetch_and_store<__TBB_full_fence>(value);
+ }
+
+ template
+ value_type compare_and_swap( value_type value, value_type comparand ) {
+ converter u, v, w;
+ u.value = value;
+ v.value = comparand;
+ w.bits = internal::atomic_traits::compare_and_swap(&rep.value,u.bits,v.bits);
+ return w.value;
+ }
+
+ value_type compare_and_swap( value_type value, value_type comparand ) {
+ return compare_and_swap<__TBB_full_fence>(value,comparand);
+ }
+
+ operator value_type() const volatile { // volatile qualifier here for backwards compatibility
+ return __TBB_Load8(&rep.value);
+ }
+
+protected:
+ value_type store_with_release( value_type rhs ) {
+ __TBB_Store8(&rep.value,rhs);
+ return rhs;
+ }
+};
+
+#endif // __TBB_WORDSIZE == 4
+
//! Base class that provides basic functionality for atomic with fetch_and_add.
/** I is the underlying type.
D is the difference type.
@@ -275,35 +378,6 @@
}
};

-#if __TBB_WORDSIZE == 4
-// Plaforms with 32-bit hardware require special effort for 64-bit loads and stores.
-#if defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400
-
-template<>
-inline atomic_impl<__TBB_LONG_LONG>::operator atomic_impl<__TBB_LONG_LONG>::value_type() const volatile {
- return __TBB_Load8(&rep.value);
-}
-
-template<>
-inline atomic_impl::operator atomic_impl::value_type() const volatile {
- return __TBB_Load8(&rep.value);
-}
-
-template<>
-inline atomic_impl<__TBB_LONG_LONG>::value_type atomic_impl<__TBB_LONG_LONG>::store_with_release( value_type rhs ) {
- __TBB_Store8(&rep.value,rhs);
- return rhs;
-}
-
-template<>
-inline atomic_impl::value_type atomic_impl::store_with_release( value_type rhs ) {
- __TBB_Store8(&rep.value,rhs);
- return rhs;
-}
-
-#endif /* defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400 */
-#endif /* __TBB_WORDSIZE==4 */
-
} /* Internal */
//! @endcond

@@ -325,12 +399,8 @@
atomic& operator=( const atomic& rhs ) {store_with_release(rhs); return *this;} \
};

-#if defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400
__TBB_DECL_ATOMIC(__TBB_LONG_LONG)
__TBB_DECL_ATOMIC(unsigned __TBB_LONG_LONG)
-#else
-// Some old versions of MVSC cannot correctly compile templates with "long long".
-#endif /* defined(__INTEL_COMPILER)||!defined(_MSC_VER)||_MSC_VER>=1400 */

__TBB_DECL_ATOMIC(long)
__TBB_DECL_ATOMIC(unsigned long)

0 Kudos
1 Reply
Vladimir_P_1234567890
204 Views
Hi! Could you submit a patch via tbb contribution page http://www.threadingbuildingblocks.org/contribution_first.php ?

thanks.
--Vladimir
0 Kudos
Reply