Restored acq-rel fence in urcu access_lock().
[libcds.git] / cds / opt / permutation.h
index 233ced164f12efe19c8b25b2365279af0c199c2a..a69b57f707276f0a38a8ad5c74058336126879a5 100644 (file)
@@ -1,11 +1,42 @@
-//$$CDS-header$$
+/*
+    This file is a part of libcds - Concurrent Data Structures library
 
-#ifndef __CDS_OPT_PERMUTATION_H
-#define __CDS_OPT_PERMUTATION_H
+    (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 <cstdlib> // rand, srand
+#include <random>
+#include <algorithm> // std::shuffle
+#include <numeric>   // std::iota
 
 #include <cds/opt/options.h>
-#include <stdlib.h> // rand, srand
-#include <algorithm> // random_shuffle
 
 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 {
@@ -69,7 +101,7 @@ namespace cds { namespace opt {
 
         /// Permutation generator of arbitrary length based on \p rand()
         /**
-            The class is suitable for opt::permutation_generator option.
+            The class is suitable for \p opt::permutation_generator option.
 
             The generator calculates <tt>n = rand()</tt> and produces the sequence
             <tt>[n % nLen, (n + 1) % nLen, ..., (n + nLen - 1) % nLen]</tt>.
@@ -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,13 +146,13 @@ 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;
             }
         };
 
         /// Permutation generator of power-of-2 length based on \p rand()
         /**
-            The class is suitable for opt::permutation_generator option.
+            The class is suitable for \p opt::permutation_generator option.
 
             The generator calculates <tt>n = rand()</tt> and produces the sequence
             <tt>[n % nLen, (n + 1) % nLen, ..., (n + nLen - 1) % nLen]</tt>.
@@ -172,24 +204,29 @@ 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;
             }
         };
 
-        /// Permutation generator based on \p std::random_shuffle
+        /// Permutation generator based on \p std::shuffle
         /**
-            The class is suitable for opt::permutation_generator option.
+            The class is suitable for \p opt::permutation_generator option.
 
-            The generator produces a permutation of [0, nLen) sequence.
+            The generator produces a permutation of <tt>[0, nLen)</tt> sequence.
             The generator instance allocates a memory block.
 
-            \p Int template argument specifies the type of generated value, it should be any integer.
+            Template parameters:
+            - \p Int - specifies the type of generated value, it should be any integer.
+            - \p RandomGenerator - random generator, default is \p std::mt19937
+            - \p RandomDevice - random device, default is \p std::random_device
         */
-        template <typename Int=int>
+        template <typename Int=int, class RandomGenerator = std::mt19937, class RandomDevice = std::random_device >
         class random_shuffle_permutation
         {
         public:
-            typedef Int     integer_type;   ///< Type of generated value
+            typedef Int     integer_type;             ///< Type of generated value
+            typedef RandomGenerator random_generator; ///< random generator
+            typedef RandomDevice random_device;       ///< random device
 
         protected:
             //@cond
@@ -201,12 +238,11 @@ namespace cds { namespace opt {
         public:
             /// Initializes the generator of arbitrary length \p nLength
             random_shuffle_permutation( size_t nLength )
-                : m_pCur( null_ptr<integer_type *>() )
+                : m_pCur( nullptr )
             {
                 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();
             }
 
@@ -230,7 +266,7 @@ namespace cds { namespace opt {
             /// Resets the generator to produce new sequence
             void reset()
             {
-                std::random_shuffle( m_pFirst, m_pLast );
+                std::shuffle( m_pFirst, m_pLast, random_generator{ random_device{}() });
                 m_pCur = m_pFirst;
             }
         };
@@ -241,7 +277,7 @@ namespace cds { namespace opt {
                 <tt>int(Generator) + nOffset</tt>
             where \p Generator - a permutation generator.
 
-            The class is suitable for opt::permutation_generator option
+            The class is suitable for \p opt::permutation_generator option
             if the goal sequence should be a permutation of <tt>[nOffset, nOffset + nLength)</tt>
         */
         template <typename Generator>
@@ -290,4 +326,4 @@ namespace cds { namespace opt {
 
 }} // namespace cds::opt
 
-#endif // #ifndef __CDS_OPT_PERMUTATION_H
+#endif // #ifndef CDSLIB_OPT_PERMUTATION_H