Merged branch 'master' of https://github.com/Nemo1369/libcds
[libcds.git] / cds / container / details / make_skip_list_set.h
index edfe22c40d4a8b15405437ae05508fb49cca3e27..ae629060ea3300cec54d9f4865b8152507826399 100644 (file)
@@ -1,4 +1,32 @@
-//$$CDS-header$$
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
 
 #ifndef CDSLIB_CONTAINER_DETAILS_MAKE_SKIP_LIST_SET_H
 #define CDSLIB_CONTAINER_DETAILS_MAKE_SKIP_LIST_SET_H
@@ -27,27 +55,32 @@ namespace cds { namespace container { namespace details {
             //atomic_marked_ptr m_arrTower[] ;  // allocated together with node_type in single memory block
 
             template <typename Q>
-            node_type( unsigned int nHeight, atomic_marked_ptr * pTower, Q const& v )
-                : m_Value(v)
+            node_type( unsigned int nHeight, atomic_marked_ptr * pTower, Q&& v )
+                : m_Value( std::forward<Q>( v ))
             {
-                if ( nHeight > 1 ) {
-                    new (pTower) atomic_marked_ptr[ nHeight - 1 ];
-                    base_class::make_tower( nHeight, pTower );
-                }
+                init_tower( nHeight, pTower );
             }
 
             template <typename Q, typename... Args>
             node_type( unsigned int nHeight, atomic_marked_ptr * pTower, Q&& q, Args&&... args )
                 : m_Value( std::forward<Q>(q), std::forward<Args>(args)... )
+            {
+                init_tower( nHeight, pTower );
+            }
+
+            node_type() = delete;
+
+        private:
+            void init_tower( unsigned nHeight, atomic_marked_ptr* pTower )
             {
                 if ( nHeight > 1 ) {
-                    new (pTower) atomic_marked_ptr[ nHeight - 1 ];
+                    // TSan: make_tower() issues atomic_thread_fence( release )
+                    CDS_TSAN_ANNOTATE_IGNORE_WRITES_BEGIN;
+                    new ( pTower ) atomic_marked_ptr[nHeight - 1];
                     base_class::make_tower( nHeight, pTower );
+                    CDS_TSAN_ANNOTATE_IGNORE_WRITES_END;
                 }
             }
-
-        private:
-            node_type() ;   // no default ctor
         };
 
         typedef skip_list::details::node_allocator< node_type, traits> node_allocator;