Use std::unique_ptr for handling http work items, and std::move to move them into and out of the queue.
This makes the code more RAII and, as mentioned in the comment, is what I planned when I wrote the code in the first place.
Use std::unique_ptr for handling http work items, and std::move to move them into and out of the queue.
This makes the code more RAII and, as mentioned in the comment, is what I planned when I wrote the code in the first place.
70 | @@ -71,8 +71,7 @@ class WorkQueue 71 | /** Mutex protects entire object */ 72 | CWaitableCriticalSection cs; 73 | CConditionVariable cond; 74 | - /* XXX in C++11 we can use std::unique_ptr here and avoid manual cleanup */ 75 | - std::deque<WorkItem*> queue; 76 | + std::deque<std::unique_ptr<WorkItem> > queue;
Also, in C++11, you no longer need to avoid the '>>' in Template1<Template2<Template3>>.
I was just about to ask why the space is there...
@paveljanik because >> is an operator. But yes with c++11 this is apparently parsed differently so will remove the space.
104 | @@ -106,19 +105,15 @@ class WorkQueue
105 | */
106 | ~WorkQueue()
Do we need an empty destructor?
I'll remove it.
On second thought, I'm going to keep it, the precondition comment is still relevant.
287 | assert(workQueue); 288 | - if (workQueue->Enqueue(item.get())) 289 | - item.release(); /* if true, queue took ownership */ 290 | - else 291 | + if (!workQueue->Enqueue(std::move(item))) 292 | item->req->WriteReply(HTTP_INTERNAL, "Work queue depth exceeded");
item has been given to the queue here
use after move here
The actual moving happens in unique_ptr's ctor. The function just needs to accept a unique_ptr&&, then it can freely move that into a new unique_ptr or not.
It doesn't seem to work. I've tested with a (hacked) work-queue size of 0, and the connection is closed before the error message can be sent.
Leaving out the std::move in the ->Enqueue line gives a compile error about pointer conversions:
/home/orion/projects/bitcoin/bitcoin/src/httpserver.cpp:289:33: error: no viable conversion from 'unique_ptr<HTTPWorkItem>' to 'unique_ptr<HTTPClosure>'
if (!workQueue->Enqueue(item))
Bleh.
Decided to forget about using std::move to move items conditionally into the queue, the resulting code was too complex, the old code is cleaner.
111 | @@ -118,7 +112,7 @@ class WorkQueue 112 | if (queue.size() >= maxDepth) { 113 | return false; 114 | } 115 | - queue.push_back(item); 116 | + queue.push_back(std::unique_ptr<WorkItem>(item));
nit: queue.emplace_back(item);
ut ACK, other than the little nit
Use std::unique_ptr for handling work items.
This makes the code more RAII and, as mentioned in the comment, is what
I planned when I wrote the code in the first place.
More useful error reporting.
No need for boost here.
Thanks to Cory Fields for the idea.
111 | @@ -118,7 +112,7 @@ class WorkQueue 112 | if (queue.size() >= maxDepth) { 113 | return false; 114 | } 115 | - queue.push_back(item); 116 | + queue.emplace_back(std::unique_ptr<WorkItem>(item));
Creating the unique_ptr here defeats the purpose of the emplace :) Passing it item directly would mean that the unique_ptr would be constructed in-place. As is, it's moved instead.
Not worth worrying about, just pointing it out.
Yes by all means feel free to improve this further.