add "insert item troubleshooting" to docs
authorkhizmax <khizmax@gmail.com>
Fri, 24 Oct 2014 09:10:37 +0000 (13:10 +0400)
committerkhizmax <khizmax@gmail.com>
Fri, 24 Oct 2014 09:10:37 +0000 (13:10 +0400)
13 files changed:
cds/container/impl/lazy_kvlist.h
cds/container/impl/lazy_list.h
cds/container/impl/michael_kvlist.h
cds/container/impl/michael_list.h
cds/container/lazy_kvlist_rcu.h
cds/container/lazy_list_rcu.h
cds/container/michael_kvlist_rcu.h
cds/container/michael_list_rcu.h
cds/intrusive/details/base.h
cds/intrusive/impl/lazy_list.h
cds/intrusive/impl/michael_list.h
cds/intrusive/lazy_list_rcu.h
cds/intrusive/michael_list_rcu.h

index d736e62057498e1612e8361996f7f9fed1a2f609..e593b827c94b0137c1b798e9f43b502efcae74b3 100644 (file)
@@ -427,6 +427,8 @@ namespace cds { namespace container {
 
             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
 
             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
@@ -471,11 +473,11 @@ namespace cds { namespace container {
             however, \p func must guarantee that during changing no any other modifications
             could be made on this item by concurrent threads.
 
             however, \p func must guarantee that during changing no any other modifications
             could be made on this item by concurrent threads.
 
-            You may pass \p func argument by reference using \p std::ref.
-
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
index 427dcaf2124c930f6567d450ca3cda1ab1eb6d14..dfed21d8732ff11400327b0210fe1f8c65c52be3 100644 (file)
@@ -389,6 +389,8 @@ namespace cds { namespace container {
 
             This can be useful if complete initialization of object of \p value_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
 
             This can be useful if complete initialization of object of \p value_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
@@ -431,11 +433,11 @@ namespace cds { namespace container {
             The functor may change non-key fields of the \p item; however, \p func must guarantee
             that during changing no any other modifications could be made on this item by concurrent threads.
 
             The functor may change non-key fields of the \p item; however, \p func must guarantee
             that during changing no any other modifications could be made on this item by concurrent threads.
 
-            You may pass \p func argument by reference using \p std::ref
-
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func f )
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func f )
index 09623b0371d84ef81474155c0dd25622bf78dcc4..7dce75f5c7a586d7118573918c564e91eb1e0f1e 100644 (file)
@@ -395,6 +395,8 @@ namespace cds { namespace container {
 
             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
 
             This can be useful if complete initialization of object of \p mapped_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
@@ -432,6 +434,8 @@ namespace cds { namespace container {
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
index d600a9e1822a549b36d46792ae094591d79ecb63..17224e31d5d5a1488af0c568b4fc17d1844325d5 100644 (file)
@@ -352,6 +352,8 @@ namespace cds { namespace container {
 
             The method can be useful if complete initialization of object of \p value_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The method can be useful if complete initialization of object of \p value_type is heavyweight and
             it is preferable that the initialization should be completed only if inserting is successful.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
@@ -387,6 +389,8 @@ namespace cds { namespace container {
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func func )
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func func )
index f1b9afe8b0ec1409fff13e4ccc9b9dc8823d9acf..3456a29cd405eb6ed663006187d9654ae221d1f4 100644 (file)
@@ -411,6 +411,8 @@ namespace cds { namespace container {
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
@@ -457,13 +459,13 @@ namespace cds { namespace container {
             however, \p func must guarantee that during changing no any other modifications
             could be made on this item by concurrent threads.
 
             however, \p func must guarantee that during changing no any other modifications
             could be made on this item by concurrent threads.
 
-            You may pass \p func argument by reference using \p std::ref
-
             The function makes RCU lock internally.
 
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             The function makes RCU lock internally.
 
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
index 6b2ac2f20fee9c220a895ff3a439ee426e3ab4ad..5e694a7bd2839c77bff42a7a0af4235bed4177c0 100644 (file)
@@ -385,6 +385,8 @@ namespace cds { namespace container {
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
@@ -436,6 +438,8 @@ namespace cds { namespace container {
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func f )
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func f )
index 04bc71a72c7d1bf44effc13b2fb756342652ea61..b7fc1ad2195b8fc501745a2c9874dc8b1f2431af 100644 (file)
@@ -382,6 +382,8 @@ namespace cds { namespace container {
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
         */
         template <typename K, typename Func>
         bool insert_key( const K& key, Func func )
@@ -423,6 +425,8 @@ namespace cds { namespace container {
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
         */
         template <typename K, typename Func>
         std::pair<bool, bool> ensure( const K& key, Func f )
index 071b976bd625e082c48bee033c2cd92d0b91f13c..65a8351e0a8dcd0beb328bf63bc5e5adab070925 100644 (file)
@@ -356,6 +356,8 @@ namespace cds { namespace container {
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
             it is preferable that the initialization should be completed only if inserting is successful.
 
             The function makes RCU lock internally.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
         */
         template <typename Q, typename Func>
         bool insert( Q const& key, Func func )
@@ -393,6 +395,8 @@ namespace cds { namespace container {
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool> </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func f )
         */
         template <typename Q, typename Func>
         std::pair<bool, bool> ensure( Q const& key, Func f )
index 73c653de9f725932eb60678f3c0b38de1bd7328c..5bf0b38942c0b09f3766c27b21acdc42a2bab817 100644 (file)
@@ -31,7 +31,138 @@ namespace cds {
     struct tag1;
     cds::intrusive::treiber_stack::node< cds::gc::HP, tag<tag1> > 
     \endcode
     struct tag1;
     cds::intrusive::treiber_stack::node< cds::gc::HP, tag<tag1> > 
     \endcode
-    If no tag is specified åðó default \p cds::opt::none will be used.
+    If no tag is specified the default \p cds::opt::none will be used.
+
+    \anchor cds_intrusive_item_creating
+    \par Inserting items
+    Many intrusive and non-intrusive (standard-like) containers in the library have the member functions 
+    that take an functor argument to initialize the inserted item after it has been successfully inserted, 
+    for example:
+    \code
+    template <typename Q, typename Func>
+    bool insert( Q& key, Func f );
+
+    template <typename Q, typename Func>
+    std::pair<bool, bool> ensure( Q& key, Func f );
+    \endcode
+    The first member function calls \p f functor iif an new item has been inserted. The functor takes two parameter: a reference to inserted item and
+    \p key.
+
+    The second member function, \p ensure, allows to insert a new item to the container if \p key is not found, or to find the item with \p key and
+    to perform some action with it. The \p f signature is:
+    \code
+    void f( bool bNew, item_type& item, Q& key );
+    \endcode
+    where \p bNew is a flag to indicate whether \p item is a new created node or not.
+
+    Such functions should be used with caution in multi-threaded environment
+    since they can cause races. The library does not synchronize access
+    to container's items, so many threads can access to one item simultaneously.
+    For example, for \p insert member function the following race is possible:
+    \code
+        // Suppose, Foo is a complex structure with int key field
+        SomeContainer<Foo> q;
+
+        Thread 1                                  Thread 2
+
+        q.insert( Foo(5),                         q.find( 5, []( Foo& item ) {
+            []( Foo& item ){                         // access to item fields
+               // complex initialization             ...
+               item.f1 = ...;                     });
+               ...
+            });
+    \endcode
+    Execute sequence:
+    \code
+        Find 5 in the container.
+        Key 5 is not found
+        Create a new item                         Find key 5
+            with calling Foo(5) ctor
+        Insert the new item
+                                                  The key 5 is found - 
+                                                     call the functor     (!)
+        Perform complex
+           initialization - 
+           call the functor
+    \endcode
+    (!): Thread 2 found the key and call its functor on incomplete initialized item.
+    Simultaneous access to the item also is possible. In this case Thread 1 is
+    initializing the item, thread 2 is reading (or writing) the item's fields. 
+    In any case, Thread 2 can read uninitialized or incomplete initialized fields.
+
+    \p ensure member function race. Suppose, thread 1 and thread 2 perform 
+    the 
+    following code:
+    \code
+        q.ensure( 5, []( bool bNew, Foo& item, int  arg )
+           {
+              // bNew: true if the new element has been created
+              //       false otherwise
+              if ( bNew ) {
+                 // initialize item
+                 item.f1=...;
+                 //...
+              }
+              else {
+                 // do some work
+                 if ( !item.f1 ) 
+                    item.f1 = ...;
+                 else {
+                   //...
+                 }
+                 //...
+              }
+           }
+        );
+    \endcode
+    Execute sequence:
+    \code
+        Thread 1                                  Thread 2
+        key 5 not found
+        insert new item Foo(5)                    Find 5
+                                                  Key 5 found
+                                                  call the functor with 
+                                                     bNew = false        (!)
+        call the functor with
+           bNew = true
+    \endcode
+    (!): Thread 2 executes its functor on incomplete initialized item. 
+
+    To protect your code from such races you can use some item-level synchronization,
+    for example:
+    \code
+    struct Foo {
+       spinlock lock;       // item-level lock
+       bool initialized = false;    // initialization flag
+       // other fields
+       // ....
+    };
+
+    q.ensure( 5, []( bool bNew, Foo& item, int  arg )
+        {
+            // Lock access to the item
+            std::unique_lock( item.lock );
+
+            if ( !item.initialized ) {
+                // initialize item
+                item.f1=...;
+                //...
+                item.initialized = true; // mark the item as initialized
+            }
+            else {
+                // do some work
+                if ( !item.f1 ) 
+                    item.f1 = ...;
+                else {
+                    //...
+                }
+                //...
+            }
+        }
+    );
+    \endcode
+    If the item-level synchronization is not suitable, you should not use any inserting member function
+    with post-insert functor argument.
 
     \anchor cds_intrusive_item_destroying
     \par Destroying items
 
     \anchor cds_intrusive_item_destroying
     \par Destroying items
index 273a14c8f94520cfd37a4b2fac548dca6ecd7321..4e29b4cc056ea8d1029992e3265b71b6174c3f47 100644 (file)
@@ -537,8 +537,9 @@ namespace cds { namespace intrusive {
             \endcode
             where \p val is the item inserted.
             While the functor \p f is working the item \p val is locked.
             \endcode
             where \p val is the item inserted.
             While the functor \p f is working the item \p val is locked.
-            The user-defined functor is called only if the inserting is success and may be passed by reference
-            using \p std::ref
+            The user-defined functor is called only if the inserting is success.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
@@ -566,11 +567,11 @@ namespace cds { namespace intrusive {
             The functor may change non-key fields of the \p item.
             While the functor \p f is working the item \p item is locked.
 
             The functor may change non-key fields of the \p item.
             While the functor \p f is working the item \p item is locked.
 
-            You may pass \p func argument by reference using \p std::ref.
-
             Returns std::pair<bool, bool> where \p first is \p true if operation is successfull,
             \p second is \p true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns std::pair<bool, bool> where \p first is \p true if operation is successfull,
             \p second is \p true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
         std::pair<bool, bool> ensure( value_type& val, Func func )
         */
         template <typename Func>
         std::pair<bool, bool> ensure( value_type& val, Func func )
index 8c2980ba37095c201960f16682bef384f11179f9..2922cb6ab14a7c64b8342f27ecbb09bc671bafab 100644 (file)
@@ -517,6 +517,8 @@ namespace cds { namespace intrusive {
             where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
             \p val no any other changes could be made on this list's item by concurrent threads.
             The user-defined functor is called only if the inserting is success.
             where \p val is the item inserted. User-defined functor \p f should guarantee that during changing
             \p val no any other changes could be made on this list's item by concurrent threads.
             The user-defined functor is called only if the inserting is success.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
@@ -547,6 +549,8 @@ namespace cds { namespace intrusive {
             Returns std::pair<bool, bool> where \p first is \p true if operation is successfull,
             \p second is \p true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns std::pair<bool, bool> where \p first is \p true if operation is successfull,
             \p second is \p true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
         std::pair<bool, bool> ensure( value_type& val, Func func )
         */
         template <typename Func>
         std::pair<bool, bool> ensure( value_type& val, Func func )
index 48dbd6046d9f969cd1f87d28ce1cb10e096e1607..4ac0a86316bb5ef5e04af24818f99baa610588b7 100644 (file)
@@ -444,8 +444,9 @@ namespace cds { namespace intrusive {
             \endcode
             where \p val is the item inserted.
             While the functor \p f is working the item \p val is locked.
             \endcode
             where \p val is the item inserted.
             While the functor \p f is working the item \p val is locked.
-            The user-defined functor is called only if the inserting is success and may be passed by reference
-            using \p std::ref.
+            The user-defined functor is called only if the inserting is success.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
@@ -475,11 +476,11 @@ namespace cds { namespace intrusive {
             The functor may change non-key fields of the \p item.
             While the functor \p f is calling the item \p item is locked.
 
             The functor may change non-key fields of the \p item.
             While the functor \p f is calling the item \p item is locked.
 
-            You may pass \p func argument by reference using \p std::ref.
-
             Returns <tt> std::pair<bool, bool>  </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
             Returns <tt> std::pair<bool, bool>  </tt> where \p first is true if operation is successfull,
             \p second is true if new item has been added or \p false if the item with \p key
             already is in the list.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
 
         template <typename Func>
         */
 
         template <typename Func>
index 4ff82b575cd59da22f3a624e4b0a376be9812b42..1cd4b6622977c6a76c6b5e4c6beafa107b262995 100644 (file)
@@ -340,6 +340,8 @@ namespace cds { namespace intrusive {
             The user-defined functor is called only if the inserting is success.
 
             The function makes RCU lock internally.
             The user-defined functor is called only if the inserting is success.
 
             The function makes RCU lock internally.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
         */
         template <typename Func>
         bool insert( value_type& val, Func f )
@@ -374,6 +376,8 @@ namespace cds { namespace intrusive {
             already is in the list.
 
             The function makes RCU lock internally.
             already is in the list.
 
             The function makes RCU lock internally.
+
+            @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
         */
         template <typename Func>
         std::pair<bool, bool> ensure( value_type& val, Func func )
         */
         template <typename Func>
         std::pair<bool, bool> ensure( value_type& val, Func func )