Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C、 创建动态套接字线程池_C_Multithreading_Dynamic Memory Allocation - Fatal编程技术网

C、 创建动态套接字线程池

C、 创建动态套接字线程池,c,multithreading,dynamic-memory-allocation,C,Multithreading,Dynamic Memory Allocation,耶罗 我正在编写C服务器端代码,该代码旨在接受来自远程设备的连接,从远程设备接收数据并将其发布到数据库中,这些设备可以同时连接,但也不能永久连接,因为它们是电池供电的 在看过之后,我选择使用一个动态pthread池,它可以被标记为正在使用,然后在单元使用完它们后重新使用。如果同时有更多的套接字,那么池本身也会增加可用线程的数量 基本上,我已经完成了我认为可以工作的代码,但是之前没有使用过动态内存,并且知道如果处理不正确,事情会变得多么糟糕,我希望检查我的代码,以确保我的代码可以工作,而不只是摔倒

耶罗

我正在编写C服务器端代码,该代码旨在接受来自远程设备的连接,从远程设备接收数据并将其发布到数据库中,这些设备可以同时连接,但也不能永久连接,因为它们是电池供电的

在看过之后,我选择使用一个动态pthread池,它可以被标记为正在使用,然后在单元使用完它们后重新使用。如果同时有更多的套接字,那么池本身也会增加可用线程的数量

基本上,我已经完成了我认为可以工作的代码,但是之前没有使用过动态内存,并且知道如果处理不正确,事情会变得多么糟糕,我希望检查我的代码,以确保我的代码可以工作,而不只是摔倒或射中我的脚。因此,任何关于这是否是一个好方法或是否存在问题的建议都将不胜感激,谢谢:)

注意,下面的代码部分仅适用于动态池。我以前使用过的套接字、线程和互斥体:

#include <pthread.h>
#include <stdbool.h>
#include <stdlib.h>

#define DEFAULT_SIZE    8
#define SIZE_INCREMENTS 8

// Structure used to hold the dynamic array
typedef struct
{
    pthread_t worker;
    bool used;
} Element;

typedef struct
{
    Element *data;
    size_t size;
} DynamicPool;

// Global function prototypes
int initDynamicPool (DynamicPool *temp);
pthread_t getFreeElement (DynamicPool *temp);
int freeElement (DynamicPool *temp, pthread_t element);
int freePool (DynamicPool *temp);

// Local function prototypes
int resizePool (DynamicPool *temp);

// Create a new dynamic array
int initDynamicPool (DynamicPool *temp)
{
    if (temp->size == 0)
    {
        temp->size = DEFAULT_SIZE;
        temp->data = (Element*) malloc (temp->size * sizeof (Element));

        // Assigns defaults to new elements
        int t;
        for (t = 0; t < temp->size; t++)
        {
            //temp->data[t].worker = NULL;
            temp->data[t].used = false;
        }

        return temp->size;
    }
    else
    {
        return -1;
    }
}

// Get first free element
pthread_t getFreeElement (DynamicPool *temp)
{
    if (temp->size > 0)
    {
        // Search the array for any element that isn't used
        int t;
        for (t = 0; t < temp->size; t++)
        {
            if (!temp->data[t].used)
            {
                temp->data[t].used = true;
                return temp->data[t].worker;
            }
        }

        // If no worker found, increase the size and send the first new element
        resizePool(temp);
        temp->data[t].used = true;
        return temp->data[t].worker;
    }
    else
    {
        return -1;
    }
}

// Resize array
int resizePool (DynamicPool *temp)
{
    if (temp->size > 0)
    {
        int old_size = temp->size;
        temp->size += SIZE_INCREMENTS;
        temp->data = (Element*) realloc (temp->data, temp->size * sizeof (Element));

        // Assigns defaults to new elements
        int t;
        for (t = old_size; t < temp->size; t++)
        {
            //temp->data[t].worker = NULL;
            temp->data[t].used = false;
        }

        return temp->size;
    }
    else
    {
        return -1;
    }
}

// Free element
int freeElement (DynamicPool *temp, pthread_t element)
{
    if (temp->size > 0)
    {
        // Search the pool for the selected element
        int t;
        for (t = 0; t < temp->size; t++)
        {
            // If we find the element, null the thread and make it as unused
            if (temp->data[t].worker == element)
            {
                //temp->data[t].worker = NULL;
                temp->data[t].used = false;
                break;
            }
        }

        // If we can't find the element error out
        if (t >= temp->size)
        {
            return -2;
        }
        else
        {
            return t;
        }
    }
    else
    {
        return -1;
    }
}

