If you need something to be dynamic based on a situation like so:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <stdbool.h>
typedef int (*worker_operation)(int);
int check_for_new_woot(int inVal) {
int ret = arc4random() % 10;
if (ret < 5) {
puts("Found new woot!");
sleep(1);
return 1;
} else {
puts("No new woot :(");
sleep(1);
return 0;
}
}
int buy_current_woot(int inVal) {
if (inVal != 0) {
fprintf(stderr, "Insufficient funds!!!\n");
}
return 0;
}
int check_if_should_buy_woot(int inVal) {
printf("Should we buy the latest woot? ");
char input[10];
read(STDIN_FILENO, input, 10);
if (input[0] == 'y') {
return 1;
} else {
return 0;
}
}
void *worker_thread(void *inVal) {
worker_operation *ops = (worker_operation *)inVal;
int i = 0;
worker_operation op = ops[i];
int arg = 0;
while (op) {
arg = op(arg);
op = ops[++i];
}
free(ops);
return NULL;
}
pthread_t start_worker(worker_operation *ops) {
pthread_t pt;
pthread_create(&pt, NULL, worker_thread, ops);
return pt;
}
int main(int argc, const char *argv[]) {
bool autoBuy = true; // fetch whether we should automatically buy from woot.com from argv or stdin
int numberLoops = 10; // fetch number of times to loop through the process
int i;
worker_operation *operations;
if (autoBuy) {
operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 2 + 1));
for (i = 0; i < numberLoops; i++) {
operations[2 * i] = check_for_new_woot;
operations[2 * i + 1] = buy_current_woot;
}
operations[2 * i] = (worker_operation)NULL;
} else {
operations = (worker_operation *)malloc(sizeof(worker_operation) * (numberLoops * 3 + 1));
for (i = 0; i < numberLoops; i++) {
operations[3 * i] = check_for_new_woot;
operations[3 * i + 1] = check_if_should_buy_woot;
operations[3 * i + 2] = buy_current_woot;
}
operations[3 * i] = (worker_operation)NULL;
}
pthread_join(start_worker(operations), NULL);
return 0;
}
Note that in this code snippet uses function pointers in two places. We have a function which is agnostic of how the user wants the program to perform, that is start_worker
simply creates a worker thread that will work with a list of operations. This can be easily used to create a program which has multiple threads going all with different operation queues. The second place function pointers are used are with threads. The ptrhead_create
call uses a function pointer in order to create a new thread (the function specified is the function to be ran on the new thread).
Generally this is called a command programming paradigm. One can easily create an operation that another part of code can call, agnostic of what the function does. For instance this could be useful for games in the following situation:
We have a game controller that gives input. The user clicks 'up'. In code call the operation that is hooked to the 'up' action.
This modular approach allows one to enable settings for the controls so someone can hook a 'jump' operation to 'up' or a 'move forward' operation, or anything really.
Hope this helps!