1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 2011-2016. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #include "erl_driver.h"
22
23 #define NO_ASYNC_JOBS 10000
24
25 static void stop(ErlDrvData drv_data);
26 static ErlDrvData start(ErlDrvPort port,
27 char *command);
28 static void output(ErlDrvData drv_data,
29 char *buf, ErlDrvSizeT len);
30 static void ready_async(ErlDrvData drv_data,
31 ErlDrvThreadData thread_data);
32
33 static ErlDrvEntry async_blast_drv_entry = {
34 NULL /* init */,
35 start,
36 stop,
37 output,
38 NULL /* ready_input */,
39 NULL /* ready_output */,
40 "async_blast_drv",
41 NULL /* finish */,
42 NULL /* handle */,
43 NULL /* control */,
44 NULL /* timeout */,
45 NULL /* outputv */,
46 ready_async,
47 NULL /* flush */,
48 NULL /* call */,
49 NULL /* event */,
50 ERL_DRV_EXTENDED_MARKER,
51 ERL_DRV_EXTENDED_MAJOR_VERSION,
52 ERL_DRV_EXTENDED_MINOR_VERSION,
53 ERL_DRV_FLAG_USE_PORT_LOCKING,
54 NULL /* handle2 */,
55 NULL /* handle_monitor */
56 };
57
58 typedef struct {
59 ErlDrvPort port;
60 ErlDrvTermData port_id;
61 ErlDrvTermData caller;
62 int counter;
63 } async_blast_data_t;
64
65
DRIVER_INIT(async_blast_drv)66 DRIVER_INIT(async_blast_drv)
67 {
68 return &async_blast_drv_entry;
69 }
70
stop(ErlDrvData drv_data)71 static void stop(ErlDrvData drv_data)
72 {
73 driver_free((void *) drv_data);
74 }
75
start(ErlDrvPort port,char * command)76 static ErlDrvData start(ErlDrvPort port,
77 char *command)
78 {
79 async_blast_data_t *abd;
80
81 abd = driver_alloc(sizeof(async_blast_data_t));
82 if (!abd)
83 return ERL_DRV_ERROR_GENERAL;
84
85 abd->port = port;
86 abd->port_id = driver_mk_port(port);
87 abd->counter = 0;
88 return (ErlDrvData) abd;
89 }
90
async_invoke(void * data)91 static void async_invoke(void *data)
92 {
93
94 }
95 #include <stdio.h>
96
ready_async(ErlDrvData drv_data,ErlDrvThreadData thread_data)97 static void ready_async(ErlDrvData drv_data,
98 ErlDrvThreadData thread_data)
99 {
100 async_blast_data_t *abd = (async_blast_data_t *) drv_data;
101 if (--abd->counter == 0) {
102 ErlDrvTermData spec[] = {
103 ERL_DRV_PORT, abd->port_id,
104 ERL_DRV_ATOM, driver_mk_atom("done"),
105 ERL_DRV_TUPLE, 2
106 };
107 erl_drv_send_term(abd->port_id, abd->caller,
108 spec, sizeof(spec)/sizeof(spec[0]));
109 }
110 }
111
output(ErlDrvData drv_data,char * buf,ErlDrvSizeT len)112 static void output(ErlDrvData drv_data,
113 char *buf, ErlDrvSizeT len)
114 {
115 async_blast_data_t *abd = (async_blast_data_t *) drv_data;
116 if (abd->counter == 0) {
117 int i;
118 abd->caller = driver_caller(abd->port);
119 abd->counter = NO_ASYNC_JOBS;
120 for (i = 0; i < NO_ASYNC_JOBS; i++) {
121 if (0 > driver_async(abd->port, NULL, async_invoke, NULL, NULL)) {
122 driver_failure_atom(abd->port, "driver_async_failed");
123 break;
124 }
125 }
126 }
127 }
128