2014-02-24 34 views
0

黃釉,C,創建動態套接字線程池

我正在寫,旨在接受來自遠程單元的連接,從他們那裏得到的數據,並將它們上傳到數據庫C服務器端代碼,這些單位可以連接在同時也不要永久連接,因爲它們是電池供電的。

看過後我選擇了可​​以標記爲正在使用的動態pthread池,然後在單元完成時重新使用它們。如果同時有更多的套接字,池本身也會增加可用線程的數量。

基本上我已經完成了我認爲可以工作的代碼,但是之前沒有使用過動態內存,並且知道如果你不正確處理它會有多糟糕的事情會出錯,我正在尋找我的代碼檢查以確保我的工作將會發生,並且不會倒下或者在腳下進一步向我射擊。所以,如果這是一個好方法,或者如果有什麼問題,任何意見將不勝感激,謝謝:)

請注意下面的代碼部分僅適用於動態池。套接字,線程和mutexs我合作過:

#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; 
    } 
} 
+4

這個問題似乎是題外話,因爲工作的代碼進行審查。如果你想避免動態應該去http://codereview.stackexchange.com/ – alk

+0

內存分配/重新分配,那麼你可以將你的元素存儲在一個鏈表中而不是一個數組中,所以你只需爲正在使用的元素分配內存,然後釋放它們並將它們從列表中移除。 – SlappyTheFish

回答

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 */ 
} 

等等......

+0

謝謝,我最初計劃將腳本中的互斥量放在具有偵聽新套接字的線程的腳本中,因爲它實際上是它應該訪問的唯一地方,但將它放入API似乎是一個更好的解決方案。 – Skid