dimanche 2 avril 2017

Atomic variables are not updated instantaneously

I have a program that uploads data to a server in another thread (std::thread). I would like to monitor the progress of the data transfer using some atomic doubles. The client writes data like this (for full disclosure I didn't remove the write calls):

setUploadProgress(0,static_cast<double>(message.size()));
while(static_cast<long>(message.size()) - count >= max_length)
{
    boost::asio::write(socket_,
                       boost::asio::buffer(message.substr(count,max_length)));
    count += max_length;
    setUploadProgress(static_cast<double>(count),static_cast<double>(message.size()));
}
boost::asio::write(socket_,boost::asio::buffer(message.substr(count,max_length)),boost::asio::transfer_at_least(static_cast<long>(message.size()) - count),error);
setUploadProgress(static_cast<double>(message.size()),static_cast<double>(message.size()));
handle_write(error);

This will write max_length at a time, and update the progress variables. setUploadProgress looks like this:

void SSLClient::setUploadProgress(double uploadedSize, double totalSize)
{
    std::lock_guard<decltype(this->progress_mutex)> lg(this->progress_mutex);
    if(this->progressValue_uploaded != nullptr) this->progressValue_uploaded->store(uploadedSize);
    if(this->progressValue_uploadTotalSize != nullptr) this->progressValue_uploadTotalSize->store(totalSize);
}

The following is how I capture the upload progress:

auto resultFuture = fileToUpload.promise.get_future();
commThreadController->uploadFile(&fileToUpload);
while (resultFuture.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready)
{
    std::cerr<<fileToUpload.getProgress()*100.<<"%"<<std::endl;
    QCoreApplication::processEvents();
}
uploadFinished(resultFuture.get(),fileToUpload);

And this is how fileToUpload.getProgress() looks like:

double FileToUpload::getProgress() const
{
    return progressValue_uploaded.load()/progressValue_uploadTotalSize.load();
}

The problem: I can see that the value of the progress is updated very often (by simply couting the progress value on every update), for a specific case I've been studying, up to about every 0.1%. However, on the main thread, I see the change only every 3%! What synchronization option should I be using to make this fast that every update can be seen in the main thread? By default everything is synchronized with memory_order_seq_cst (which is basically the best sync I know of), but that doesn't seem to be enough! What am I missing?

Aucun commentaire:

Enregistrer un commentaire