The concurrent_queue class does not provide assignment operator or copy constructor, but I am stuck in a condition where i want to assign a concurrent_queue variable to another variable of concurrent_queue. Is there any way or trick around?
Thanks in advance
Let me ask why do you need to copy a queue?
The concurrent queue is not likea integral type; it's a complex object, and in fact the tbb::concurrent_queue class only represents the high-level interface while implementation is done in internal classes. I do not see how a copy operation on a queue would be useful; copying it without user data is of no value because you might just create a new queue object, while copying it with all user data is questionable from many standpoints. The same is true for any container, actually. Also for TBB containers and concurrent_queue in particular, thread safety is another concern: what if another thread inserts more elements into the queue while it is being copied?
If you provide any idea what so special you try to do that requires copying a concurrent_queue object, we might give you some idea how to do it another way.
Agreed that my design has some flaws, that I/we need to re-think and re-design it.
But the current design forces me to have copy-constructor for concurrent_queue. I will take care of multithreading and related issues.
It may sound bad to you, the TBB developers, but the fact is that a container should provide flexibility in its usage. The container (of any type) can be used in millions of ways, so it is irrelevant where and why I (or anyone) is putting a container in software design. Just like 'resize' is provided for CV, and well mentioned that it's not thread-safe, CQ should have similar constructs (CTOR is one of them) - that may be thread-unsafe as well.
In a spreadsheet making a 3D bar-chart on the basis of lastname may sound absurd, but developer can't escape saying this type of chart doesn't make sense. The chart may be bizzare, ugly and making no-sense, but the spreadsheet program is still "flexible" enough to facilitate the same. I guess you got my point.
Your points are well taken. I agree that a generic container should be flexible enough to help developers to get their job done easily and quickly. Unfortunately, flexibility does not come for free and we have to consider return-on-investment for each feature that we want to support. As Alexey mentioned before, we don't see any compelling use cases for copy constructor(s) of the concurrent queue container, and few customers have asked for them. If we see a sufficiently large traction for them, weMIGHTCONSIDER supportingthem in the future.
In the meantime, if you really need to have a copy constructor of concurrent queue, you may create your own cq, let it inherit from TBB concurrent queue and define the copy constructor there. Either you can use 'iterator' to copy over all the elements to the new queue or you can pop each element from the old queue and push it back into the old queue as well as the new queue.Please note that none of the options guarantee thread-safety as Alexeywarned before.
nitinsayare:Agreed that my design has some flaws, that I/we need to re-think and re-design it.
I did not mean anything like this. If my post sounded this way to you, I apologize.
nitinsayare:But the current design forces me to have copy-constructor for concurrent_queue. I will take care of multithreading and related issues.
... it is irrelevant where and why I (or anyone) is putting a container in software design.
Again, I meant nothing except willing to help you use the container as it is now, and possibly collect the requirements for its improvement; thusthe questions. It sounds like you got me wrong. Nevertheless, TBB's concurrent_queue does not allow copy construction or assignment at the moment. I am sorry but for now you have to use some workaround. I am sure you will find the best way for that.
That said, I think that providing a constructor that takes a couple of input iterators [begin, end) and adds every element in between to the queue would probably be generic and non-contradictory enough to be reasonable to implement. The question is, could we make it more efficient than explicitly pushing each element?
Thanks for the suggestions. I deeply regret for any rudeness caused.We'll think about deriving class from CQ.
The thing is that 2 instances of tbb::concurrent_queue are inside a structure (along with other data-members). This structure is "type" for another vector. The vector is extensively used throughout the application. The 2 instances of CQ inside play important role for the sockets (more details are unneeded, I guess).
Now the each element of vector is moving around, requiring assignment operator and C-CTOR for struct (and thus the CQ instances).
We also thought of using pointers (of CQ, or of the struct) instead of instance variables, as you might suggest. But that adds complexity, re-design, code-reviews and re-testing. This all can be done, but we may still need copy-constructable CQ in future.
Your answer suggests me that you actually need a constructor that supports move semantics, as in the end you are not interested in the original element of the vector, only in the new one. Does that sound right? A moving constructor for a container makes perfect sense to me; it allows "shallow" copying which is more efficient and also does not duplicate the contained data. Unfortunately at the moment, move semantics is not supported by the C++ language, so we all have to use copy construction instead, which affects performance, increases memory usage (at least temporarily),and creates potential data duplication issues. The upcoming C++0x standard addresses this problem; and I think future TBB containers will provide efficient moving constructors.
If you use CQ inside another structure, you possibly don't need to derive a class from CQ, if you could use the copy constructor of that structure to pop all elements from the original queue and push to the newly createdone. Assumed moving semantics of your whole operation suggests popping from the old queue instead of iterating over it; the latter would create a "duplicate" while the former "moves" data by deleting those from the original queue.