C++ Concurrency in Action 9.6 threadpool использует thread_local

Говорят, что thread_local имеет одну копию на поток.

Итак, если поток threadPool (назовем его A) создает другой поток (назовем его B), переменные thread_local (local_work_queue) в потоках A и B — это две разные вещи。

Поэтому я путаю это, когда задача саммита пула в потоке пула A (int main()), как она может получить доступ к local_work_queue в подпотоке B??? они совершенно неактуальны.

Функция submit находится в потоке пула, а local_work_queue инициализируется только в подпотоке, поэтому в функции отправки local_work_queue всегда будет nullptr, не так ли?

Ниже приведен код:

class thread_pool
{
    typedef std::queue<function_wrapper> local_queue_type;
    static thread_local std::unique_ptr<local_queue_type> local_work_queue;
    std::vector<std::thread> threads;`

    thread_pool()
    {
        unsigned const thread_count=std::thread::hardware_concurrency();
        for(unsigned i=0;i<thread_count;++i)
        {
            threads.push_back(
            std::thread(&thread_pool::worker_thread,this,i));
        }
    }

    void worker_thread()
    {
        local_work_queue.reset(new local_queue_type);  //just init in the sub thread
        while(1)
        {
            function_wrapper task;
            if(local_work_queue && !local_work_queue->empty())
            {
                task=std::move(local_work_queue->front());
                local_work_queue->pop();
                task();
            }
            else
            {
                std::this_thread::yield();
            }
        }
    }

    template<typename FunctionType>
    std::future<typename std::result_of<FunctionType()>::type>submit(FunctionType f)
    {
        typedef typename std::result_of<FunctionType()>::type result_type;
        std::packaged_task<result_type()> task(f);
        std::future<result_type> res(task.get_future());
        if(local_work_queue) //function submit is in pool thread, and local_work_queue only init in sub thred, so in this ,local_work_queue will away nullptr, isn't it? so confuse how the code work.
        {
            local_work_queue->push(std::move(task));
        }
        return res;
    }
};

void func()
{
    std::cout<<"test"<<std::endl;
}
int main()
{
    thread_pool p;
    p.submit(func);
}

person swtybb    schedule 02.03.2016    source источник
comment
В чем именно заключается ваш вопрос?   -  person Jeya Suriya Muthumari    schedule 02.03.2016
comment
вопрос в том, что local_work_queue в submit() всегда имеет значение nullptr, поэтому пул потоков не может получить доступ для отправки задачи в local_work_queue в подпотоке. и как это решить?   -  person swtybb    schedule 03.03.2016


Ответы (1)


но вы сделали его статичным. Значит, он будет доступен через класс? я предполагаю, что над правилом thread_local.

см. класс хранилища

5) Ключевое слово thread_local разрешено только для объектов, объявленных в области пространства имен, объектов, объявленных в области блока, и статических элементов данных. Это указывает на то, что объект имеет продолжительность хранения потока. Его можно комбинировать со статическим или внешним для указания внутренней или внешней связи (за исключением статических элементов данных, которые всегда имеют внешнюю связь) соответственно, но этот дополнительный статический элемент не влияет на продолжительность хранения.

его время жизни является локальным потоком, но я думаю, что связь распространяется на весь класс.

person idler1515    schedule 03.03.2016
comment
но я проверяю это, я не могу быть доступен в другом потоке. local_work_queue всегда имеет значение null в потоке пула, это не может быть шагом в этом: if(local_work_queue) { local_work_queue-›push(std::move(task)); } - person swtybb; 03.03.2016