私はスレッドプールを実装しようとしています.ftwのOnOpen関数内に存在する一時的なインスタンスよりも永続的に保存されるように、作業するはずのファイルパスを取得するのにかなりの問題があります. . 処理されるすべてのファイルパスに対して malloc を実行することは許可されていません。
これは現在、OnOpen がスレッドに一時データを渡さないようにしようとしているものであり、memcpy でクラッシュする理由について混乱しています。
memcpy を実行する char* の余分な配列を作成せずに、編集中の一時変数からデータを保護する方法を知りたいです。
typedef struct Task{
void (*taskFunc)(char*);
char* arg;
} Task;
void HashFunc(char* arg)
{
pthread_mutex_lock(&lock);
printf("%s\n", arg);
thingsDone++;
pthread_mutex_unlock(&lock);
}
static int OnOpen(const char* path, const struct stat* sb, int flags)//will send folder paths too
{
if(strstr(path, ".exe") || strstr(path, ".cfg")) return 0;
Task t = {
.taskFunc = &HashFunc,
.arg = path
};
memcpy(t.arg, path, strlen(path));
while(taskCount == MAX_OPEN_FILE_HANDLES-1); //busy wait
submitTask(t);
return 0;
}
編集:素晴らしいフィードバックですが、それは私が必要としているものではありません.
以下に、私が問題を抱えているコード、つまりスレッドプールとタスク構造体の使用方法に関連するものをいくつか追加します。それについて行くことができます:
void executeTask(Task* task) {task->taskFunc(task->arg);}
void* threadFunc(void* arg)
{
Task task;
while (!(doneSending==1 && thingsDone == thingsToDo))
{
pthread_mutex_lock(&lock);
while (taskCount==0 && doneSending==0) {pthread_cond_wait(&condQueue, &lock);}
task = taskQueue[0];
for (int i = 0; i < taskCount-1; i++) {taskQueue[i] = taskQueue[i+1];}
taskCount > 0 ? --taskCount : 0;
pthread_mutex_unlock(&lock);
if (doneSending==0 || thingsDone<thingsToDo) executeTask(&task);
printf("%d, %d, %d, %d\n", taskCount, thingsDone, thingsToDo, doneSending);
}
}
void submitTask(Task task)
{
pthread_mutex_lock(&lock);
taskQueue[taskCount++] = task;
++thingsToDo;
pthread_mutex_unlock(&lock);
pthread_cond_signal(&condQueue);
}
私のスレッドプールは 8 つのスレッドで構成されており、これは私の taskQueue のサイズでもあります。
以前は持って.arg = strcpy(temp, path)
いましたが、temp は一時的であるため、hashFunc に不正なデータが出力されました。
各スレッドは、互いに干渉する危険を冒さないように、動作する Task 構造体の独自のコピーを持つことになっています。
最終編集:私はそれを機能させました。これがどのように見える必要があるかです:
volatile int taskIdx = 0, pathIdx = 0;
Task taskArray[MAX_OPEN_FILE_HANDLES];
char* pathQueue[MAX_OPEN_FILE_HANDLES];
void* threadFunc(void* args)
{
Task task;
while (!(doneSending==1 && taskIdx == pathIdx))
{
if (doneSending && taskIdx==pathIdx) break;
pthread_mutex_lock(&lock);
pthread_cond_wait(&condArray, &lock);
if (doneSending && taskIdx==pathIdx)
{
pthread_mutex_unlock(&lock);
break;
}
task = taskArray[taskIdx];
taskIdx = (taskIdx+1)%MAX_OPEN_FILE_HANDLES;
pthread_mutex_unlock(&lock);
executeTask(&task);
}
}
void submitTask(Task t)
{
pthread_mutex_lock(&lock);
taskArray[pathIdx] = t;
pathIdx = (pathIdx+1)%MAX_OPEN_FILE_HANDLES;
pthread_cond_signal(&condArray);
pthread_mutex_unlock(&lock);
}
static int OnOpen(const char* path, const struct stat* sb, int flags)
{
if(flags != FTW_F || strstr(path, ".cfg") || strstr(path, ".exe") || strstr(path, ".vscode") || strstr(path, "anticheat") || strstr(path, "Makefile")) return 0;
if (thingsToDo-thingsDone == MAX_OPEN_FILE_HANDLES) HashFunc((char*)path, thingsToDo++);
else
{
Task t = {
.taskFunc = &HashFunc,
.filePath = strcpy(pathQueue[pathIdx], path)
};
submitTask(t);
}
return 0;
}
int main()
{
pthread_mutex_init(&lock, NULL);
pthread_cond_init(&condArray, NULL);
for (int i=0; i<MAX_OPEN_FILE_HANDLES; i++)
{
if(pthread_create(&pool[i], NULL, &threadFunc, NULL) != 0) perror("pth_create");
pathQueue[i] = calloc(MAX_PATH_LENGTH, sizeof(char));
}