1
\$\begingroup\$

The following is a class for curl wrapper.

This class will be called like:

 class curlWrapper {
private:
 CURLcode curlCode;
 CURL* curlHandle;
 struct curl_slist *header = NULL;
 MemoryStructA response;
 static std::atomic<int> numberOfCurlProcess;
 static std::atomic<bool> isGlobalInitCalled;
 static std::mutex curlGlobalkey; 
public:
 curlWrapper(){
 curlGlobalkey.lock();
 if(!isGlobalInitCalled)
 {
 curl_global_init(CURL_GLOBAL_ALL); // this should be called only once in the entire program when a first object using this class.
 numberOfCurlProcess++;
 }
 else
 {
 numberOfCurlProcess++;
 }
 curlGlobalkey.unlock();
 //globalCurlInit();
 initializeMemoryStruct();
 }
 ~curlWrapper(){
 curlGlobalkey.lock();
 if(numberOfCurlProcess > 0)
 {
 numberOfCurlProcess--;
 }
 else if(numberOfCurlProcess == 0)
 {
 // this should be called only once in the entire program when a last object using this class.
 curl_global_cleanup();
 }
 curlGlobalkey.unlock();
 }
 int trace(CURL *handle, curl_infotype type, char *data, size_t size, void *classPointer);
 int traceImpl(CURL *handle, curl_infotype type, char *data, size_t size);
 CURL* curlInit();
 void curlClose();
 bool initializeConnection();
 bool sendRequest(const char* request);
 char* getResponse();
 void setMemorytoWrite();
 bool listen();
 void closeConnection();
 bool setURL(const char* url);
 bool setHttpHeader(const char * contentType, const char * charSet);
 void setTrace(bool trace);// If true trace will be displayd
 bool curlExec();
 void initializeMemoryStruct();
 void globalCurlInit();
 void globalCulrClean();
};

This class will be used as:

 class Accessor{
 public:
 curlWrapper *curl = new curlWrapper()
 };
main(){
 //somewhere in the main
 Accessor aa = new Accessor();
 Accessor bb = new Accessor();
 thread(aa).doProcess();
 thread(bb).dpProcess()
}

Did I call curl_global_init(CURL_GLOBAL_ALL) at first thread starts and only once? Similarly, did I call curl_global_cleanup() while the last thread ends?

Heslacher
50.9k5 gold badges83 silver badges177 bronze badges
asked Jan 30, 2017 at 15:41
\$\endgroup\$
2
  • \$\begingroup\$ You can benchmark it and see how often it gets called using cProfile like here. \$\endgroup\$ Commented Jan 30, 2017 at 16:10
  • \$\begingroup\$ I have rolled back the last edit. Please see what you may and may not do after receiving answers . \$\endgroup\$ Commented Jan 31, 2017 at 9:36

1 Answer 1

2
\$\begingroup\$

Based on the code you have listed, the answer to both of your questions is: no.

curl_global_init(CURL_GLOBAL_ALL) won't be called only once as you're checking isGlobalInitCalled but not setting it to indicate the initialization shouldn't be done again. curl_global_cleanup() won't be called because you have no matching delete-expression for the destructors to get called (see the memory leaks portion of new expression).

Regarding how to make this work...

For the one-time-initialization, you could eliminate the use of the isGlobalInitCalled variable and just use numberOfCurlProcess instead (in the constructor) like this:

curlWrapper() {
 curlGlobalkey.lock();
 if(numberOfCurlProcess == 0)
 {
 curl_global_init(CURL_GLOBAL_ALL); // this should be called only once in the entire program when a first object using this class.
 }
 numberOfCurlProcess++;
 curlGlobalkey.unlock();
 //globalCurlInit();
 initializeMemoryStruct();
}

For the one-time-cleanup, I'd suggest using smart pointers which "enable automatic, exception-safe, object lifetime management". As to how code using smart pointers could look, that can depend on what the newest version of the C++ standard is that you're able to use. With C++14, I'd use code that instead looked more like:

class Accessor {
public:
 std::unique_ptr<curlWrapper> curl = std::make_unique<curlWrapper>();
};
main() { 
 //somewhere in the main
 std::unique_ptr<Accessor> aa = std::make_unique<Accessor>();
 std::unique_ptr<Accessor> bb = std::make_unique<Accessor>();
 thread(aa).doProcess();
 thread(bb).doProcess();
}

There are other ways to solve the second problem too but if you're going to dynamically allocate instances, smart pointers is the way I'd suggest managing memory as they'll take care of calling the instances' destructors for you.

answered Jan 31, 2017 at 0:41
\$\endgroup\$
1
  • \$\begingroup\$ Hi, Thanks I found the mistake for first question I included a code to change the bool value. And also included a call which calls destructor of the wrapper. \$\endgroup\$ Commented Jan 31, 2017 at 9:33

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.