Skip to content

Commit 637b626

Browse files
author
Koen Deforche
committed
Several changes:
- WResource: added static resource concurrency test - WResource: reorganized resource/continuations concurrency - WResource: allow aborted requests to be handled, and allow an individual request to be continued - Http::Client: allow response data to be processed incrementally
1 parent eaad228 commit 637b626

File tree

14 files changed

+388
-201
lines changed

14 files changed

+388
-201
lines changed

CMakeLists.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ IF(BOOST_WT_MT_FOUND)
377377
IF(MULTI_THREADED)
378378
MESSAGE("** Enabling multi threading.")
379379
SET(MULTI_THREADED_BUILD true)
380-
381-
ADD_DEFINITIONS(-DWT_THREADED -D_REENTRANT -DBOOST_SPIRIT_THREADSAFE)
380+
SET(WT_THREADED true)
381+
ADD_DEFINITIONS(-D_REENTRANT -DBOOST_SPIRIT_THREADSAFE)
382382
ELSE(MULTI_THREADED)
383383
MESSAGE("** Disabling multi threading.")
384384
SET(MULTI_THREADED_BUILD false)

WConfig.h.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#cmakedefine WT_NO_STD_WSTRING
4141
#cmakedefine WT_USE_OPENGL
4242
#cmakedefine WT_DEBUG_ENABLED
43+
#cmakedefine WT_THREADED
4344

4445
#cmakedefine WT_USE_BOOST_SIGNALS
4546
#cmakedefine WT_USE_BOOST_SIGNALS2

src/Wt/Http/Response

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,14 @@ public:
112112
WT_BOSTREAM& bout() { return out(); }
113113

114114
private:
115-
WResource *resource_;
116-
WebResponse *response_;
117-
ResponseContinuation *continuation_;
118-
WT_BOSTREAM *out_;
119-
bool headersCommitted_;
115+
WResource *resource_;
116+
WebResponse *response_;
117+
ResponseContinuationPtr continuation_;
118+
WT_BOSTREAM *out_;
119+
bool headersCommitted_;
120120

121121
Response(WResource *resource, WebResponse *response,
122-
ResponseContinuation *continuation);
122+
ResponseContinuationPtr continuation);
123123
Response(WResource *resource, WT_BOSTREAM& out);
124124

125125
friend class Wt::WResource;

src/Wt/Http/Response.C

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,19 @@ void Response::addHeader(const std::string& name, const std::string& value)
4040

4141
ResponseContinuation *Response::createContinuation()
4242
{
43-
if (!continuation_)
44-
continuation_ = new ResponseContinuation(resource_, response_);
45-
else
43+
if (!continuation_) {
44+
ResponseContinuation *c = new ResponseContinuation(resource_, response_);
45+
continuation_ = resource_->addContinuation(c);
46+
} else
4647
continuation_->resource_ = resource_;
4748

48-
return continuation_;
49+
return continuation_.get();
4950
}
5051

5152
ResponseContinuation *Response::continuation() const
5253
{
5354
if (continuation_ && continuation_->resource_)
54-
return continuation_;
55+
return continuation_.get();
5556
else
5657
return 0;
5758
}
@@ -126,7 +127,7 @@ WT_BOSTREAM& Response::out()
126127
}
127128

