将结构内存分配给多个线程的args

时间:2015-03-10 14:53:13

标签: c++ multithreading struct args

以下代码运行多个线程,如果已经使用相同的ID启动了一个线程,它将取消之前的线程。我使用此代码重新启动灯的计时器。

我的问题是如何重复使用两次线程参数?我必须为struct" thread_data"分配内存。在重用之前和再次创建线程之前...这可以通过" thread_list"来完成。地图?也许我没有问正确的问题......但是,我正确回答

#include <iostream>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <map>

using namespace std;

pthread_mutex_t mutex_t;
map <string, pthread_t> thread_list;

struct thread_data
{
    char *num;
    char *type;
    int time;
};

static void cleanup(void *arg)
{
    pthread_mutex_lock(&mutex_t);
    cout << "Thread Cleaned" << endl;
    pthread_mutex_unlock(&mutex_t);
}

static void *thread(void *arg)
{
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);

    pthread_cleanup_push(&cleanup,NULL);

    thread_data* my_data = (thread_data*)(arg);
    int time = my_data->time;

    pthread_mutex_lock(&mutex_t);
    cout << "Thread start " << time << " " << my_data->num << endl << flush;
    pthread_mutex_unlock(&mutex_t);

    while(time)
    {
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
        pthread_testcancel();
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

        sched_yield();

        pthread_mutex_lock(&mutex_t);
        sleep(1);
        time--;
        pthread_mutex_unlock(&mutex_t);
    }

    pthread_mutex_lock(&mutex_t);
    cout << "Thread End " << endl;
    pthread_mutex_unlock(&mutex_t);

    pthread_cleanup_pop(0);

    return NULL;
}

void interrupt(string num, int time = 0, string type = "")
{
    cout << "Interruptable " << num << " " << time << " " << type << endl;

    if (thread_list.find(num)->second)
    {
        cout << "Cancel " << num << endl;

        if (pthread_cancel(thread_list[num]) == 0)
        {
            pthread_detach(thread_list[num]);
            while (pthread_kill(thread_list[num], 0)==0)
                sched_yield();
        }

        thread_list.erase(num);
    }

    thread_data td;
    td.time = time;
    td.num = "Ok";

    pthread_t thread_id;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    pthread_mutex_init(&mutex_t, NULL);
    pthread_create (&thread_id, &attr, &(thread), (void *)&td);
    thread_list.insert(pair <string, pthread_t> (num, thread_id));
}

int main()
{
    cout << "Start main" << endl;

    interrupt("6335", 5, "");
    sleep(1);
    interrupt("6335", 2, "");
    sleep(6);

    cout << "End main" << endl;
    return 0;
}

2 个答案:

答案 0 :(得分:0)

首先,您似乎正在尝试使用不为其分配内存的结构:

 thread_data td;
 td.time = time;
 td.num = "Ok";

这个代码片段在我看来是错误的,因为没有为变量td分配内存(堆栈除外),但它尝试分配一个值。因此,一旦创建了线程并且函数返回,则内存将被破坏。因此,您永远不应该使用局部变量将数据传递给另一个函数。通常,我希望为结构分配一些堆内存,例如:

 thread_data td;
 td = malloc( sizeof( thread_data ) );
 if( td == NULL ) ... [error handling] ...
 td.time = time;
 td.num = "Ok";

每次需要此结构时,都应为其分配内存。通常,(除了在专门的高性能应用程序中),您不应该尝试重新使用内存。

另外,请注意设计存在缺陷,因为无法释放为td结构分配的内存。你应该在更高级别创建td结构,例如,在main()中,然后当interrupt()函数返回时,你应该释放使用的内存。例如:

   main(){
     ....
     thread_data td;
     td = malloc( sizeof( thread_data ) );
     if( td == NULL ) ... [error handling] ...
     td.time = time;
     td.num = "Ok";
     interrupt( td );
     ...
     [do next interrupt]
     ...
     [after worker thread is complete]
     free( td );

或类似的东西。

答案 1 :(得分:0)

我在“thread_data”结构中设置了“td”。很长一段时间后它失败了......

struct thread_data
{
    int duration;
    string num;
    string type;
} td;

完成代码:

#include <iostream>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <unistd.h>
#include <map>

using namespace std;

pthread_mutex_t mutex_t;
map <string, pthread_t> thread_list;

struct thread_data
{
    int duration;
    string num;
    string type;
} td;

static void cleanup(void *arg)
{
    pthread_mutex_lock(&mutex_t);
    cout << "Thread Cleaned" << endl;
    pthread_mutex_unlock(&mutex_t);
}

static void *thread(void *arg)
{
    pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);
    pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED,NULL);

    pthread_cleanup_push(&cleanup,NULL);

    thread_data* my_data = (thread_data*)(arg);
    int duration = my_data->duration;

    pthread_mutex_lock(&mutex_t);
    cout << "Thread start " << duration << " " << my_data->num << endl;
    pthread_mutex_unlock(&mutex_t);

    while(duration)
    {
        pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL);
        pthread_testcancel();
        pthread_setcancelstate(PTHREAD_CANCEL_DISABLE,NULL);

        sched_yield();

        pthread_mutex_lock(&mutex_t);
        sleep(1);
        duration--;
        pthread_mutex_unlock(&mutex_t);
    }

    pthread_mutex_lock(&mutex_t);
    cout << "Thread End " << endl;
    pthread_mutex_unlock(&mutex_t);

    pthread_cleanup_pop(0);

    return NULL;
}

void timer_launch(int duration, string num, string type)
{
    cout << "Interruptable " << num << " " << duration << " " << type << endl;

    if (thread_list.find(num)->second)
    {
        cout << "Cancel " << num << endl;

        if (pthread_cancel(thread_list[num]) == 0)
        {
            pthread_detach(thread_list[num]);
            while (pthread_kill(thread_list[num], 0)==0)
                sched_yield();
        }
        thread_list.erase(num);
    }

    td.duration = duration;
    td.num = num;
    td.type = type;

    pthread_t thread_id;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

    pthread_mutex_init(&mutex_t, NULL);
    pthread_create (&thread_id, &attr, &(thread), (void *)&td);

    thread_list.insert(pair <string, pthread_t> (td.num, thread_id));
}

int main()
{
    cout << "Start main" << endl;

    timer_launch(5, "6335", "div");
    sleep(1);
    timer_launch(3, "6335", "div");
    sleep(6);

    cout << "End main" << endl;
    return 0;
}