Threading in C with CreateThread() - c

I am very much a novice to C, and I am trying to make a program to run MIDI sequences, and basically, I have two functions, both running a different MIDI pattern, and I need them to run in parallel. Due to the nature of the functions (one running a sequence and the other playing random notes), I am almost 100% sure that I can't have then running in the same function.
I've been scouring the internet for some clue on how to do this with pthreads (which apparently don't work on Windows?) and CreateThread(), but I can't seem to get it to work. I am currently trying to use CreateThread() and trying to bring in the integers required for the random midi sequence and I am getting an error concerning 'LPTHREAD_START_ROUTINE' which reads: 'expected 'LPTHREAD_START_ROUTINE' but argument is of type 'DWORD (*)(int, int, int)'.
A sort of pseudocode of what I'm working on is here:
DWORD WINAPI solo_thread(int key, int tempo, int scale)
{
///// this contains the random midi notes
}
int backing(int key, int tempo, int backing)
{
HANDLE thread = CreateThread(NULL, 0, solo_thread, NULL, 0, NULL);
if (thread) {
////// this contains the midi sequence
}
Hopefully I have explained my problem well... But I am well aware that the most likely case is that I am going about this CreateThread() thing in all the wrong ways.
Thanks!

The signature of the thread entry function is, from the ThreadProc() reference page:
DWORD WINAPI ThreadProc(
_In_ LPVOID lpParameter
);
and solo_thread() does not have that signature.
If it is necessary to supply multiple arguments to the function create a struct containing multiple members representing the desired arguments. The argument to the thread must outlive the thread otherwise the thread will be accessing a dangling pointer. The common solution is to dynamically allocate the argument and have the thread free() it when it no longer requires it.
Example:
struct Thread_data
{
int key;
int tempo;
int scale;
};
DWORD WINAPI solo_thread(void* arg)
{
struct Thread_data* data = arg;
/* Use 'data'. */
free(data);
return 0;
}
int backing(int key, int tempo, int backing)
{
struct Thread_data* data = malloc(*data);
if (data)
{
data->key = key;
data->tempo = tempo;
data->scale = backing;
HANDLE thread = CreateThread(NULL, 0, solo_thread, &data, 0, NULL);
}

Related

How can I create a function object in C

I would like to create a wrapper for c functions, so that I can convert a function call of the form ret = function(arg1,arg2,arg3); into the form /*void*/ function_wrapper(/*void*/);. That is similar to function objects in C++ and boost bind.
Is this possible? how can I do it?
Update:
To explain in more details what I am looking for:
We start with this function:
int f(int i){
//do stuff
return somevalue;
}
Obvioulsy, it is called like this:
// do stuff
int x = 0;
ret = f(0);
// do more stuff.
I would like to do some magic that will wrap the function into void function(void)
struct function_object fo;
fo.function_pointer = &f;
fo.add_arg(x, int);
fo.set_ret_pointer(&ret);
fo.call();
Note: I saw that there was a vote for closing this question and marking it as unclear. Please do not do that. I have a legitimate need to get this question answered. If you need explanation, ask and I will be glad to elaborate.
I came up with a better code that might allow you to do what you want. First I'll explain how it works, show the code and explain why I still don't think it's a good idea to use it (though the code might open doors for improvements that addresses those issues).
Functionality:
Before you start using the "function objects", you have to call an initialization function (FUNCTIONOBJ_initialize();), which will initialize the mutexes on every data structure used in the library.
After initializing, every time you want to call one of those "function objects", without using the parameters, you will have to set it up first. This is done by creating a FUNCTIONOBJ_handler_t pointer and calling get_function_handler(). This will search for a free FUNCTIONOBJ_handler data structure that can be used at the moment.
If none is found (all FUNCTIONOBJ_handler data structures are busy, being used by some function call) NULL is returned.
If get_function_handler() does find a FUNCTIONOBJ_handler data structure it will try to lock the FUNCTIONOBJ_id_holder data structure, that holds the ID of the FUNCTIONOBJ_handler of the function about to be called.
If FUNCTIONOBJ_id_holder is locked already, get_function_handler() will hang until it's unlocked by the thread using it.
Once FUNCTIONOBJ_id_holder is locked, the ID of the grabbed FUNCTIONOBJ_handler is wrote on it and the FUNCTIONOBJ_handler pointer is returned by get_function_handler.
With the pointer in hand, the user can set the pointer to the arguments and the return variable with set_args_pointer and set_return_pointer, which both take a void * as arguments.
Finally, you can call the function you want. It has to:
1 - Grab the FUNCTIONOBJ_handler ID from the FUNCTIONOBJ_id_holder data structure and use it to get a pointer to the FUNCTIONOBJ_handler itself.
2 - Use the FUNCTIONOBJ_handler to access the arguments.
3 - Return by using one of the return function (on the example we have ret_int, which will return an integer and unlock the FUNCTIONOBJ_handler)
Below is a simplified mind map describing a bit of what is going on:
Finally, the code:
funcobj.h:
#include <stdio.h>
#include <pthread.h>
#define MAX_SIMULTANEOUS_CALLS 1024
typedef struct {
//Current ID about to be called
int current_id;
//Mutex
pthread_mutex_t id_holder_mutex;
} FUNCTIONOBJ_id_holder_t;
typedef struct {
//Attributes
void *arguments;
void *return_pointer;
//Mutex
pthread_mutex_t handler_mutex;
} FUNCTIONOBJ_handler_t;
FUNCTIONOBJ_handler_t FUNCTIONOBJ_handler[MAX_SIMULTANEOUS_CALLS];
FUNCTIONOBJ_id_holder_t FUNCTIONOBJ_id_holder;
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer);
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value);
void FUNCTIONOBJ_initialize(void);
FUNCTIONOBJ_handler_t *get_function_handler(void);
funcobj.c:
#include "funcobj.h"
void set_return_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->return_pointer = pointer;
}
void set_args_pointer(FUNCTIONOBJ_handler_t *this, void *pointer){
this->arguments = pointer;
}
void ret_int(FUNCTIONOBJ_handler_t *this, int return_value){
if(this->return_pointer){
*((int *) (this->return_pointer)) = return_value;
}
pthread_mutex_unlock(&(this->handler_mutex));
}
void FUNCTIONOBJ_initialize(void){
for(int i = 0; i < MAX_SIMULTANEOUS_CALLS; ++i){
pthread_mutex_init(&FUNCTIONOBJ_handler[i].handler_mutex, NULL);
}
pthread_mutex_init(&FUNCTIONOBJ_id_holder.id_holder_mutex, NULL);
}
FUNCTIONOBJ_handler_t *get_function_handler(void){
int i = 0;
while((0 != pthread_mutex_trylock(&FUNCTIONOBJ_handler[i].handler_mutex)) && (i < MAX_SIMULTANEOUS_CALLS)){
++i;
}
if(i >= MAX_SIMULTANEOUS_CALLS){
return NULL;
}
//Sets the ID holder to hold this ID until the function is called
pthread_mutex_lock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
FUNCTIONOBJ_id_holder.current_id = i;
return &FUNCTIONOBJ_handler[i];
}
main.c:
#include "funcobj.h"
#include <string.h>
//Function:
void print(void){
//First the function must grab the handler that contains all its attributes:
//The FUNCTIONOBJ_id_holder is mutex locked, so we can just access its value and
//then free the lock:
FUNCTIONOBJ_handler_t *this = &FUNCTIONOBJ_handler[FUNCTIONOBJ_id_holder.current_id];
//We dont need the id_holder anymore, free it!
pthread_mutex_unlock(&FUNCTIONOBJ_id_holder.id_holder_mutex);
//Do whatever the function has to do
printf("%s\n", (char *) this->arguments);
//Return the value to the pointed variable using the function that returns an int
ret_int(this, 0);
}
void *thread_entry_point(void *data){
int id = (int) data;
char string[100];
snprintf(string, 100, "Thread %u", id);
int return_val;
FUNCTIONOBJ_handler_t *this;
for(int i = 0; i < 200; ++i){
do {
this = get_function_handler();
} while(NULL == this);
set_args_pointer(this, string);
set_return_pointer(this, &return_val);
print();
}
return NULL;
}
int main(int argc, char **argv){
//Initialize global data strucutres (set up mutexes)
FUNCTIONOBJ_initialize();
//testing with 20 threads
pthread_t thread_id[20];
for(int i = 0; i < 20; ++i){
pthread_create(&thread_id[i], NULL, &thread_entry_point, (void *) i);
}
for(int i = 0; i < 20; ++i){
pthread_join(thread_id[i], NULL);
}
return 0;
}
To compile: gcc -o program main.c funcobj.c -lpthread
Reasons to avoid it:
By using this, you are limiting the number of "function objects" that can be running simultaneously. That's because we need to use global data structures to hold the information required by the functions (arguments and return pointer).
You will be seriously slowing down the program when using multiple threads if those use "function objects" frequently: Even though many functions can run at the same time, only a single function object can be set up at a time. So at least for that fraction of time it takes for the program to set up the function and actually call it, all other threads trying to run a function will be hanging waiting the the data structure to be unlocked.
You still have to write some non-intuitive code at the beginning and end of each function you want to work without arguments (grabbing the FUNCTIONOBJ_handler structure, unlocking the FUNCTIONOBJ_id_holder structure, accessing arguments through the pointer you grabbed and returning values with non-built-in functions). This increases the chances of bugs drastically if care is not taken, specially some nasty ones:
Increases the chances of deadlocks. If you forget to unlock one of the data structures in any point of your code, you might end up with a program that works fine at some moments, but randomly freeze completely at others (because all function calls without arguments will be hanging waiting for the lock to be freed). That is a risk that happens on multithreaded programs anyways, but by using this you are increasing the amount of code that requires locks unnecessarily (for style purposes).
Complicates the use of recursive functions: Every time you call the function object you'll have to go through the set up phrase (even when inside another function object). Also, if you call the recursive function enough times to fill all FUNCTIONOBJ_handler structures the program will deadlock.
Amongst other reasons I might not notice at the moment :p

