Thread: Threads

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    5

    Unhappy Threads

    Hey guys...I am having trouble with this program here as I am rusty in C and just learning about threads. The .c file has all of the instructions commented out and where the lines of code are below the commented out numbers is where I filled in the work. I am specifically haveing a problem with the pthread_cancel(); I really do not know what to pass in there. Currently, I am passing the pointer to the thread, but how do I just pass the thread itself?

    Here is my code....TIA

    enzyme.c
    Code:
    #include "enzyme.h"
    
    int please_quit;
    int use_yield;
    int workperformed;
    char temp;
    
    // The code each enzyme executes.
    void *run_enzyme(void *data) {	
    	/* This function should :
    	1. cast the void* pointer to thread_info_t*
    	2. initialize the swapcount to zero
    	3. Set the cancel type to PTHREAD_CANCEL_ASYNCHRONOUS
    	4. If the first letter of the string is a C then call pthread_cancel on this thread.
    	5. Create a while loop that only exits when please_quit is nonzero
    	6. Within this loop: if the first character of the string has an ascii value greater than the second (s[0] >s[1]) then -
    		Set workperformed=1, increment swapcount for this thread, then swap the two characters around
    		If "use_yield" is nonzero then call pthread_yield at the end of the loop.
    	7. Return a pointer to the updated structure.
    	*/
    	
    	//1	
    	thread_info_t *thread = (thread_info_t*)data;
    	//2	
    	thread->swapcount = 0;
    	//3
    	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
    	//4
    	if(strncmp(thread->string, "C", 1) == 0){ pthread_cancel(thread);}
    	//5
    	while(please_quit != 0){
    		//6
    		if((int)(thread->string[0]) > (int)(thread->string[1])){
    			workperformed = 1;
    			thread->swapcount++;
    			temp = thread->string[1];
    			thread->string[1] = thread->string[0];
    			thread->string[0] = temp;
    		}
    		if(use_yield != 0){ pthread_yield();}	
    	}
    	
    	//7
    	//while(0) {
    	//	sched_yield();
    	//};
    	return (void *)thread;
    	
    }
    enzyme.h
    Code:
    #include <pthread.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    #define MAX 100
    
    typedef struct {
            char *string; // keep testing and swap contents if necessary so that string[0] < string[1]
            int swapcount; // used later
    } thread_info_t;
    
    extern int please_quit;
    
    extern int workperformed;
    
    void *run_enzyme(void *data);
    int make_enzyme_threads(pthread_t * enzymes_tid, char *string, void *(*fp)(void *));
    int join_on_enzymes(pthread_t *threads_tid, int n);
    
    int smp2_main(int, char**);
    Last edited by Lynx; 03-17-2009 at 07:00 AM.

  2. #2
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I haven't worked with pthreads before, but pthread_cancel probably expects a pthread_t* - not a thread_info_t*. The logical solution, of course, would be to store the former into the latter...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  3. #3
    Registered User
    Join Date
    Mar 2009
    Posts
    5
    I tried that, but it does not find the struct after I implement that line of code

  4. #4
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    I don't follow you. What I meant was to define your struct like this:

    Code:
    typedef struct {
            pthread_t * thread;
            char *string; // keep testing and swap contents if necessary so that string[0] < string[1]
            int swapcount; // used later
    } thread_info_t;
    When you create your thread, just be sure to store your pthread_t* in the struct so that you can access it from within your callback function...
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  5. #5
    Registered User
    Join Date
    Mar 2009
    Posts
    5
    Oh..I am sorry. I misunderstood.

    I can't change anything in the enzyme.h because there are other files that are dependent on it. The only thing I can change is the .c function called enzymes. What I was thinking is:

    Code:
    pthread_t* thread = (thread_info_t*)data;
    that is where my struct is not found. I think that it needs to be casted this way and somehow told that it is a pthread_t, but I am not sure how to implement that...

  6. #6
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    Let's try this again. pthread_t* is a handle to your thread. When the thread is created, you pass it a pointer to some "userdata". In this case, that's a thread_info_t*. So casting it to a pthread_t* would be pointless. Now, I have never worked with pthreads, and don't know the API, but I would be willing to bet that there is a function that can obtain the pthread_t* of the calling thread (or at least an id, in which case there would probably be a function that can convert an identifier to a pthread_t*) so that you wouldn't need to store the handle in the first place. Locate those functions and you can then pass the result along to pthread_cancel. Something along the lines of:

    pthread_cancel( get_current_pthread_t( ) )
    - or -
    pthread_cancel( pthread_t_from_id( get_current_pthread_id( ) ) )

    Does that make sense?
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  7. #7
    Registered User
    Join Date
    Mar 2009
    Posts
    5
    Yes, thank you very much. I will give that a go when I get back home.

  8. #8
    Registered User
    Join Date
    Mar 2009
    Posts
    5
    rofl man....I think I got it.

    pthread_self() returns the calling thread's handle....so I just put that in the cancel function and it looks like it is working. No errors and no warnings.

    Thanks a bunch, Sebastiani. I really appreciate you clearing it up for me and setting me on the right track.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 10-17-2008, 11:28 AM
  2. Yet another n00b in pthreads ...
    By dimis in forum C++ Programming
    Replies: 14
    Last Post: 04-07-2008, 12:43 AM
  3. Classes and Threads
    By Halloko in forum Windows Programming
    Replies: 9
    Last Post: 10-23-2005, 05:27 AM
  4. problem with win32 threads
    By pdmarshall in forum C++ Programming
    Replies: 6
    Last Post: 07-29-2004, 02:39 PM
  5. Block and wake up certain threads
    By Spark in forum C Programming
    Replies: 9
    Last Post: 06-01-2002, 03:39 AM