// Free the pool
int freePool (DynamicPool *temp)
{
    if (temp->size > 0)
    {
        // Free the memory then reset all values incase re-initializion is intended
        free (temp->data);
        temp->size = 0;
        temp->data = NULL;

        return temp->size;
    }
    else
    {
        return -1;
    }
}
#包括
#包括
#包括
#定义默认的_大小8
#定义大小_增量8
//用于保存动态数组的结构
类型定义结构
{
pthread_t worker;
布尔使用;
}元素;
类型定义结构
{
元素*数据;
大小;
}动态工具;
//全局函数原型
int initDynamicPool(DynamicPool*temp);
pthread_t getfreelement(DynamicPool*temp);
int freelement(DynamicPool*temp、pthread\u t元素);
int freePool(DynamicPool*temp);
//局部函数原型
int resizePool(DynamicPool*temp);
//创建一个新的动态数组
int initDynamicPool(DynamicPool*temp)
{
如果(温度->尺寸==0)
{
临时->大小=默认大小;
temp->data=(元素*)malloc(temp->size*sizeof(元素));
//将默认值指定给新元素
int t;
对于(t=0;tsize;t++)
{
//temp->data[t]。worker=NULL;
临时->数据[t]。已使用=假;
}
返回温度->大小;
}
其他的
{
返回-1;
}
}
//获取第一个自由元素
pthread\u t getfreelement(DynamicPool*temp)
{
如果(温度->尺寸>0)
{
//在数组中搜索任何未使用的元素
int t;
对于(t=0;tsize;t++)
{
如果(!temp->data[t]。已使用)
{
临时->数据[t]。已使用=真;
返回临时->数据[t]。工人;
}
}
//如果未找到工作进程,请增大大小并发送第一个新元素
调整池(临时);
临时->数据[t]。已使用=真;
返回临时->数据[t]。工人;
}
其他的
{
返回-1;
}
}
//调整数组大小
int resizePool(DynamicPool*temp)
{
如果(温度->尺寸>0)
{
int old_size=temp->size;
温度->尺寸+=尺寸增量;
temp->data=(元素*)realloc(temp->data,temp->size*sizeof(元素));
//将默认值指定给新元素
int t;
对于(t=old_size;tsize;t++)
{
//temp->data[t]。worker=NULL;
临时->数据[t]。已使用=假;
}
返回温度->大小;
}
其他的
{
返回-1;
}
}
//自由元素
int freelement(DynamicPool*temp、pthread\u t元素)
{
如果(温度->尺寸>0)
{
//在池中搜索所选元素
int t;
对于(t=0;tsize;t++)
{
//如果我们找到了元素,则将线程设为null,并将其设为未使用
如果(临时->数据[t]。工作者==元素)
{
//temp->data[t]。worker=NULL;
临时->数据[t]。已使用=假;
打破
}
}
//如果我们找不到元素错误
如果(t>=温度->尺寸)
{
返回-2;
}
其他的
{
返回t;
}
}
其他的
{
返回-1;
}
}
//腾出游泳池
int freePool(DynamicPool*temp)
{
如果(温度->尺寸>0)
{
//释放内存,然后在需要重新初始化时重置所有值
免费(临时->数据);
温度->尺寸=0;
temp->data=NULL;
返回温度->大小;
}
其他的
{
返回-1;
}
}

您的代码正常,但必须确保对
DynamicPool
的所有调用都是同步的。我假设您从不同的线程调用该API。此外,可以由多个线程修改的计数器和其他字段必须是volatile

typedef struct
{
    volatile Element *data;/* Force compiler always load/store the value */
    volatile size_t size;  /* Force compiler always load/store the value */
    pthread_mutex_t mutex; /* Protect size  and data */
} DynamicPool;

int initDynamicPool (DynamicPool *temp)
{
   ...
   pthread_mutex_init(&temp->mutex);
   ...
}

pthread_t getFreeElement (DynamicPool *temp)
{
    pthread_mutex_lock(&temp->mutex);  /* */
    ...
    pthread_mutex_unlock(&temp->mutex); /* always unlock before return */
    return res;  /* return value must be computed before unlocking */
}

等等…

谢谢,我本来打算把互斥锁放在脚本中,脚本中有线程正在监听新的套接字,因为它是唯一应该访问的地方,但是把它放在API中似乎是一个更简洁的解决方案。这个问题似乎离题了,因为要检查的工作代码应该转到。如果你想避免动态内存分配/重新分配,那么你可以将元素存储在链表而不是数组中,因此,您只需为正在使用的元素分配内存,然后释放它们,并将它们从列表中删除。