I am trying to write a program which gets input files and prints included items into the screen by threads. However, last thread doesn’t give any output unexpectedly. I couldn’t figure out what the problem is. I am waiting for your help.
Each thread gets 3 parameters :inputFile1, inputFile2 and targetBuf(lets say it is sequence number.) Files are sorted, I just simply try to print their union in order. Only positive numbers are printed.
Command line : merge N outfile file1 file2 file3 …. fileN
N is the number of input files.
If I give 2 input files (means 1 thread), it works. If I give 4 files, then 1st thread give output, 2nd one does not. If I give 6 input files, then 1st and 2nd threads give output but 3rd doesn’t.
There are two structs in header file. I pasted them below.
//thread information
struct threadInfo{
pthread_t tid;
pthread_attr_t attr;
};
//Beginning thread input
struct beginThreadInput{
FILE **inputFile1, **inputFile2;
int targetBuf;
};
typedef struct threadInfo THREADINFO;
typedef struct beginThreadInput BEGINT_INPUT;
Main File Code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h> //for O_ constants
#include <sys/stat.h>
#include <pthread.h> /* thread library */
#include "merge.h"
int main(int argc, char** argv){
int i, k, N;
/***FILE INITIALIZATION***/
FILE *output;
N = atoi(argv[1]);
output = fopen(argv[2], "w");
FILE **inputFileList = ((FILE**)malloc (N * sizeof(FILE*)));
printf("int N is %d\n", N);
for(i = 0; i<N; i++){
inputFileList[i] = fopen(argv[i + 3], "r");
}
//START THREADS
BEGINT_INPUT **threadInputList = ((BEGINT_INPUT**) malloc ( (N/2)* sizeof(BEGINT_INPUT*)));
THREADINFO **threadInfoList = ((THREADINFO**) malloc ( (N/2) * sizeof(THREADINFO*)));
for(i = 0; i< N/2 ; i++){
threadInputList[i] = (BEGINT_INPUT *) malloc (sizeof(BEGINT_INPUT));
threadInfoList[i] = (THREADINFO *) malloc (sizeof(THREADINFO));
}
pthread_t tid;
pthread_attr_t attr;
for(i = 0, k = 0; i < (N/2); i++){
threadInputList[i]->inputFile1 = &(inputFileList[k]);
threadInputList[i]->inputFile2 = &(inputFileList[++k]);
threadInputList[i]->targetBuf = i;
pthread_attr_init(&(threadInfoList[i]->attr));
pthread_create(&(threadInfoList[i]->tid), &(threadInfoList[i]->attr), runBeginningThreads, (void*)threadInputList[i]);
}
pthread_join((threadInfoList[[(N/2)-1]]->tid), NULL);
for(i = 0; i<N; i++){
fclose(inputFileList[i]);
}
}
void *runBeginningThreads(void *input){
BEGINT_INPUT *myInput = (BEGINT_INPUT *)input;
int first = -1, second = -1, iseof;
printf("Thread number %d\n", myInput->targetBuf);
while((second > -2) && (first > -2)){
//read integer values from files
if(first == -1){
iseof = fscanf(*(myInput->inputFile1), "%d", &first);
if(iseof == EOF){
first = -2; //means end of file
}
else if(first < 0)
first = -1; //means waiting for an integer
}
if(second == -1){
iseof = fscanf(*(myInput->inputFile2), "%d", &second);
if(iseof == EOF){
second = -2;
}
else if(second < 0)
second = -1;
}
//print smaller one
if((first != -1) && (second != -1)){
if(((first < second) || (second == -2)) && (first != -2)){
printf("%d\n", first);
first = -1;
}
else if(second != -2){
printf("%d\n", second);
second = -1;
}
}
}
}
I solve my question in the following way. As it is seen above, I open the files in main function, then pass them into corresponding threads. I have changed this way and passed the names of the files into threads and open related files in them.
Additionally, while passing files, I was making mistakes, its code is below
This lines are run in a loop. This causes an input sequence like the following ([0,1], [1,2], [2,3], [3,4] …) becuase I increment k only one time.However, each thread takes two of inputFiles. So the correct code is this:
I want to point out an issue. I fixed this code for file names, not FILE pointer variables as it is posted there. But to make it clear, I fixed the bug on a code posted there. Thanks for your help, everybody