hs_try_putmvar003_c.c 2.12 KB
Newer Older
Simon Marlow's avatar
Simon Marlow committed
1
2
3
4
5
6
7
8
9
10
11
#include "HsFFI.h"
#include "Rts.h"
#include "RtsAPI.h"
#include <unistd.h>
#include <pthread.h>
#include "hs_try_putmvar003_stub.h"

struct callback_queue {
    pthread_mutex_t lock;
    pthread_cond_t cond;
    int use_foreign_export;
12
13
14
    // How many requests will be submitted to this queue?
    // (e.g. n_threads * n_requests_per_thread)
    int n_requests;
Simon Marlow's avatar
Simon Marlow committed
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
    struct callback *pending;
};

struct callback {
    HsStablePtr mvar;
    int cap;
    int *presult;
    struct callback *next;
};

void* callback(struct callback_queue *q)
{
    struct callback *cb;

    pthread_mutex_lock(&q->lock);
30
    for (int i=0; i < q->n_requests; i++) {
Simon Marlow's avatar
Simon Marlow committed
31
32
33
34
35
36
37
38
39
40
41
42
43
44
        if (q->pending == NULL) {
            pthread_cond_wait(&q->cond,&q->lock);
        }
        if (q->pending != NULL) {
            cb = q->pending;
            q->pending = cb->next;
            *cb->presult = 42;
            if (q->use_foreign_export) {
                callbackPutMVar(cb->mvar);
            } else {
                hs_try_putmvar(cb->cap,cb->mvar);
            }
            free(cb);
        }
45
    }
Simon Marlow's avatar
Simon Marlow committed
46
47
48
49
50
51
52
53
    pthread_mutex_unlock(&q->lock);

    hs_thread_done();
    return NULL;
}

typedef void* threadfunc(void *);

54
struct callback_queue* mkCallbackQueue(int use_foreign_export, int n_requests)
Simon Marlow's avatar
Simon Marlow committed
55
56
57
58
59
60
61
{
    struct callback_queue *q = malloc(sizeof(struct callback_queue));
    pthread_t t;
    pthread_mutex_init(&q->lock, NULL);
    pthread_cond_init(&q->cond, NULL);
    q->pending = NULL;
    q->use_foreign_export = use_foreign_export;
62
    q->n_requests = n_requests;
Simon Marlow's avatar
Simon Marlow committed
63
    pthread_create(&t, NULL, (threadfunc*)callback, q);
Simon Marlow's avatar
Simon Marlow committed
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
    return q;
}

void destroyCallbackQueue(struct callback_queue *q)
{
    pthread_mutex_destroy(&q->lock);
    pthread_cond_destroy(&q->cond);
    free(q);
}

void scheduleCallback(struct callback_queue *q,
                      HsStablePtr mvar,
                      HsInt cap, int *presult)
{
    struct callback *p = malloc(sizeof(struct callback));
    p->mvar = mvar;
    p->cap = cap;
    p->presult = presult;
    pthread_mutex_lock(&q->lock);
    p->next = q->pending;
    q->pending = p;
    pthread_cond_signal(&q->cond);
    pthread_mutex_unlock(&q->lock);
}