为多线程将结构内存分配给参数

Allocate struct memory to args for multiple thread

本文关键字:分配 参数 内存 结构 多线程      更新时间:2023-10-16

以下代码运行多个线程,如果线程已使用相同的 id 启动,则会取消前一个线程。我使用此代码重新启动灯的计时器。

我的问题是如何重复使用线程参数两次?在重用之前和再次创建线程之前,我必须为结构"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;
}

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

 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 );

或类似的东西。

我在"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;
}