20
20
#include < sys/types.h>
21
21
#include < sys/stat.h>
22
22
#include < signal.h>
23
+ #include < future>
23
24
24
25
#include < event2/event.h>
25
26
#include < event2/http.h>
35
36
#endif
36
37
#endif
37
38
38
- #include < boost/algorithm/string/case_conv.hpp> // for to_lower()
39
- #include < boost/foreach.hpp>
40
-
41
39
/* * Maximum size of http request (request line + headers) */
42
40
static const size_t MAX_HEADERS_SIZE = 8192 ;
43
41
@@ -69,8 +67,8 @@ class WorkQueue
69
67
{
70
68
private:
71
69
/* * Mutex protects entire object */
72
- CWaitableCriticalSection cs;
73
- CConditionVariable cond;
70
+ std::mutex cs;
71
+ std::condition_variable cond;
74
72
std::deque<std::unique_ptr<WorkItem>> queue;
75
73
bool running;
76
74
size_t maxDepth;
@@ -83,12 +81,12 @@ class WorkQueue
83
81
WorkQueue &wq;
84
82
ThreadCounter (WorkQueue &w): wq(w)
85
83
{
86
- boost ::lock_guard<boost ::mutex> lock (wq.cs );
84
+ std ::lock_guard<std ::mutex> lock (wq.cs );
87
85
wq.numThreads += 1 ;
88
86
}
89
87
~ThreadCounter ()
90
88
{
91
- boost ::lock_guard<boost ::mutex> lock (wq.cs );
89
+ std ::lock_guard<std ::mutex> lock (wq.cs );
92
90
wq.numThreads -= 1 ;
93
91
wq.cond .notify_all ();
94
92
}
@@ -109,7 +107,7 @@ class WorkQueue
109
107
/* * Enqueue a work item */
110
108
bool Enqueue (WorkItem* item)
111
109
{
112
- boost ::unique_lock<boost ::mutex> lock (cs);
110
+ std ::unique_lock<std ::mutex> lock (cs);
113
111
if (queue.size () >= maxDepth) {
114
112
return false ;
115
113
}
@@ -124,7 +122,7 @@ class WorkQueue
124
122
while (true ) {
125
123
std::unique_ptr<WorkItem> i;
126
124
{
127
- boost ::unique_lock<boost ::mutex> lock (cs);
125
+ std ::unique_lock<std ::mutex> lock (cs);
128
126
while (running && queue.empty ())
129
127
cond.wait (lock);
130
128
if (!running)
@@ -138,14 +136,14 @@ class WorkQueue
138
136
/* * Interrupt and exit loops */
139
137
void Interrupt ()
140
138
{
141
- boost ::unique_lock<boost ::mutex> lock (cs);
139
+ std ::unique_lock<std ::mutex> lock (cs);
142
140
running = false ;
143
141
cond.notify_all ();
144
142
}
145
143
/* * Wait for worker threads to exit */
146
144
void WaitExit ()
147
145
{
148
- boost ::unique_lock<boost ::mutex> lock (cs);
146
+ std ::unique_lock<std ::mutex> lock (cs);
149
147
while (numThreads > 0 ){
150
148
cond.wait (lock);
151
149
}
@@ -154,7 +152,7 @@ class WorkQueue
154
152
/* * Return current depth of queue */
155
153
size_t Depth ()
156
154
{
157
- boost ::unique_lock<boost ::mutex> lock (cs);
155
+ std ::unique_lock<std ::mutex> lock (cs);
158
156
return queue.size ();
159
157
}
160
158
};
@@ -191,7 +189,7 @@ static bool ClientAllowed(const CNetAddr& netaddr)
191
189
{
192
190
if (!netaddr.IsValid ())
193
191
return false ;
194
- BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
192
+ for (const CSubNet& subnet : rpc_allow_subnets)
195
193
if (subnet.Match (netaddr))
196
194
return true ;
197
195
return false ;
@@ -209,7 +207,7 @@ static bool InitHTTPAllowList()
209
207
rpc_allow_subnets.push_back (CSubNet (localv6)); // always allow IPv6 localhost
210
208
if (mapMultiArgs.count (" -rpcallowip" )) {
211
209
const std::vector<std::string>& vAllow = mapMultiArgs[" -rpcallowip" ];
212
- BOOST_FOREACH (std::string strAllow, vAllow) {
210
+ for (std::string strAllow : vAllow) {
213
211
CSubNet subnet;
214
212
LookupSubNet (strAllow.c_str (), subnet);
215
213
if (!subnet.IsValid ()) {
@@ -222,7 +220,7 @@ static bool InitHTTPAllowList()
222
220
}
223
221
}
224
222
std::string strAllowed;
225
- BOOST_FOREACH (const CSubNet& subnet, rpc_allow_subnets)
223
+ for (const CSubNet& subnet : rpc_allow_subnets)
226
224
strAllowed += subnet.ToString () + " " ;
227
225
LogPrint (" http" , " Allowing HTTP connections from: %s\n " , strAllowed);
228
226
return true ;
@@ -309,13 +307,14 @@ static void http_reject_request_cb(struct evhttp_request* req, void*)
309
307
}
310
308
311
309
/* * Event dispatcher thread */
312
- static void ThreadHTTP (struct event_base * base, struct evhttp * http)
310
+ static bool ThreadHTTP (struct event_base * base, struct evhttp * http)
313
311
{
314
312
RenameThread (" dynamic-http" );
315
313
LogPrint (" http" , " Entering http event loop\n " );
316
314
event_base_dispatch (base);
317
315
// Event loop will be interrupted by InterruptHTTPServer()
318
316
LogPrint (" http" , " Exited http event loop\n " );
317
+ return event_base_got_break (base) == 0 ;
319
318
}
320
319
321
320
/* * Bind HTTP server to specified addresses */
@@ -444,17 +443,22 @@ bool InitHTTPServer()
444
443
return true ;
445
444
}
446
445
447
- boost::thread threadHTTP;
446
+ std::thread threadHTTP;
447
+ std::future<bool > threadResult;
448
448
449
449
bool StartHTTPServer ()
450
450
{
451
451
LogPrint (" http" , " Starting HTTP server\n " );
452
452
int rpcThreads = std::max ((long )GetArg (" -rpcthreads" , DEFAULT_HTTP_THREADS), 1L );
453
453
LogPrintf (" HTTP: starting %d worker threads\n " , rpcThreads);
454
- threadHTTP = boost::thread (boost::bind (&ThreadHTTP, eventBase, eventHTTP));
454
+ std::packaged_task<bool (event_base*, evhttp*)> task (ThreadHTTP);
455
+ threadResult = task.get_future ();
456
+ threadHTTP = std::thread (std::move (task), eventBase, eventHTTP);
455
457
456
- for (int i = 0 ; i < rpcThreads; i++)
457
- boost::thread (boost::bind (&HTTPWorkQueueRun, workQueue));
458
+ for (int i = 0 ; i < rpcThreads; i++) {
459
+ std::thread rpc_worker (HTTPWorkQueueRun, workQueue);
460
+ rpc_worker.detach ();
461
+ }
458
462
return true ;
459
463
}
460
464
@@ -463,7 +467,7 @@ void InterruptHTTPServer()
463
467
LogPrint (" http" , " Interrupting HTTP server\n " );
464
468
if (eventHTTP) {
465
469
// Unlisten sockets
466
- BOOST_FOREACH (evhttp_bound_socket *socket, boundSockets) {
470
+ for (evhttp_bound_socket *socket : boundSockets) {
467
471
evhttp_del_accept_socket (eventHTTP, socket);
468
472
}
469
473
// Reject requests on current connections
@@ -494,16 +498,11 @@ void StopHTTPServer()
494
498
// master that appears to be solved, so in the future that solution
495
499
// could be used again (if desirable).
496
500
// (see discussion in https://github.com/bitcoin/bitcoin/pull/6990)
497
- #if BOOST_VERSION >= 105000
498
- if (!threadHTTP.try_join_for (boost::chrono::milliseconds (2000 ))) {
499
- #else
500
- if (!threadHTTP.timed_join (boost::posix_time::milliseconds (2000 ))) {
501
- #endif
502
-
501
+ + if (threadResult.valid () && threadResult.wait_for (std::chrono::milliseconds (2000 )) == std::future_status::timeout) {
503
502
LogPrintf (" HTTP event loop did not exit within allotted time, sending loopbreak\n " );
504
503
event_base_loopbreak (eventBase);
505
- threadHTTP.join ();
506
504
}
505
+ threadHTTP.join ();
507
506
}
508
507
if (eventHTTP) {
509
508
evhttp_free (eventHTTP);
@@ -530,7 +529,7 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data)
530
529
delete self;
531
530
}
532
531
533
- HTTPEvent::HTTPEvent (struct event_base * base, bool deleteWhenTriggered, const boost ::function<void (void )>& handler):
532
+ HTTPEvent::HTTPEvent (struct event_base * base, bool deleteWhenTriggered, const std ::function<void (void )>& handler):
534
533
deleteWhenTriggered(deleteWhenTriggered), handler(handler)
535
534
{
536
535
ev = event_new (base, -1 , 0 , httpevent_callback_fn, this );
@@ -612,7 +611,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
612
611
assert (evb);
613
612
evbuffer_add (evb, strReply.data (), strReply.size ());
614
613
HTTPEvent* ev = new HTTPEvent (eventBase, true ,
615
- boost ::bind (evhttp_send_reply, req, nStatus, (const char *)NULL , (struct evbuffer *)NULL ));
614
+ std ::bind (evhttp_send_reply, req, nStatus, (const char *)NULL , (struct evbuffer *)NULL ));
616
615
ev->trigger (0 );
617
616
replySent = true ;
618
617
req = 0 ; // transferred back to main thread
0 commit comments