19
19
#include < sys/types.h>
20
20
#include < sys/stat.h>
21
21
#include < signal.h>
22
+ #include < future>
22
23
23
24
#include < event2/event.h>
24
25
#include < event2/http.h>
34
35
#endif
35
36
#endif
36
37
37
- #include < boost/algorithm/string/case_conv.hpp> // for to_lower()
38
- #include < boost/foreach.hpp>
39
-
40
38
/* * Maximum size of http request (request line + headers) */
41
39
static const size_t MAX_HEADERS_SIZE = 8192 ;
42
40
@@ -68,8 +66,8 @@ class WorkQueue
68
66
{
69
67
private:
70
68
/* * Mutex protects entire object */
71
- CWaitableCriticalSection cs;
72
- CConditionVariable cond;
69
+ std::mutex cs;
70
+ std::condition_variable cond;
73
71
std::deque<std::unique_ptr<WorkItem>> queue;
74
72
bool running;
75
73
size_t maxDepth;
@@ -82,12 +80,12 @@ class WorkQueue
82
80
WorkQueue &wq;
83
81
ThreadCounter (WorkQueue &w): wq(w)
84
82
{
85
- boost ::lock_guard<boost ::mutex> lock (wq.cs );
83
+ std ::lock_guard<std ::mutex> lock (wq.cs );
86
84
wq.numThreads += 1 ;
87
85
}
88
86
~ThreadCounter ()
89
87
{
90
- boost ::lock_guard<boost ::mutex> lock (wq.cs );
88
+ std ::lock_guard<std ::mutex> lock (wq.cs );
91
89
wq.numThreads -= 1 ;
92
90
wq.cond .notify_all ();
93
91
}
@@ -108,7 +106,7 @@ class WorkQueue
108
106
/* * Enqueue a work item */
109
107
bool Enqueue (WorkItem* item)
110
108
{
111
- boost ::unique_lock<boost ::mutex> lock (cs);
109
+ std ::unique_lock<std ::mutex> lock (cs);
112
110
if (queue.size () >= maxDepth) {
113
111
return false ;
114
112
}
@@ -123,7 +121,7 @@ class WorkQueue
123
121
while (running) {
124
122
std::unique_ptr<WorkItem> i;
125
123
{
126
- boost ::unique_lock<boost ::mutex> lock (cs);
124
+ std ::unique_lock<std ::mutex> lock (cs);
127
125
while (running && queue.empty ())
128
126
cond.wait (lock);
129
127
if (!running)
@@ -137,22 +135,22 @@ class WorkQueue
137
135
/* * Interrupt and exit loops */
138
136
void Interrupt ()
139
137
{
140
- boost ::unique_lock<boost ::mutex> lock (cs);
138
+ std ::unique_lock<std ::mutex> lock (cs);
141
139
running = false ;
142
140
cond.notify_all ();
143
141
}
144
142
/* * Wait for worker threads to exit */
145
143
void WaitExit ()
146
144
{
147
- boost ::unique_lock<boost ::mutex> lock (cs);
145
+ std ::unique_lock<std ::mutex> lock (cs);
148
146
while (numThreads > 0 )
149
147
cond.wait (lock);
150
148
}
151
149
152
150
/* * Return current depth of queue */
153
151
size_t Depth ()
154
152
{
155
- boost ::unique_lock<boost ::mutex> lock (cs);
153
+ std ::unique_lock<std ::mutex> lock (cs);
156
154
return queue.size ();
157
155
}
158
156
};
@@ -189,7 +187,7 @@ static bool ClientAllowed(const CNetAddr& netaddr)
189
187
{
190
188
if (!netaddr.IsValid ())
191
189
return false ;
192
- BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
190
+ for (const CSubNet& subnet : rpc_allow_subnets)
193
191
if (subnet.Match (netaddr))
194
192
return true ;
195
193
return false ;
@@ -203,7 +201,7 @@ static bool InitHTTPAllowList()
203
201
rpc_allow_subnets.push_back (CSubNet (" ::1" )); // always allow IPv6 localhost
204
202
if (mapMultiArgs.count (" -rpcallowip" )) {
205
203
const std::vector<std::string>& vAllow = mapMultiArgs[" -rpcallowip" ];
206
- BOOST_FOREACH (std::string strAllow, vAllow) {
204
+ for (std::string strAllow : vAllow) {
207
205
CSubNet subnet (strAllow);
208
206
if (!subnet.IsValid ()) {
209
207
uiInterface.ThreadSafeMessageBox (
@@ -215,7 +213,7 @@ static bool InitHTTPAllowList()
215
213
}
216
214
}
217
215
std::string strAllowed;
218
- BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
216
+ for (const CSubNet& subnet : rpc_allow_subnets)
219
217
strAllowed += subnet.ToString () + " " ;
220
218
LogPrint (" http" , " Allowing HTTP connections from: %s\n " , strAllowed);
221
219
return true ;
@@ -302,13 +300,14 @@ static void http_reject_request_cb(struct evhttp_request* req, void*)
302
300
}
303
301
304
302
/* * Event dispatcher thread */
305
- static void ThreadHTTP (struct event_base * base, struct evhttp * http)
303
+ static bool ThreadHTTP (struct event_base * base, struct evhttp * http)
306
304
{
307
305
RenameThread (" bitcoin-http" );
308
306
LogPrint (" http" , " Entering http event loop\n " );
309
307
event_base_dispatch (base);
310
308
// Event loop will be interrupted by InterruptHTTPServer()
311
309
LogPrint (" http" , " Exited http event loop\n " );
310
+ return event_base_got_break (base) == 0 ;
312
311
}
313
312
314
313
/* * Bind HTTP server to specified addresses */
@@ -437,17 +436,22 @@ bool InitHTTPServer()
437
436
return true ;
438
437
}
439
438
440
- boost::thread threadHTTP;
439
+ std::thread threadHTTP;
440
+ std::future<bool > threadResult;
441
441
442
442
bool StartHTTPServer ()
443
443
{
444
444
LogPrint (" http" , " Starting HTTP server\n " );
445
445
int rpcThreads = std::max ((long )GetArg (" -rpcthreads" , DEFAULT_HTTP_THREADS), 1L );
446
446
LogPrintf (" HTTP: starting %d worker threads\n " , rpcThreads);
447
- threadHTTP = boost::thread (boost::bind (&ThreadHTTP, eventBase, eventHTTP));
447
+ std::packaged_task<bool (event_base*, evhttp*)> task (ThreadHTTP);
448
+ threadResult = task.get_future ();
449
+ threadHTTP = std::thread (std::move (task), eventBase, eventHTTP);
448
450
449
- for (int i = 0 ; i < rpcThreads; i++)
450
- boost::thread (boost::bind (&HTTPWorkQueueRun, workQueue));
451
+ for (int i = 0 ; i < rpcThreads; i++) {
452
+ std::thread rpc_worker (HTTPWorkQueueRun, workQueue);
453
+ rpc_worker.detach ();
454
+ }
451
455
return true ;
452
456
}
453
457
@@ -456,7 +460,7 @@ void InterruptHTTPServer()
456
460
LogPrint (" http" , " Interrupting HTTP server\n " );
457
461
if (eventHTTP) {
458
462
// Unlisten sockets
459
- BOOST_FOREACH (evhttp_bound_socket *socket, boundSockets) {
463
+ for (evhttp_bound_socket *socket : boundSockets) {
460
464
evhttp_del_accept_socket (eventHTTP, socket);
461
465
}
462
466
// Reject requests on current connections
@@ -482,15 +486,11 @@ void StopHTTPServer()
482
486
// master that appears to be solved, so in the future that solution
483
487
// could be used again (if desirable).
484
488
// (see discussion in https://github.com/bitcoin/bitcoin/pull/6990)
485
- #if BOOST_VERSION >= 105000
486
- if (!threadHTTP.try_join_for (boost::chrono::milliseconds (2000 ))) {
487
- #else
488
- if (!threadHTTP.timed_join (boost::posix_time::milliseconds (2000 ))) {
489
- #endif
489
+ if (threadResult.valid () && threadResult.wait_for (std::chrono::milliseconds (2000 )) == std::future_status::timeout) {
490
490
LogPrintf (" HTTP event loop did not exit within allotted time, sending loopbreak\n " );
491
491
event_base_loopbreak (eventBase);
492
- threadHTTP.join ();
493
492
}
493
+ threadHTTP.join ();
494
494
}
495
495
if (eventHTTP) {
496
496
evhttp_free (eventHTTP);
@@ -517,7 +517,7 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data)
517
517
delete self;
518
518
}
519
519
520
- HTTPEvent::HTTPEvent (struct event_base * base, bool deleteWhenTriggered, const boost ::function<void (void )>& handler):
520
+ HTTPEvent::HTTPEvent (struct event_base * base, bool deleteWhenTriggered, const std ::function<void (void )>& handler):
521
521
deleteWhenTriggered(deleteWhenTriggered), handler(handler)
522
522
{
523
523
ev = event_new (base, -1 , 0 , httpevent_callback_fn, this );
@@ -599,7 +599,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
599
599
assert (evb);
600
600
evbuffer_add (evb, strReply.data (), strReply.size ());
601
601
HTTPEvent* ev = new HTTPEvent (eventBase, true ,
602
- boost ::bind (evhttp_send_reply, req, nStatus, (const char *)NULL , (struct evbuffer *)NULL ));
602
+ std ::bind (evhttp_send_reply, req, nStatus, (const char *)NULL , (struct evbuffer *)NULL ));
603
603
ev->trigger (0 );
604
604
replySent = true ;
605
605
req = 0 ; // transferred back to main thread
0 commit comments