#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <pthread.h>
#include <unistd.h>
#include <semaphore.h>
bool prtlog = true;
#define ASSERT(cond) \
if (!(cond)) {printf("ASSERT | file: %s line: %d func: %s\n", __FILE__, __LINE__, __FUNCTION__); exit(-1);}
#define LOG(thdctl, fmt, ...) \
do { \
if (prtlog) { \
char data_[2048]; \
snprintf(data_, 2048, (fmt), ##__VA_ARGS__); \
thdctl != NULL ? \
printf(" >%-3d %s\n", ((ThdCtl *)(thdctl))->id, data_) : \
printf("%s\n", data_); \
} \
} while (0)
/* ---------------------------------------------------------------------- */
typedef struct ThdCtl ThdCtl;
typedef struct ThdData ThdData;
typedef void (*ThdHookFunc)(ThdCtl *thdctl, ThdData *data);
struct ThdCtl {
/* thread info */
int stat;
pthread_t thd;
int id;
/* thread function */
ThdHookFunc init_func;
ThdHookFunc exec_func;
ThdHookFunc exit_func;
ThdData *data;
/* thread control */
bool iswait;
sem_t wait;
};
typedef struct {
int thdnum;
ThdCtl *thdarr[10000];
} ProCtl;
/* ---------------------------------------------------------------------- */
void multi_execute(ThdHookFunc initfunc, ThdHookFunc execfunc, ThdHookFunc exitfunc, int thdnum, ThdData *dataarr);
typedef struct ThdData {
int id;
} ThdData;
void init(ThdCtl *thdctl, ThdData *data)
{
LOG(thdctl, "init");
data->id = thdctl->id;
}
void execute(ThdCtl *thdctl, ThdData *data)
{
LOG(thdctl, "execute, id: %d", data->id);
}
void finish(ThdCtl *thdctl, ThdData *data)
{
LOG(thdctl, "finish, id: %d", data->id);
}
int main()
{
ThdData datas[10] = {0};
multi_execute(init, execute, finish, 10, datas);
return 0;
}
/* ---------------------------------------------------------------------- */
void *thread_main(void *arg)
{
ThdCtl *tctl = (ThdCtl *)arg;
if (tctl->init_func != NULL) {
tctl->init_func(tctl, tctl->data);
}
/* wait to be wake up */
// LOG(tctl, "sleep");
sem_wait(&tctl->wait);
/* wake up now */
// LOG(tctl, "wakeup");
tctl->iswait = false;
/* ====== user funtion begin ========== */
if (tctl->exec_func != NULL) {
tctl->exec_func(tctl, tctl->data);
}
/* ====== user funtion finish ========== */
if (tctl->exit_func != NULL) {
tctl->exit_func(tctl, tctl->data);
}
return NULL;
}
ThdCtl *create_thread(ProCtl *process, ThdHookFunc initfunc, ThdHookFunc execfunc, ThdHookFunc exitfunc, void *thddata)
{
static int thdid = 0;
ThdCtl *t = (ThdCtl *)malloc(sizeof(ThdCtl));
if (t == NULL) {
ASSERT(false);
return NULL;
}
/* thread info */
t->stat = -1;
t->id = thdid++;
/* thread function */
t->init_func = initfunc;
t->exec_func = execfunc;
t->exit_func = exitfunc;
t->data = thddata;
t->stat = pthread_create(&t->thd, NULL, thread_main, t);
/* thread control */
t->iswait = true;
sem_init(&t->wait, 0, 0);
process->thdarr[process->thdnum] = t;
process->thdnum++;
return t;
}
ProCtl *create_process()
{
ProCtl *pro = (ProCtl *)malloc(sizeof(ProCtl));
ASSERT(pro != NULL);
pro->thdnum = 0;
memset(pro->thdarr, 0, sizeof(pro->thdarr));
return pro;
}
void multi_execute(ThdHookFunc initfunc, ThdHookFunc execfunc, ThdHookFunc exitfunc, int thdnum, ThdData *dataarr)
{
ProCtl *pro = create_process();
LOG(NULL, "init ------------------------");
int i;
for (i = 0; i < thdnum; i++) {
create_thread(pro, initfunc, execfunc, exitfunc, &dataarr[i]);
}
LOG(NULL, "execute ------------------------");
for (i = 0; i < pro->thdnum; i++) {
ThdCtl *tctl = pro->thdarr[i];
sem_post(&tctl->wait);
}
for (i = 0; i < pro->thdnum; i++) {
pthread_join(pro->thdarr[i]->thd, NULL);
}
LOG(NULL, "finish ------------------------");
}