Skip to content

Commit 863eb0f

Browse files
authored
Merge pull request #104 from sergey-shambir/noncopyable_multi
2 parents 59623ae + f4928ff commit 863eb0f

File tree

2 files changed

+53
-49
lines changed

2 files changed

+53
-49
lines changed

include/curl_multi.h

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -212,17 +212,15 @@ namespace curl {
212212
* to initialize the entire curl environment using custom
213213
* options.
214214
*/
215-
explicit curl_multi(const long);
215+
explicit curl_multi(const long globalOptions);
216216
/**
217-
* Copy constructor to perform a correct copy of the curl
218-
* handler and attributes.
217+
* Move constructor which moves internal data to another object.
219218
*/
220-
curl_multi(const curl_multi &);
219+
curl_multi(curl_multi&&);
221220
/**
222-
* Assignment operator. Let's apply the rule of three to
223-
* avoid strange situations!
221+
* Move assignment operator which moves internal data to another object.
224222
*/
225-
curl_multi &operator=(const curl_multi &);
223+
curl_multi& operator=(curl_multi&&);
226224
/**
227225
* Destructor to deallocate all the resources using
228226
* libcurl.
@@ -318,9 +316,16 @@ namespace curl {
318316
*/
319317
CURLM *get_curl() const;
320318
private:
319+
struct milti_deleter
320+
{
321+
void operator()(CURLM* ptr) const;
322+
};
323+
324+
using multi_ptr = std::unique_ptr<CURLM, milti_deleter>;
325+
321326
int message_queued;
322327
int active_transfers;
323-
CURLM *curl;
328+
multi_ptr curl;
324329
};
325330

326331
// Implementation of add method
@@ -370,11 +375,6 @@ namespace curl {
370375
inline const void *curl_multi::curl_message::get_other() const {
371376
return this->whatever;
372377
}
373-
374-
// Implementation of get_curl method.
375-
inline CURLM *curl_multi::get_curl() const {
376-
return this->curl;
377-
}
378378
}
379379

380380
#undef CURLCPP_DEFINE_OPTION

src/curl_multi.cpp

Lines changed: 40 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -11,57 +11,56 @@ using curl::curl_easy;
1111
using std::vector;
1212
using std::unique_ptr;
1313

