The program
Reads out a textfile and emails it’s contents
The original code (with help of Sehe)
https://gist.github.com/1342118#file_test.cpp
The problem:
I am trying to run the application multiple times using threading, using a different textfile for each thread. This means I can no longer use a global vector because thread 3 may add to / alter this vector while thread 1 is still working on it. This means this line is becoming problematic:
curl_easy_setopt(curl, CURLOPT_READFUNCTION, read_callback);
This calls this function:
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct WriteThis *pooh = (struct WriteThis *)userp;
if(size*nmemb < 1)
return 0;
if (pooh->counter < text.size())
{
const std::string& data = text[pooh->counter];
memcpy(ptr, data.data(), data.length());
pooh->counter++; /* advance pointer */
return data.length();
}
return 0; /* no more data left to deliver */
}
As you can see it uses the globally defined vector “text”. I thought I could fix it by simply making the vector inside that function (read_callback) but since I’m using threading now, the filename is no longer hard coded so I end up having to pass a variable anyway.
Curl seems to fill in the variables that read_callback accepts automatically so how is this done?
Just to clarify, here’s what I have now:
std::vector<string> read_text(char* fname)
{
std::ifstream myfile (fname);
std::vector<string> text;
std::string line;
while (std::getline(myfile, line))
{
text.push_back(line + '\n');
}
return text;
}
static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *userp)
{
std::vector<string> text;
text = read_text(textfilename);
struct WriteThis *pooh = (struct WriteThis *)userp;
if(size*nmemb < 1)
return 0;
if (pooh->counter < text.size())
{
const std::string& data = text[pooh->counter];
memcpy(ptr, data.data(), data.length());
pooh->counter++; /* advance pointer */
return data.length();
}
return 0; /* no more data left to deliver */
}
But read_text doesn’t work because textfilename hasn’t been passed to the function.
Read carefully again curl_easy_setopt‘s documentation. You might set the
CURLOPT_READDATAto yourtextfilenameand cast theuserpto get it inside yourread_callbackedit
Your
userpis actually used; so you should add thetextfilenamein a new field of yourWriteThisstruct. Most callback functions take only one user data, but it should be enough (since you can pack arbitrary stuff in it).