Pthreads and shared memory in C

Can anyone tell me why my shared memory data structure (implemented using sys/shm.h) is not being read correctly by pthreads? This is an edited version of my question, with a reduced amount of code. Hopefully its easier to navigate.
Initially, the structure being referenced is created in shared memory space, so two different applications can read and write to it. The aim: to have one application update the shared structure, and the other read it using pthreads. So far everything things are working to an extent. Both applications can read and write to the shared memory, except the pthreads. they don't seem to pick up the modified shared structure?
An overview of the code is below. It is based on a basic runtime system, however, it is not overly complicated. The function executed within the pthreads is:
void* do_work(void *p)
The shared structure is:
typedef struct WL_CTRL_T
Currently all i am trying do is print out the elements of the array. Initially all elements are set to true. Halfway through the execution, using GDB to halt the process, i update the structure from outside, using the other application, by changing elements 0 and 1 to false, then continue to the process. At this i also print out the state of the array from each application via the sequential code, and the print out is correct. However, when the threads are set off, they print the original state of the array, all true...
The structure contains an array of structs, where the active bool field is read by the pthread
I have tried many ways to try and correct this problem, but no joy.
Any advice appreciated, thanks :-)
/*controller api.h*/
typedef struct WL_CTRL_T
{
int targetNumThreads;
int sizeBuf;
int numEntries;
int nextIdx;
thread_state_control_t volatile thread_state_control[THREAD_NUM];
mon_entry_t buffer[];
} wl_ctrl_t;
typedef struct THREADPOOL_T
{
int num_threads;
int qsize;
pthread_t *threads;
todo_t *qhead;
todo_t *qtail;
pthread_mutex_t qlock;
pthread_cond_t q_not_empty;
pthread_cond_t q_empty;
int shutdown;
int dont_accept;
}threadpool_t;
typedef struct TODO_T
{
void (*routine) (void*);
void * arg;
int lock;
struct todo_t* next;
} todo_t;
The function assigned to the pthread
/********************************************************************
*
* do_work:
*
* this is the reusable thread, assigned work via the dispatch
* function.
*
********************************************************************/
void* do_work(void *p)
{
int c = 0;
thread_args_t *thread_args = (thread_args_t*)p;
threadpool_t *pool = thread_args->threadpool;
todo_t* workload;
wl_ctrl_t volatile *wcc = thread_args->wl_ctrl;
while(1)
{
pool->qsize = pool->qsize;
/* while work que is empty, spinlock */
while( pool->qsize == 0)
{
if(c<1)
printf("thread: %d spin-lock \n", thread_args->thread_id);
c++;
}
/* update the threadpool, minus current workload */
workload = pool->qhead;
pool->qsize--;
if(pool->qsize == 0)
{
pool->qhead = NULL;
pool->qtail = NULL;
}
else
{
pool->qhead = workload->next;
}
/* execute workload */
(workload->routine) (workload->arg);
free(workload);
/* check this threads wait state */
printf("In thread: %d\n",wcc->thread_state_control[thread_args->thread_id].active);
}
}

