Skip to content

Instantly share code, notes, and snippets.

@Geal
Last active January 22, 2023 10:07
Show Gist options
  • Star 21 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save Geal/8f85e02561d101decf9a to your computer and use it in GitHub Desktop.
Save Geal/8f85e02561d101decf9a to your computer and use it in GitHub Desktop.
small future and promise library in C with pthreads
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include <time.h>
#include <stdarg.h>
#include <string.h>
#include "future.h"
future* future_create(void *(*start_routine) (void *)) {
future* f = malloc(sizeof(future));
pthread_attr_init(&f->attr);
pthread_attr_setdetachstate(&f->attr, PTHREAD_CREATE_JOINABLE);
f->func = start_routine;
srand(time(NULL));
f->id = rand();
return f;
}
void* future_func_wrapper(void *arg) {
//msg("WRAP");
future_arg* f = (future_arg*) arg;
void* res = f->func(f->arg);
free(f);
//msg("WRAPPED");
pthread_exit(res);
return res;
}
void future_start(future* f, void* arg) {
future_arg* farg = malloc(sizeof(future_arg));
farg->func = f->func;
farg->arg = arg;
pthread_create(&f->thread, &f->attr, future_func_wrapper, farg);
}
void future_stop(future* f) {
pthread_cancel(f->thread);
}
void future_close(future* f) {
void * status;
int rc = pthread_join(f->thread, &status);
pthread_attr_destroy(&f->attr);
free(f);
}
promise* promise_create() {
promise* p = malloc(sizeof(promise));
pthread_mutex_init(&p->mutex, NULL);
pthread_cond_init(&p->cond, NULL);
srand(time(NULL));
p->id = rand();
msg("P(%d) created", p->id);
return p;
}
void promise_set(promise* p, int res) {
msg("P(%d) set LOCK", p->id);
pthread_mutex_lock(&p->mutex);
p->result = res;
p->done = true;
pthread_cond_signal(&p->cond);
msg("P(%d) set UNLOCK", p->id);
pthread_mutex_unlock(&p->mutex);
}
int promise_get(promise* p) {
msg("P(%d) get LOCK", p->id);
pthread_mutex_lock(&p->mutex);
while(!p->done) {
msg("P(%d) get WAIT", p->id);
pthread_cond_wait(&p->cond, &p->mutex);
}
msg("P(%d) get UNLOCK", p->id);
pthread_mutex_unlock(&p->mutex);
return p->result;
}
bool promise_done(promise* p) {
pthread_mutex_lock(&p->mutex);
bool done = p->done;
pthread_mutex_unlock(&p->mutex);
return done;
}
void promise_close(promise* p) {
pthread_mutex_destroy(&p->mutex);
pthread_cond_destroy(&p->cond);
free(p);
}
#include <stdbool.h>
typedef struct _future {
pthread_t thread;
pthread_attr_t attr;
void *(*func) (void *);
} future;
typedef struct _future_arg {
void *(*func) (void *);
void * arg;
} future_arg;
typedef struct _promise {
int result;
pthread_mutex_t mutex;
pthread_cond_t cond;
bool done;
int id;
} promise;
future* future_create(void *(*start_routine) (void *));
void future_start(future* f, void* arg);
void future_stop(future* f);
void future_close(future* f);
promise* promise_create();
int promise_get(promise* p);
void promise_set(promise *p, int res);
bool promise_done(promise* p);
void promise_close(promise *p);
#ifdef DEBUG
#define msg(format, ...) printf("T(%d)|" format "\n", (int)pthread_self(), ##__VA_ARGS__)
#else
#define msg(format, ...)·
#endif
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdbool.h>
#include "future/future.h"
void* func(void * arg) {
promise* p = (promise*) arg;
printf("\tstarted thread\n");
sleep(3);
printf("\tthread will set promise\n");
promise_set(p, 42);
printf("\tstopping thread\n");
return NULL;
}
int main() {
long t;
printf("main thread\n");
future* f = future_create(func);
promise* p = promise_create();
future_start(f, p);
printf("got result from future: %d\n", promise_get(p));
promise_close(p);
future_close(f);
pthread_exit(NULL);
}
@Liam0205
Copy link

Liam0205 commented Jan 16, 2018

future_close(f) should be called before promise_close(p), otherwise, deadlock might happen.

@Globik
Copy link

Globik commented Jun 28, 2018

What's this? Is this identical to the c++ std::future under the hood?

@shipof123
Copy link

add a header guard:

#ifndef _FUTURE_H_
#define _FUTURE_H_
...
#endif  /*_FUTURE_H_*/

@anasuti
Copy link

anasuti commented Feb 26, 2020

to compile, should add "id" to the structure future:

typedef struct _future {
  pthread_t thread;
  pthread_attr_t attr;
  void *(*func) (void *); 
  int id; 
} future;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment