Создание потоков, которые копируют переданные им аргументы - PullRequest
0 голосов
/ 17 августа 2010

В настоящее время я использую boost :: thread, потому что он очень удобно позволяет передавать потоку произвольное количество аргументов и копировать их по пути, поэтому мне не нужно беспокоиться об их удалении допоток запускается.Есть ли какая-либо другая библиотека, которая позволяет это, или способ имитировать это с помощью pthreads?Я бы хотел отучиться от буста, но я никогда не видел, чтобы какая-либо другая библиотека делала это.

Ответы [ 2 ]

1 голос
/ 17 августа 2010

Я не помню деталей Boost.Thread, но общая идея примерно такая:

class thread_function_base
{
public:
    virtual ~thread_function_base(void) {}
    virtual void run(void) = 0;
};

template <typename Func>
class thread_function_0 : public thread_function_base
{
public:
    thread_function_0(const Func& pFunc) :
    mFunc(pFunc)
    {}

    void run(void)
    {
        mFunc();
    }

private:
    Func mFunc;
};

template <typename Func, typename A0>
class thread_function_1 : public thread_function_base
{
public:
    thread_function_1(const Func& pFunc, const A0& pA0) :
    mFunc(pFunc),
    mA0(pA0)
    {}

    void run(void)
    {
        mFunc(mA0);
    }

private:
    Func mFunc;
    A0 mA0;
};

// and so on to some limit, either
// generated either by hand (yuck), by
// Boost.PP (phew), or by C++0x's
// variadic templates (yay, no limit either)

class thread
{
public:
    template <typename Func>
    thread(const Func& pFunc)
    {
        std::auto_ptr<thread_function_base>
            threadFunc(new thread_function_0<Func>(pFunc));

        create_thread(threadFunc);
    }

    template <typename Func, typename A0>
    thread(const Func& pFunc, const A0& pA0)
    {
        std::auto_ptr<thread_function_base>
            threadFunc(new thread_function_1<Func, A0>(pFunc, pA0));

        create_thread(threadFunc);
    }

    // again, needs to be generated somehow

private:
    // noncopyable
    thread(const thread&);
    thread& operator=(const thread&);

    // signature needs to match implementations expectations:
    static void thread_function(void* pUserData)
    {
        std::auto_ptr<thread_function_base>
            pFunc(static_cast<thread_function_base*>(pUserData));

        // (A)

        pFunc->run();
    }

    void create_thread(std::auto_ptr<thread_function_base>& pThreadFunc)
    {
        // again, implementation specific function:
        if (create_thread(&thread_function, pThreadFunc.get(), ...))
        {
            // failed, do something (and return), 
            // auto_ptr in constructor will free resources
            return;
        }    

        // thread was created, so it now owns that resource
        pThreadFunc.release();

        // (B)
    }
};

По сути, все, что нужно для вызова потока, копируется в некоторый динамически размещенный контейнер, указатель на этот динамический контейнер передается в функцию потока (тривиально), затем право собственности передается извне потока внутрь.

Вы можете сделать вещи более безопасными, упаковав не только thread_function_base в пользовательские данные, но также и (специфичный для реализации) дескриптор сигнала. Функция многопоточности будет блокироваться на (A), пока сигнал не будет поднят на (B), что указывает на то, что основной поток предоставил рабочему потоку полное владение ресурсами. (И оттуда это auto_ptr в конечном счете удалит это.)

И так далее, делая его более изощренным.

0 голосов
/ 17 августа 2010

Вам потребуется создать обертку вокруг pthread_create и передать хранилище, специфичное для потока, в pthread_create, который, например, содержит массив аргументов.Оболочка будет использовать форму, такую ​​как:

void *mythreadfunction(void *arg) {...}

pthread_create_wrapper(context ctx, ...) {
   Array *arr;
   pthread_t mythread;

   arr = new Array();

   // push arguments to array here
   blah blah ...
   // create thread and pass in argument list as thread data pointer.
   pthread_create(&mythread, NULL, mythreadfunction, (void *)arr);
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...