query about few threading terms

I am understanding and implementing the concept of threading in my application. Since now things are going good. But I have few questions still unanswered and they are making me slow now. I would appreciate if anyone replies to even any of them
In Createthread(), can we only take 1 argument? as I have seen in MSDN website and all other examples that I have seen I saw only 1 argument, LPVOID.
The other thing is , what does the return value DWORD WINAPI means as a return value? Can we have only DWORD , int or any other return type. I suppose it has something to do with HANDLE (may be)
I want to use the array of the thread, hence I learn the array to functions, and (as I have understood) threads are itself just a function called by CreateThread() routine, hence I tried to implement that concept there but could not because of the return type DWORD WINAPI was not allowing me to do so?
I have one single thread for saving files, now I want its array so that I can save multiple files at the same time (not exaclty the same starting time, but sort of parallel file saving). How can I do that?
Thanks
Shan
Indeed, you can only take one argument, of type void * (LPVOID).
However, since it can point to anything, it can point to a struct
or object (usually allocated on the heap for lifetime reasons).
WINAPI is not part of the return value, it's the function's calling
convention. The function must return a DWORD or anything that fit
in it. It must NOT return a pointer, because a pointer can't fit a
DWORD in Win64.
I don't understand, please elaborate what you're
trying to do.
Usually for this you need a single thread function,
passed several times to CreateThread() with a different argument
each time. Don't forget to keep the thread handles (which you'll
likely save in an array) until you stop needing them and close them
with CloseHandle().
for the point number three I guess I understood and will try differently. I was using
DWORD WINAPI save_uwpi_file0( LPVOID )
{
while(1)
{
if(release == 1 && flag_oper1 == 1)
{
int w_cnt = 0; FILE *opfile;
char fname[30] = "txt_file0.txt";
//opening file for write
opfile = fopen(fname , "w");
printf("assigning memory for file 1 \n");
ssint *Lmem = (ssint *)malloc( sizeof(ssint)*size_of_memory);
memcpy(Lmem, pInDMA, sizeof(ssint)*size_of_memory);
release = 0;
printf("relseaing for second file saving\n");
for( int nbr = 0; nbr < size_of_memory; nbr++){
fprintf(opfile , "%hi\n", Lmem[nbr] );
}
printf("aligned free 1\n");
free(Lmem);
fclose(opfile);
printf("File saved 1\n\n");
return 1;
} //if statement ends
}
}
and I was using following to make the pointer to (thread) function
DWORD WINAPI (* save_uwpi_file0)(LPVOID);
I guess I should try something like
DWORD (* save_uwpi_file0)(LPVOID);
I will do it and post the result here