14-
// Implementation of constructor.
15-
curl_multi::curl_multi() : curl_interface() {
16-
this->curl = curl_multi_init();
14+
void curl_multi::milti_deleter::operator()(CURLM* ptr) const
15+
{
16+
curl_multi_cleanup(ptr);
17+
}
18+
19+
curl_multi::curl_multi() : curl_multi(CURL_GLOBAL_ALL) {
20+
}
21+
22+
curl_multi::curl_multi(const long flag)
23+
: curl_interface(flag),
24+
curl(curl_multi_init()) {
1725
if (this->curl == nullptr) {
18-
throw curl_multi_exception("Null pointer intercepted",__FUNCTION__);
26+
throw curl_multi_exception("Null pointer intercepted", __FUNCTION__);
1927
}
2028
this->active_transfers = 0;
2129
this->message_queued = 0;
2230
}
2331

24-
// Implementation of overloaded constructor.
25-
curl_multi::curl_multi(const long flag) : curl_interface(flag) {
26-
curl_multi();
32+
curl_multi::curl_multi(curl_multi&& other)
33+
: curl_interface(std::forward<curl_interface>(other)),
34+
curl(std::move(other.curl)),
35+
active_transfers(other.active_transfers),
36+
message_queued(other.message_queued) {
2737
}
2838

29-
// Implementation of copy constructor to respect the rule of three.
30-
curl_multi::curl_multi(const curl_multi &multi)
31-
: curl_interface(),
32-
message_queued(multi.message_queued),
33-
active_transfers(multi.active_transfers) {
34-
this->curl = curl_multi_init();
35-
if (this->curl == nullptr) {
36-
throw curl_multi_exception("Null pointer intercepted",__FUNCTION__);
39+
curl_multi &curl_multi::operator=(curl_multi&& other) {
40+
if (this != &other) {
41+
curl = std::move(other.curl);
42+
active_transfers = other.active_transfers;
43+
message_queued = other.message_queued;
3744
}
38-
}
3945

40-
// Implementation of assignment operator to perform deep copy.
41-
curl_multi &curl_multi::operator=(const curl_multi &multi) {
42-
if (this == &multi) {
43-
return *this;
44-
}
45-
curl_multi();
4646
return *this;
4747
}
4848

49-
// Implementation of destructor.
50-
curl_multi::~curl_multi() NOEXCEPT{
51-
curl_multi_cleanup(this->curl);
49+
curl_multi::~curl_multi() NOEXCEPT
50+
{
5251
}
5352

5453
// Implementation of add method for easy handlers.
5554
void curl_multi::add(const curl_easy &easy) {
56-
const CURLMcode code = curl_multi_add_handle(this->curl,easy.get_curl());
55+
const CURLMcode code = curl_multi_add_handle(this->curl.get(),easy.get_curl());
5756
if (code != CURLM_OK) {
5857
throw curl_multi_exception(code,__FUNCTION__);
5958
}
6059
}
6160

6261
// Implementation of remove for easy handlers.
6362
void curl_multi::remove(const curl_easy &easy) {
64-
const CURLMcode code = curl_multi_remove_handle(this->curl,easy.get_curl());
63+
const CURLMcode code = curl_multi_remove_handle(this->curl.get(),easy.get_curl());
6564
if (code != CURLM_OK) {
6665
throw curl_multi_exception(code,__FUNCTION__);
6766
}
@@ -71,7 +70,7 @@ void curl_multi::remove(const curl_easy &easy) {
7170
vector<unique_ptr<curl_multi::curl_message>> curl_multi::get_info() {
7271
vector<unique_ptr<curl_multi::curl_message>> infos;
7372
CURLMsg *message = nullptr;
74-
while ((message = curl_multi_info_read(this->curl,&this->message_queued))) {
73+
while ((message = curl_multi_info_read(this->curl.get(),&this->message_queued))) {
7574
infos.push_back(unique_ptr<curl_multi::curl_message>(new curl_multi::curl_message(message)));
7675
}
7776
return infos;
@@ -80,7 +79,7 @@ vector<unique_ptr<curl_multi::curl_message>> curl_multi::get_info() {
8079
// Implementation of overloaded get_info method.
8180
unique_ptr<curl_multi::curl_message> curl_multi::get_info(const curl_easy &easy) {
8281
CURLMsg *message = nullptr;
83-
while ((message = curl_multi_info_read(this->curl,&this->message_queued))) {
82+
while ((message = curl_multi_info_read(this->curl.get(),&this->message_queued))) {
8483
if (message->easy_handle == easy.get_curl()) {
8584
unique_ptr<curl_multi::curl_message> ptr{new curl_multi::curl_message(message)};
8685
return ptr;
@@ -92,7 +91,7 @@ unique_ptr<curl_multi::curl_message> curl_multi::get_info(const curl_easy &easy)
9291
// Implementation of is_finished method.
9392
bool curl_multi::is_finished(const curl_easy &easy) {
9493
CURLMsg *message = nullptr;
95-
while ((message = curl_multi_info_read(this->curl,&this->message_queued))) {
94+
while ((message = curl_multi_info_read(this->curl.get(),&this->message_queued))) {
9695
if (message->easy_handle == easy.get_curl() and message->msg == CURLMSG_DONE) {
9796
return true;
9897
}
@@ -102,7 +101,7 @@ bool curl_multi::is_finished(const curl_easy &easy) {
102101

103102
// Implementation of perform method.
104103
bool curl_multi::perform() {
105-
const CURLMcode code = curl_multi_perform(this->curl,&this->active_transfers);
104+
const CURLMcode code = curl_multi_perform(this->curl.get(),&this->active_transfers);
106105
if (code == CURLM_CALL_MULTI_PERFORM) {
107106
return false;
108107
}
@@ -114,7 +113,7 @@ bool curl_multi::perform() {
114113

115114
// Implementation of socket_action method.
116115
bool curl_multi::socket_action(const curl_socket_t sockfd, const int ev_bitmask) {
117-
const CURLMcode code = curl_multi_socket_action(this->curl,sockfd,ev_bitmask,&this->active_transfers);
116+
const CURLMcode code = curl_multi_socket_action(this->curl.get(),sockfd,ev_bitmask,&this->active_transfers);
118117
if (code == CURLM_CALL_MULTI_PERFORM) {
119118
return false;
120119
}
@@ -126,31 +125,31 @@ bool curl_multi::socket_action(const curl_socket_t sockfd, const int ev_bitmask)
126125

127126
// Implementation of set_fd method.
128127
void curl_multi::set_descriptors(fd_set *read, fd_set *write, fd_set *exec, int *max_fd) {
129-
const CURLMcode code = curl_multi_fdset(this->curl,read,write,exec,max_fd);
128+
const CURLMcode code = curl_multi_fdset(this->curl.get(),read,write,exec,max_fd);
130129
if (code != CURLM_OK) {
131130
throw curl_multi_exception(code,__FUNCTION__);
132131
}
133132
}
134133

135134
// Implementation of wait method.
136135
void curl_multi::wait(struct curl_waitfd extra_fds[], const unsigned int extra_nfds, const int timeout_ms, int *numfds) {
137-
const CURLMcode code = curl_multi_wait(this->curl,extra_fds,extra_nfds,timeout_ms,numfds);
136+
const CURLMcode code = curl_multi_wait(this->curl.get(),extra_fds,extra_nfds,timeout_ms,numfds);
138137
if (code != CURLM_OK) {
139138
throw curl_multi_exception(code,__FUNCTION__);
140139
}
141140
}
142141

143142
// Implementation of assign method.
144143
void curl_multi::assign(const curl_socket_t sockfd, void *sockptr) {
145-
const CURLMcode code = curl_multi_assign(this->curl,sockfd,sockptr);
144+
const CURLMcode code = curl_multi_assign(this->curl.get(),sockfd,sockptr);
146145
if (code != CURLM_OK) {
147146
throw curl_multi_exception(code,__FUNCTION__);
148147
}
149148
}
150149

151150
// Implementation of timeout method.
152151
void curl_multi::timeout(long *timeout) {
153-
const CURLMcode code = curl_multi_timeout(this->curl,timeout);
152+
const CURLMcode code = curl_multi_timeout(this->curl.get(),timeout);
154153
if (code != CURLM_OK) {
155154
throw curl_multi_exception(code,__FUNCTION__);
156155
}
@@ -161,3 +160,8 @@ curl_multi::curl_message::curl_message(const CURLMsg *msg) :
161160
message(msg->msg), whatever(msg->data.whatever), code(msg->data.result) {
162161
// ... nothing to do here ...
163162
}
163+
164+
// Implementation of get_curl method.
165+
CURLM *curl_multi::get_curl() const {
166+
return this->curl.get();
167+
}

0 commit comments

Comments
 (0)