Restored acq-rel fence in urcu access_lock().
[libcds.git] / cds / opt / permutation.h
index 62fe61ebcc44d37a1ffbb2451b1d92f2fab08489..a69b57f707276f0a38a8ad5c74058336126879a5 100644 (file)
@@ -1,11 +1,42 @@
-//$$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_OPT_PERMUTATION_H
 #define CDSLIB_OPT_PERMUTATION_H
 
-#include <cds/opt/options.h>
-#include <stdlib.h> // rand, srand
+#include <cstdlib> // rand, srand
 #include <random>
+#include <algorithm> // std::shuffle
+#include <numeric>   // std::iota
+
+#include <cds/opt/options.h>
 
 namespace cds { namespace opt {
 
@@ -31,7 +62,8 @@ namespace cds { namespace opt {
         };
         \endcode
 
-        Usage example:
+        <b>Usage example</b>
+
         The permutation generator is intended for <tt>do {} while</tt> loop:
         \code
         permutation_generator gen( 16 );
@@ -39,21 +71,21 @@ namespace cds { namespace opt {
         do {
             int i = gen;
             //...
-        } while ( gen.next() );
+        } while ( gen.next());
 
         // Get other permutation
         gen.reset();
         do {
             int i = gen;
             //...
-        } while ( gen.next() );
+        } while ( gen.next());
         \endcode
 
         The following \p Generator defined:
-        - opt::v::random_permutation
-        - opt::v::random2_permutation
-        - opt::v::random_shuffle_permutation
-        - opt::v::skew_permutation
+        - \p opt::v::random_permutation
+        - \p opt::v::random2_permutation
+        - \p opt::v::random_shuffle_permutation
+        - \p opt::v::skew_permutation
     */
     template <typename Generator>
     struct permutation_generator {
@@ -94,7 +126,7 @@ namespace cds { namespace opt {
             random_permutation( size_t nLength )
                 : m_nCur(0)
                 , m_nStart(0)
-                , m_nMod( integer_type(nLength) )
+                , m_nMod( integer_type(nLength))
             {
                 reset();
             }
@@ -114,7 +146,7 @@ namespace cds { namespace opt {
             /// Resets the generator to produce new sequence
             void reset()
             {
-                m_nCur = m_nStart = integer_type( rand() ) % m_nMod;
+                m_nCur = m_nStart = integer_type( std::rand()) % m_nMod;
             }
         };
 
@@ -172,7 +204,7 @@ namespace cds { namespace opt {
             /// Resets the generator to produce new sequence
             void reset()
             {
-                m_nCur = m_nStart = integer_type( rand() ) & m_nMask;
+                m_nCur = m_nStart = integer_type( std::rand()) & m_nMask;
             }
         };
 
@@ -201,21 +233,16 @@ namespace cds { namespace opt {
             integer_type *      m_pCur;
             integer_type *      m_pFirst;
             integer_type *      m_pLast;
-
-            random_generator    m_RandomGenerator;
-            random_device       m_RandomDevice;
             //@endcond
 
         public:
             /// Initializes the generator of arbitrary length \p nLength
             random_shuffle_permutation( size_t nLength )
                 : m_pCur( nullptr )
-                , m_RandomGenerator( m_RandomDevice() )
             {
                 m_pFirst = new integer_type[nLength];
                 m_pLast = m_pFirst + nLength;
-                for ( integer_type i = 0; i < static_cast<integer_type>(nLength); ++i )
-                    m_pFirst[i] = i;
+                std::iota(m_pFirst, m_pLast, integer_type{0} );
                 reset();
             }
 
@@ -239,7 +266,7 @@ namespace cds { namespace opt {
             /// Resets the generator to produce new sequence
             void reset()
             {
-                std::shuffle( m_pFirst, m_pLast, m_RandomGenerator );
+                std::shuffle( m_pFirst, m_pLast, random_generator{ random_device{}() });
                 m_pCur = m_pFirst;
             }
         };