[intrusive] list compatibility with existing application-defined intrusive lists
Hi all, boost::intrusive lists can be easily customized to be compatible with an existing doubly-linked intrusive list implementation, such as the one used in the linux kernel (struct list_head). Indeed, I have been able to declare and use a boost::intrusive::list of my own with custom traits that uses struct list_head as the underlying representation, enabling me to simply use .end().pointed_node() to get access to the list head and pass it to legacy C code that expects a struct list_head*. However, I can't think of a way to achieve interoperability in the opposite direction. For example, I have an existing function (to be precise, a callback that I pass to legacy C code), that accepts a struct list_head* that is expected to contain a list of elements of a certain type. I want some way to "wrap" this raw pointer in a type-safe intrusive list type that I use as naturally as a boost::intrusive::list (iteration, modification, etc.). I see no way to achieve this. The way I see it, what I need is a boost::intrusive::list_ptr, a container that doesn't actually own the list head, but rather, points to a list head stored elsewhere. It would have the same interface as a list, allowing me to push_back, clear, etc., but behaves as a pointer when it comes to moves and copies. Additionally, there should also be a boost::intrusive::const_list_ptr, which will not allow me to modify the list, but still allows iteration and other non-modifying operations. Unless, of course, there are already existing mechanisms to achieve this. If anyone has any ideas, please let me know. Thanks.
Hi,
maybe it's possible to "creatively" use the three-argument version of circular_list_algorithms::transfer. Create an empty intrusive::list, and use transfer on the "other" list as the source. It's a constant-time operation that will relink the nodes from the "other" list to the empty intrusive::list. When you're done with the list, use transfer to perform the inverse operation.
Of course, this temporarily changes the original list. If this is a no-go, I see no other way than either just using circular_list_algorithms directly (poorer interface than list) or writing your own wrapper.
________________________________
From: Boost-users
On 03/02/2018 21:42, Rahul Ramadas via Boost-users wrote:
For example, I have an existing function (to be precise, a callback that I pass to legacy C code), that accepts a struct list_head* that is expected to contain a list of elements of a certain type. I want some way to "wrap" this raw pointer in a type-safe intrusive list type that I use as naturally as a boost::intrusive::list (iteration, modification, etc.). I see no way to achieve this.
The way I see it, what I need is a boost::intrusive::list_ptr, a container that doesn't actually own the list head, but rather, points to a list head stored elsewhere. It would have the same interface as a list, allowing me to push_back, clear, etc., but behaves as a pointer when it comes to moves and copies. Additionally, there should also be a boost::intrusive::const_list_ptr, which will not allow me to modify the list, but still allows iteration and other non-modifying operations.
Unless, of course, there are already existing mechanisms to achieve this. If anyone has any ideas, please let me know.
There is no way to do it with containers, you could use node algorithms directly. On the other hand there is some undocumented support to have a different header holding policy (header_holder_type), but it assumes the the header holder internally holds the header node (allocating it dynamically or by any other mechanism). There is no interface to modify this header holder to, say, set the a pointer to the header node. In any case, I think having the possibility to hold the header node externally it's a useful extension to Boost.Intrusive. Best, Ion
participants (3)
-
Ion Gaztañaga
-
Rahul Ramadas
-
Stian Zeljko Vrba