-
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**);
-
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...
-
I tried that, but it does not find the struct after I implement that line of code
-
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...
-
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...
-
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?
-
Yes, thank you very much. I will give that a go when I get back home.
-
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.