Using pthread_create

I am having errors when I try to use pthread_create. I understand that my use of argsRight->thread_id / argsLeft->thread_id and NULL are not correct, but I am unsure how else to make a reference to the thread id. It requires a pointer, but it seems like every way I tried (&, *), the GCC compiler would not accept.
Also, is there any reason it will not accept my use of NULL? I can't see any reason that would be wrong, but GCC says my use of the void function is invalid.
Can anyone shed some light on how to properly set up a call to pthread_create? I have included parts from my method where I am using the pthread_create function.
void pthreads_ms(struct ms_args* args)
{
int left_end = (args->end + args->start) / 2;
int right_start = left_end + 1;
int rc1, rc2;
// Create left side struct
struct ms_args* argsLeft;
argsLeft = malloc(sizeof(args));
argsLeft->thread_id = (2 * args->thread_id + 1);
argsLeft->start = args->start;
argsLeft->end = left_end;
argsLeft->array = args->array;
// Same methodology as above to create the right side
if (args->start != args->end)
{
// Print the thread id number, and start and end places
printf("[%d] start %d end %d", args->thread_id, args->start, args->end);
// Sort Left Side
rc1 = pthread_create(argsLeft->thread_id, NULL, pthreads_ms(argsLeft), argsLeft); //problem line here
//Sort right side
rc2 = pthread_create(argsRight->thread_id, NULL, pthreads_ms(argsRight), argsRight); //problem line here
}
It is not your application, it's pthread_create() will fill thread_id field. So, first of all, struct ms_args's field should be of type pthread_t and you should pass a pointer to that field:
pthread_create(&argsLeft->thread_id, ...
According to pthread_create the proper call should be
rc1 = pthread_create(&(argsLeft->thread_id), NULL, &pthreads_ms, argsLeft);
Same goes for right side.
The definition of pthread_ms() should include a return value
void *pthreads_ms(struct ms_args* args) { ... }
Besides that, your code looks pretty dangerous to me, since it creates recursively two threads for every existing one. Depending on your input, this might build a large tree of threads, which could bring your system to a halt.

My g_thread_push is not working

I am trying to create a multi-thread, jpg rotation program but I am having problems getting g_thread to work.
int processUserRequest (UserRequest *uRequest,
char * const* argv, int argc, int optind){
struct RotationData CurData;
CurData.argv=argv;
CurData.argc=argc;
CurData.optind=optind;
CurData.uRequest=uRequest;
gpointer user_data = &CurData;
int transform = FALSE;
int max_files = argc - optind;
int i;
gpointer data=&i;
GThreadPool *pool;
if(!g_thread_supported())
g_thread_init(NULL);
pool = g_thread_pool_new(MultiThreadRotation,user_data, 5, TRUE, NULL);
for(i=0;i
{
g_thread_pool_push(pool, &data,NULL);
}
//g_thread_pool_free (pool, TRUE,TRUE);
//Create a montage file
transform = createMontageFile (uRequest);
return transform;
}
The function MultiThreadRotation is suppose to be called by g_thread_pool_push, but it is not being good once. Can anyone help, I am quite the novice.
Also, I thought about outputting the error from g_thread_pool_push, how would you output a GError *error message?
First off, in the code you pasted, there's a bug in the for statement.
Assuming that's fixed, here are a few remarks.
I'm not sure why this is failing, but you can get some indication from the GError's "message" member, which is a human-readable C string you can use with printf() or whatever you like. Unfortunately, you've set the GError arguments to NULL in the g_thread_*() calls.
This routine leaks the thread pool; you should call g_thread_pool_free() before exiting it.
If you're doing other threading in your program, and you care about performance, you should think carefully about whether you want these threads to be exclusive or shared. That's set with the argument to g_thread_pool_new() which you've set to TRUE (exclusive).

Resources