128129
Response::Response(WResource *resource, WebResponse *response,
129-
ResponseContinuation *continuation)
130+
ResponseContinuationPtr continuation)
130131
: resource_(resource),
131132
response_(response),
132133
continuation_(continuation),
@@ -137,7 +138,6 @@ Response::Response(WResource *resource, WebResponse *response,
137138
Response::Response(WResource *resource, WT_BOSTREAM& out)
138139
: resource_(resource),
139140
response_(0),
140-
continuation_(0),
141141
out_(&out),
142142
headersCommitted_(false)
143143
{ }

src/Wt/Http/ResponseContinuation

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,13 @@
1010
#include <Wt/WGlobal>
1111
#include <boost/any.hpp>
1212

13+
#include <boost/shared_ptr.hpp>
14+
#include <boost/enable_shared_from_this.hpp>
15+
16+
namespace boost {
17+
class recursive_mutex;
18+
}
19+
1320
namespace Wt {
1421

1522
class WResource;
@@ -42,9 +49,12 @@ namespace Wt {
4249
*
4350
* \ingroup http
4451
*/
45-
class WT_API ResponseContinuation
52+
class WT_API ResponseContinuation
53+
: public boost::enable_shared_from_this<ResponseContinuation>
4654
{
4755
public:
56+
~ResponseContinuation();
57+
4858
/*! \brief Set data associated with the continuation.
4959
*
5060
* You could do this to keep track of the state of sending the data
@@ -83,30 +93,31 @@ public:
8393
*/
8494
bool isWaitingForMoreData() const { return waiting_; }
8595

86-
/*
87-
* Only useful for server-side events: force continuation.
88-
*/
89-
void doContinue(WebWriteEvent event);
90-
9196
private:
97+
#ifdef WT_THREADED
98+
boost::shared_ptr<boost::recursive_mutex> mutex_;
99+
#endif
100+
92101
WResource *resource_;
93102
WebResponse *response_;
94103
boost::any data_;
95-
bool waiting_, readyToContinue_, needsContinue_;
104+
bool waiting_, readyToContinue_;
96105

97106
ResponseContinuation(WResource *resource, WebResponse *response);
98107
ResponseContinuation(const ResponseContinuation&);
99-
~ResponseContinuation();
100108

101-
void cancel();
102-
void flagReadyToContinue(WebWriteEvent);
109+
void cancel(bool resourceIsBeingDeleted);
110+
void readyToContinue(WebWriteEvent writeResult);
111+
103112
WebResponse *response() { return response_; }
104113

105114
friend class Wt::WResource;
106115
friend class Wt::WebSession;
107116
friend class Response;
108117
};
109118

119+
typedef boost::shared_ptr<ResponseContinuation> ResponseContinuationPtr;
120+
110121
}
111122
}
112123

src/Wt/Http/ResponseContinuation.C

Lines changed: 80 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010

1111
#include "WebRequest.h"
1212

13+
#ifdef WT_THREADED
14+
#include <boost/thread.hpp>
15+
#endif
16+
1317
namespace Wt {
1418

1519
LOGGER("Http::ResponseContinuation");
@@ -23,79 +27,106 @@ void ResponseContinuation::setData(const boost::any& data)
2327

2428
void ResponseContinuation::haveMoreData()
2529
{
26-
if (isWaitingForMoreData())
27-
doContinue(WriteCompleted);
30+
WResource::UseLock useLock;
31+
WResource *resource = 0;
32+
33+
{
34+
#ifdef WT_THREADED
35+
boost::recursive_mutex::scoped_lock lock(*mutex_);
36+
#endif // WT_THREADED
37+
38+
if (!useLock.use(resource_))
39+
return;
40+
41+
if (waiting_) {
42+
waiting_ = false;
43+
if (readyToContinue_) {
44+
readyToContinue_ = false;
45+
resource = resource_;
46+
resource_ = 0;
47+
}
48+
}
49+
}
50+
51+
if (resource)
52+
resource->doContinue(shared_from_this());
2853
}
2954

30-
void ResponseContinuation::doContinue(WebWriteEvent event)
55+
void ResponseContinuation::readyToContinue(WebWriteEvent event)
3156
{
3257
if (event == WriteError) {
3358
LOG_ERROR("WriteError");
34-
cancel();
59+
cancel(false);
3560
return;
3661
}
3762

38-
/*
39-
* Although we are waiting for more data, we're not yet ready to continue
40-
* We'll remember to continue as soon as we become ready.
41-
*/
42-
if (waiting_ && !readyToContinue_) {
43-
needsContinue_ = true;
44-
return;
45-
}
63+
WResource::UseLock useLock;
64+
WResource *resource = 0;
65+
66+
{
67+
#ifdef WT_THREADED
68+
boost::recursive_mutex::scoped_lock lock(*mutex_);
69+
#endif // WT_THREADED
4670

47-
waiting_ = false;
48-
needsContinue_ = false;
71+
if (!useLock.use(resource_))
72+
return;
4973

50-
// We are certain that the continuation is still "alive" because it is
51-
// protected by a mutex, and thus a simultaneous change with
52-
// WebResponse::flush() is not possible: ResponseContinuation::cancel(),
53-
// called from beingDeleted() and protected by the same mutex
54-
// will not be called while we are here.
55-
resource_->doContinue(this);
74+
readyToContinue_ = true;
75+
76+
if (!waiting_) {
77+
readyToContinue_ = false;
78+
resource = resource_;
79+
resource_ = 0;
80+
}
81+
}
82+
83+
if (resource)
84+
resource->doContinue(shared_from_this());
5685
}
5786

5887
ResponseContinuation::ResponseContinuation(WResource *resource,
5988
WebResponse *response)
60-
: resource_(resource),
89+
:
90+
#ifdef WT_THREADED
91+
mutex_(resource->mutex_),
92+
#endif
93+
resource_(resource),
6194
response_(response),
6295
waiting_(false),
63-
readyToContinue_(false),
64-
needsContinue_(false)
65-
{
66-
resource_->continuations_.push_back(this);
67-
}
96+
readyToContinue_(false)
97+
{ }
6898

69-
void ResponseContinuation::cancel()
99+
void ResponseContinuation::cancel(bool resourceIsBeingDeleted)
70100
{
71-
Http::Request request(*response_, this);
72-
resource_->handleAbort(request);
73-
resource_->removeContinuation(this);
74-
75-
response_->flush(WebResponse::ResponseDone);
101+
WResource::UseLock useLock;
102+
WResource *resource = 0;
103+
104+
{
105+
#ifdef WT_THREADED
106+
boost::recursive_mutex::scoped_lock lock(*mutex_);
107+
#endif // WT_THREADED
108+
109+
if (resourceIsBeingDeleted) {
110+
if (!resource_)
111+
return;
112+
} else if (!useLock.use(resource_))
113+
return;
114+
115+
resource = resource_;
116+
resource_ = 0;
117+
}
76118

77-
delete this;
119+
if (resource) {
120+
Http::Request request(*response_, this);
121+
resource->handleAbort(request);
122+
resource->removeContinuation(shared_from_this());
123+
response_->flush(WebResponse::ResponseDone);
124+
}
78125
}
79126

80127
void ResponseContinuation::waitForMoreData()
81128
{
82129
waiting_ = true;
83-
needsContinue_ = false;
84-
readyToContinue_ = false;
85-
}
86-
87-
void ResponseContinuation::flagReadyToContinue(WebWriteEvent event)
88-
{
89-
if (event == WriteError) {
90-
LOG_ERROR("WriteError");
91-
cancel();
92-
return;
93-
}
94-
95-
readyToContinue_ = true;
96-
97-
if (needsContinue_)
98-
doContinue(event);
99130
}
100131

101132
ResponseContinuation::~ResponseContinuation()

src/Wt/WAbstractMedia.C

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,7 @@ void WAbstractMedia::setFormData(const FormData& formData)
127127
try {
128128
readyState_ = intToReadyState(boost::lexical_cast<int>(attributes[5]));
129129
} catch (const std::exception& e) {
130-
throw WException("WAbstractMedia: error parsing: " + formData.values[0]
131-
+ ": " + e.what());
130+
readyState_ = HaveNothing;
132131
}
133132
} else
134133
throw WException("WAbstractMedia: error parsing: " + formData.values[0]);

src/Wt/WBoostAny.C

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <map>
77
#include <boost/lexical_cast.hpp>
88
#include <stdio.h>
9-
9+
#include "Wt/WConfig.h"
1010
#ifdef WT_THREADED
1111
#include <boost/thread.hpp>
1212
#include <boost/shared_ptr.hpp>

0 commit comments

Comments
 (0)