jeudi 9 mars 2017

Proper usage of std::atomic, pre increment value as function param

I have code where I need unique id (packet id for some protocol). So I used std::atomic<int>. After reading documentation I was confused because it stated that increment is done in this way. fetch_add(1)+1

I understand that value inside fetch_add is incremented atomically but I get pre-increment value +1 outside atomic operation. What I would guess is not atomic.

Can I use some_func(++atomic_value)?

I wrote simple code to check if it works. And it works but I don't understand why.

#include<iostream>
#include <atomic>
#include <thread>
#include <vector>
#include <random>
#include <mutex>
#include <algorithm>

std::atomic<int> Index = 0;
//int Index = 0; // non atomic Index. It will generate duplicities

std::vector<int> Numbers;
std::mutex Mutex;
std::default_random_engine Generator;
std::uniform_int_distribution<int> Distribution(5, 10);

void func(int Value)
{
    std::lock_guard<std::mutex> Guard(Mutex);
    Numbers.push_back(Value);
}

void ThreadProc()
{
    Sleep(Distribution(Generator));
    func(++Index); // is this proper usage of std::atomic?
}

int main()
{
    const int ThreadCount = 1000;
    std::vector<std::thread> Threads;

    for ( int i = 0; i < ThreadCount; i++ )
    {
        Threads.push_back(std::thread(ThreadProc));
    }

    for_each(Threads.begin(), Threads.end(), [](std::thread& t) { t.join(); });

    std::sort(Numbers.begin(), Numbers.end());
    auto End = std::unique(Numbers.begin(), Numbers.end());

    if ( Numbers.end() == End )
    {
        std::cout << "No duplicites found." << std::endl;
    }
    else
    {
        std::cout << "Duplicites found ! - " << Numbers.end() - End << std::endl;
        for_each(End, Numbers.end(), [](int n) { std::cout << n << ", "; });
    }

    return 0;
}

Off-topic question: When I defined Index as non atomic I get duplicities but only from end of range. Numbers are always 900+. Why it is so?

Aucun commentaire:

Enregistrer un commentaire