1 |
/* |
2 |
* Author: Marc A. Lehmann <xsthreadpool@schmorp.de> |
3 |
* License: public domain, or where this is not possible/at your option, |
4 |
* CC0 (https://creativecommons.org/publicdomain/zero/1.0/) |
5 |
*/ |
6 |
#ifndef XSTHREADPOOL_H |
7 |
#define XSTHREADPOOL_H |
8 |
|
9 |
#define XSTHREADPOOL_VERSION 1 |
10 |
#define XSTHREADPOOL_MAGIC1 0x03417854 |
11 |
#define XSTHREADPOOL_MAGIC2 0x809a7b39 |
12 |
|
13 |
struct xsthreadpool_request_type |
14 |
{ |
15 |
U32 magic1; |
16 |
int req_data_size; |
17 |
|
18 |
/* this should fill in the request structure, which has undefined contents */ |
19 |
/* by parsing the nitem perl scalars at *items */ |
20 |
/* typically, this does some error checking and then serialises the items into *req_data */ |
21 |
/* on error, it should simply croak */ |
22 |
/* this callback must not block (in the Coro sense) */ |
23 |
/* can be 0 if no preparation is needed */ |
24 |
void (*xstpreq_prepare) (pTHX_ void *req_struct, SV **items, int nitems); |
25 |
|
26 |
/* this is called in another thread and should do the actual work */ |
27 |
/* it MUST NOT access any perl data structures */ |
28 |
/* but can freely read and write *req_data */ |
29 |
/* this is the only callback that cannot be 0 */ |
30 |
void (*xstpreq_execute) (void *req_data); |
31 |
|
32 |
/* this should push any result values to be passed to the rfesult callback */ |
33 |
/* onto the perl stack */ |
34 |
/* it can be 0 if the request never has any results */ |
35 |
void (*xstpreq_finish) (pTHX_ void *req_data); |
36 |
|
37 |
/* this should destroy/free the request data */ |
38 |
/* it can be called at any time from perl */ |
39 |
/* specifically, both before or after the request has executed */ |
40 |
/* it can be 0 if no cleanup is required */ |
41 |
void (*xstpreq_destroy) (pTHX_ void *req); |
42 |
|
43 |
U32 magic2; |
44 |
}; |
45 |
|
46 |
/* |
47 |
* define a new xs threadpool request type/handler. |
48 |
* stash is the package the name should be put in, |
49 |
* e.g. gv_stashpvn (PACKAGE, sizeof (PACKAGE), TRUE) |
50 |
* or, in an xs function or BOOT:, you can use "CvSTASH (cv)" |
51 |
* name is the perl function name inside the stash |
52 |
* datatype should be the request data type, which is passed to prepare/exec/finish/free |
53 |
* it should not be too large, try not to make it larger than, say, 200 bytes. |
54 |
*/ |
55 |
#define XSTHREADPOOL_REQUEST_TYPE(stash,name,datatype,prepare,execute,finish,destroy) \ |
56 |
do { \ |
57 |
/* these assignments exist only for type checking, and will likely be optimised out */ \ |
58 |
void (*xstpreq_prepare)(datatype *, SV **, int) = (prepare); \ |
59 |
void (*xstpreq_execute)(datatype *) = (execute); \ |
60 |
void (*xstpreq_finish )(datatype *) = (finish ); \ |
61 |
void (*xstpreq_destroy)(datatype *) = (destroy); \ |
62 |
/* this does the actual registration */ \ |
63 |
static const struct xsthreadpool_request_type xsthreadpool_request_type = { \ |
64 |
XSTHREADPOOL_MAGIC1, \ |
65 |
sizeof (datatype), \ |
66 |
(void (*)(void *, SV **, int))(prepare), \ |
67 |
(void (*)(void *))(execute), \ |
68 |
(void (*)(void *))(finish), \ |
69 |
(void (*)(void *))(destroy), \ |
70 |
XSTHREADPOOL_MAGIC2 \ |
71 |
}; \ |
72 |
SV *request_type_sv = newSVpvn ((void *)&xsthreadpool_request_type, \ |
73 |
sizeof (xsthreadpool_request_type)); \ |
74 |
SvREADONLY_on (request_type_sv); \ |
75 |
newCONSTSUB ((stash), (name), request_type_sv); \ |
76 |
} while (0) |
77 |
|
78 |
#endif |
79 |
|