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 )
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.
+
+ @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 )
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 )
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.
+
+ @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 )
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 )
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 )
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 )
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 )
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 )
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.
+
+ @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 )
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 )
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 )
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 )
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 )
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 )
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 )
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
\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 )
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.
+
+ @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
*/
template <typename Func>
std::pair<bool, bool> ensure( value_type& val, Func func )
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 )
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 )
\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 )
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.
+
+ @warning See \ref cds_intrusive_item_creating "insert item troubleshooting"
*/
template <typename Func>
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 )
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 )