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?

\$\endgroup\$
2

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.

\$\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\$
    – Kid
    Commented Jan 31, 2017 at 9:33

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.