Find the answer to your Linux question:
Results 1 to 9 of 9
hi. im new here. im making a simple program of writing a sequence of images. for each image to write is the increment that the input 2Dimage is rotated. to ...
  1. #1
    Just Joined!
    Join Date
    Jan 2008
    Location
    Philippines
    Posts
    10

    pthread: inconsistency in thread counter

    hi. im new here.

    im making a simple program of writing a sequence of images. for each image to write is the increment that the input 2Dimage is rotated. to quicken up the pace of the running time, i chose to implement it with pthreads.

    here's my code:
    HTML Code:
    #define IMAGE_RANGE_CHECK
    #include "image.h"
    #include "jpegio.h"
    #include "color.h"
    #include "string.h"
    #include "pthread.h"
    
    struct spaceAttr       
    { int height;
      int width;
      double thetaR;
      RGBImage outputImage,inputImage;
      int degree;
    };
    
    void *threadRotateFunction(void *struct1){
    	int h = ((struct spaceAttr *) struct1) -> height;
    	int w = ((struct spaceAttr *) struct1) -> width;
            int deg = ((struct spaceAttr *) struct1) -> degree;
    	double theR = ((struct spaceAttr *) struct1) -> thetaR;
    	RGBImage outImg = ((struct spaceAttr *) struct1) -> outputImage;
    	RGBImage inImg = ((struct spaceAttr *) struct1) -> inputImage;
    	char imageFileName[100];
            char outputFileFormat[100];
            strcpy(outputFileFormat,"rotatetest/%04d.jpg");
            outImg.setAll(0);
    
    	int halfHeight = h/2;
       	int halfWidth = w/2;
    	int nx, ny, a,b;			
    
    		for (a = 0; a < w; a++){
    		for (b = 0; b < h; b++){
    
    		nx = (int)((a-halfWidth)*cos(theR) - (b-halfHeight)*sin(theR)+halfWidth);
    
    	    	ny = (int)((a-halfWidth)* sin(theR) + (b-halfHeight)*cos(theR)+halfHeight);
    
    		if(nx < w && nx >= 0 && ny < h && ny >=0){
    			outImg(nx,ny) = inImg(a,b);}
    		}//foy b
    		}//for a
    
    		sprintf( imageFileName, outputFileFormat, deg);
    		writeJpeg( outImg, imageFileName, 65 );	
    }//threadRotateFunction
    
    
    
    int main (int argc, char *argv[]) {
       
       spaceAttr struct1;
       int degreeEnd = 360;
       double pi = 3.14159;
    
       readJpeg( struct1.inputImage, "SP2/sample1/closing/0000.jpg" );
    
       struct1.height = struct1.inputImage.height();
       struct1.width = struct1.inputImage.width();
       struct1.outputImage.resize( struct1.width,struct1.height );
       struct1.outputImage = struct1.inputImage;
       
       int result;
       pthread_attr_t attr;
       result = pthread_attr_init(&attr);   
       pthread_t th[struct1.height];
    
       for(struct1.degree = 0; struct1.degree <= degreeEnd; struct1.degree++){
       struct1.thetaR = (struct1.degree*pi)/180;	   
    			
        		if (result) { perror("pthread_attr_init failed"); exit(1); }
        		result = pthread_attr_setstacksize(&attr, 1024*1024);
        		if (result) { perror("pthread_attr_setstacksize failed"); exit(1); }	
    
    	   	pthread_create(&th[struct1.degree],&attr,threadRotateFunction, (void *)&struct1);	   	
    		if (result) { perror("pthread_create failed"); exit(1); }
       }//for degree
    	
       for(struct1.degree = 0; struct1.degree <= degreeEnd; struct1.degree++){
    		result = pthread_join(th[struct1.degree], NULL);
        		if (result) { perror("pthread_join failed"); exit(1); }		    				
       }//for degree
    	return 0;
    
    }//MAIN
    i was able to write images but some are duplicated or more
    i.e
    ...
    Successfully written JPEG: rotatetest/0032.jpg
    Successfully written JPEG: rotatetest/0039.jpg
    Successfully written JPEG: rotatetest/0039.jpg
    Successfully written JPEG: rotatetest/0039.jpg
    Successfully written JPEG: rotatetest/0032.jpg
    Successfully written JPEG: rotatetest/0032.jpg
    ...

    thus, overwriting some files. the filenames should based on each increment of struct1.degree (increasing order) but some other increments were not produced.

    i was told that the struct1.degree here is not protected. and each degree, a thread is created. iv reviewed mutexes but i think it has nothing to do with that... (???please correct me if im wrong???)

    help,anyone? tnx.

  2. #2
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    i was told that the struct1.degree here is not protected
    You were told correctly. Each thread, of course, has a pointer to the same struct1. There is no guarantee that a newly started thread will actually start running before your main thread goes back and increments struct1.degree.
    --
    Bill

    Old age and treachery will overcome youth and skill.

  3. #3
    Just Joined!
    Join Date
    Jan 2008
    Location
    Philippines
    Posts
    10
    hi. thank you. now, im enlightened. i now use an array of structures. one structure for each thread. and i was able to write the images in sequence.

    btw,iv corrected the size of array of threads. iv changed it from:

    >pthread_t th[struct1.height]
    to
    >pthread_t th[degreeEnd+1]

    the same with the size of array of structures

    >spaceAttr struct1[degreeEnd+1]

    because the range of degree of rotation will be [0,360]

    however, i didnt get to print all the frames.after a number of them, i get a segmentation fault. i think iv been blinded to see what's wrong here. can you help me see it?

  4. #4
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    i get a segmentation fault. i think iv been blinded to see what's wrong here. can you help me see it?
    I seriously doubt it. But post the new version of your code and let's take a look.
    --
    Bill

    Old age and treachery will overcome youth and skill.

  5. #5
    Just Joined!
    Join Date
    Jan 2008
    Location
    Philippines
    Posts
    10
    here's my modified code:

    HTML Code:
    #include "image.h"
    #include "jpegio.h"
    #include "color.h"
    #include "string.h"
    #include "pthread.h"
    #include "malloc.h"
    
    struct spaceAttr       
    { int height;
      int width;
      double thetaR;
      RGBImage outputImage,inputImage;
      int degree;
    }; 
    
    void *threadRotateFunction(void *structArg){
    	struct spaceAttr *structData;
    	structData = (struct spaceAttr *) structArg;
    
    	int h = structData -> height;
    	int w = structData -> width;
    	int deg = structData -> degree;
    	double theR = structData -> thetaR;
    	RGBImage outImg = structData -> outputImage;
    	RGBImage inImg = structData -> inputImage;
    	
    	char imageFileName[100];
            char outputFileFormat[100];
            strcpy(outputFileFormat,"rotatetest/%04d.jpg");
            outImg.setAll(0);
    
    	int halfHeight = h/2;
       	int halfWidth = w/2;
    	int nx, ny, x,y;			
    
    		for (x = 0; x < w; x++){
    		for (y = 0; y < h; y++){
    		nx = (int)((x-halfWidth)*cos(theR) - (y-halfHeight)*sin(theR)+halfWidth);
    	    	ny = (int)((x-halfWidth)* sin(theR) + (y-halfHeight)*cos(theR)+halfHeight);
    		if(nx < w && nx >= 0 && ny < h && ny >=0){
    			outImg(nx,ny) = inImg(x,y);}
    		}//foy b
    		}//for a
    
    		sprintf( imageFileName, outputFileFormat, deg);
    		writeJpeg( outImg, imageFileName, 65 );	
    	//return 0;
    }//threadRotateFunction
    
    
    int main (int argc, char *argv[]) {
    
       int degreeEnd = 360;
       double pi = 3.14159;
    
       spaceAttr struct1[degreeEnd+1];   
       
       int result;
       pthread_attr_t attr;
       result = pthread_attr_init(&attr);   
    
       pthread_t th[degreeEnd+1];
    
       RGBImage iImage;
       readJpeg( iImage, "SP2/sample1/closing/0000.jpg" );
    
       for(int i = 0; i < degreeEnd+1; i++){
    	
    	struct1[i].inputImage = iImage;
       	struct1[i].height = struct1[i].inputImage.height();
    	struct1[i].width = struct1[i].inputImage.width();
    
            struct1[i].outputImage.resize( struct1[i].width,struct1[i].height );
            struct1[i].outputImage = struct1[i].inputImage;
    
            struct1[i].degree = i;
            struct1[i].thetaR = (struct1[i].degree*pi)/180;	   
    			
        		if (result) { perror("pthread_attr_init failed"); exit(1); }
        		result = pthread_attr_setstacksize(&attr, 1024*1024);
        		if (result) { perror("pthread_attr_setstacksize failed"); exit(1); }	
    	   	pthread_create(&th[i],&attr,threadRotateFunction, (void *)&struct1[i]);	   	
    		if (result) { perror("pthread_create failed"); exit(1); }
    		
       }//for degree
    	
       for(int i = 0; i < degreeEnd+1; i++){
    		result = pthread_join(th[i], NULL);
        		if (result) { perror("pthread_join failed"); exit(1); }		    				
       }//for degree
    	return 0;
    }//MAIN

  6. #6
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    I don't see the problem immediately. Debugging pthreads situations can be frustrating. Do you know whether you blow up in the main thread (the one that you don't create explicitly), or each thread you create, or just some of them, or what?
    --
    Bill

    Old age and treachery will overcome youth and skill.

  7. #7
    Just Joined!
    Join Date
    Jan 2008
    Location
    Philippines
    Posts
    10
    i think i have a problem in allocation of resources that's why im getting a segfault. but i can't see it here, the array sizes have been corrected... i was able to create some threads but then, i hit segfault.

    haay... this is getting to be frustrating...

  8. #8
    Linux Engineer wje_lf's Avatar
    Join Date
    Sep 2007
    Location
    Mariposa
    Posts
    1,192
    One of the frustrating (let's see how many times we can use that word in this linuxforums thread [not to be confused with a POSIX thread]) things about pthreads is that a segmentation fault can occur in one thread, but the real cause of that segmentation fault can have occurred in another thread which corrupted the heap, perhaps minutes earlier.

    There are two lessons to learn from this.
    1. Don't use POSIX threads unless you absolutely have to. Unless speed considerations demand pthreads, redesign your program so it uses separate processes instead, or even does everything in one process.
    2. When you absolutely have to use pthreads, keep the program as simple as absolutely possible.


    I look at your code and I don't see one of the subsidiary threads use any data from another subsidiary thread, and I don't see your main thread use any of the results from any of the subsidiary threads. So why not just use fork() instead of pthreads? At least this will ensure that the same process will blow up as the one the misbehavior occurs in, which is a huge plus when debugging. Further, if you use fork(), struct1 doesn't have to be an array. Depending on how type RGBImage is laid out, you could have memory leaks if you use fork(), but they won't consume as much memory as having an array of 361 of these suckers.

    And speaking of memory allocation, do you check the result of each and every malloc() in your program? I don't see any malloc() in the code you presented, but how about in functions readJpeg() and writeJpeg()?

    And speaking of function writeJpeg(), you call it inside each of your threads. Does it call any functions which are not thread safe?

    Just a few thoughts to bother you with.

    My 400th post! w00t!
    --
    Bill

    Old age and treachery will overcome youth and skill.

  9. #9
    Just Joined!
    Join Date
    Jan 2008
    Location
    Philippines
    Posts
    10
    hay... maybe il go have a look and try at what you uv suggested.

    thank you so much though,
    uv been a big help.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...