@@ -196,14 +196,6 @@ static void isaio_complete(void *arg) {
196196
197197}
198198
199- static void raio_invoke_cb (void * arg ) {
200- nano_aio * raio = (nano_aio * ) arg ;
201- SEXP callExpr ;
202- PROTECT (callExpr = Rf_lcons ((SEXP ) raio -> cb , R_NilValue ));
203- (void ) Rf_eval (callExpr , R_GlobalEnv );
204- UNPROTECT (1 );
205- }
206-
207199static void raio_complete (void * arg ) {
208200
209201 nano_aio * raio = (nano_aio * ) arg ;
@@ -219,7 +211,6 @@ static void raio_complete(void *arg) {
219211 raio -> result = res - !res ;
220212#endif
221213
222- later2 (raio_invoke_cb , arg , 0 );
223214}
224215
225216static void raio_complete_signal (void * arg ) {
@@ -239,7 +230,6 @@ static void raio_complete_signal(void *arg) {
239230 nng_cv_wake (cv );
240231 nng_mtx_unlock (mtx );
241232
242- later2 (raio_invoke_cb , arg , 0 );
243233}
244234
245235static void request_complete_signal (void * arg ) {
@@ -262,6 +252,55 @@ static void request_complete_signal(void *arg) {
262252
263253}
264254
255+ static void raio_invoke_cb (void * arg ) {
256+ SEXP callExpr ;
257+ PROTECT (callExpr = Rf_lcons ((SEXP ) arg , R_NilValue ));
258+ (void ) Rf_eval (callExpr , R_GlobalEnv );
259+ UNPROTECT (1 );
260+ R_ReleaseObject (arg );
261+ }
262+
263+ static void raio_complete_cb (void * arg ) {
264+
265+ nano_aio * raio = (nano_aio * ) arg ;
266+ const int res = nng_aio_result (raio -> aio );
267+ if (res == 0 )
268+ raio -> data = nng_aio_get_msg (raio -> aio );
269+
270+ #ifdef NANONEXT_LEGACY_NNG
271+ nng_mtx_lock (shr_mtx );
272+ raio -> result = res - !res ;
273+ nng_mtx_unlock (shr_mtx );
274+ #else
275+ raio -> result = res - !res ;
276+ #endif
277+
278+ later2 (raio_invoke_cb , raio -> cb , 0 );
279+
280+ }
281+
282+ static void request_complete_cb (void * arg ) {
283+
284+ nano_aio * raio = (nano_aio * ) arg ;
285+ nano_aio * saio = (nano_aio * ) raio -> next ;
286+ nano_cv * ncv = (nano_cv * ) saio -> next ;
287+ nng_cv * cv = ncv -> cv ;
288+ nng_mtx * mtx = ncv -> mtx ;
289+
290+ const int res = nng_aio_result (raio -> aio );
291+ if (res == 0 )
292+ raio -> data = nng_aio_get_msg (raio -> aio );
293+
294+ nng_mtx_lock (mtx );
295+ raio -> result = res - !res ;
296+ ncv -> condition ++ ;
297+ nng_cv_wake (cv );
298+ nng_mtx_unlock (mtx );
299+
300+ later2 (raio_invoke_cb , raio -> cb , 0 );
301+
302+ }
303+
265304static void iraio_complete (void * arg ) {
266305
267306 nano_aio * iaio = (nano_aio * ) arg ;
@@ -720,7 +759,7 @@ SEXP rnng_send_aio(SEXP con, SEXP data, SEXP mode, SEXP timeout, SEXP clo) {
720759}
721760
722761SEXP rnng_recv_aio_impl (const SEXP con , const SEXP mode , const SEXP timeout ,
723- const SEXP bytes , const SEXP clo , const SEXP cb , nano_cv * ncv ) {
762+ const SEXP bytes , const SEXP clo , nano_cv * ncv ) {
724763
725764 const nng_duration dur = timeout == R_NilValue ? NNG_DURATION_DEFAULT : (nng_duration ) Rf_asInteger (timeout );
726765 const int signal = ncv != NULL ;
@@ -736,7 +775,6 @@ SEXP rnng_recv_aio_impl(const SEXP con, const SEXP mode, const SEXP timeout,
736775 raio -> next = ncv ;
737776 raio -> type = RECVAIO ;
738777 raio -> mode = mod ;
739- raio -> cb = cb ;
740778
741779 if ((xc = nng_aio_alloc (& raio -> aio , signal ? raio_complete_signal : raio_complete , raio )))
742780 goto exitlevel1 ;
@@ -803,19 +841,19 @@ SEXP rnng_recv_aio_impl(const SEXP con, const SEXP mode, const SEXP timeout,
803841
804842}
805843
806- SEXP rnng_recv_aio (SEXP con , SEXP mode , SEXP timeout , SEXP bytes , SEXP clo , SEXP cb ) {
844+ SEXP rnng_recv_aio (SEXP con , SEXP mode , SEXP timeout , SEXP bytes , SEXP clo ) {
807845
808- return rnng_recv_aio_impl (con , mode , timeout , bytes , clo , cb , NULL );
846+ return rnng_recv_aio_impl (con , mode , timeout , bytes , clo , NULL );
809847
810848}
811849
812- SEXP rnng_recv_aio_signal (SEXP con , SEXP cvar , SEXP mode , SEXP timeout , SEXP bytes , SEXP clo , SEXP cb ) {
850+ SEXP rnng_recv_aio_signal (SEXP con , SEXP cvar , SEXP mode , SEXP timeout , SEXP bytes , SEXP clo ) {
813851
814852 if (R_ExternalPtrTag (cvar ) != nano_CvSymbol )
815853 Rf_error ("'cv' is not a valid Condition Variable" );
816854 nano_cv * ncv = (nano_cv * ) R_ExternalPtrAddr (cvar );
817855
818- return rnng_recv_aio_impl (con , mode , timeout , bytes , clo , cb , ncv );
856+ return rnng_recv_aio_impl (con , mode , timeout , bytes , clo , ncv );
819857
820858}
821859
@@ -1224,11 +1262,13 @@ SEXP rnng_ncurl_session_close(SEXP session) {
12241262// request ---------------------------------------------------------------------
12251263
12261264SEXP rnng_request_impl (const SEXP con , const SEXP data , const SEXP sendmode ,
1227- const SEXP recvmode , const SEXP timeout , const SEXP clo , nano_cv * ncv ) {
1265+ const SEXP recvmode , const SEXP timeout , const SEXP clo ,
1266+ nano_cv * ncv , const SEXP cb ) {
12281267
12291268 const nng_duration dur = timeout == R_NilValue ? NNG_DURATION_DEFAULT : (nng_duration ) Rf_asInteger (timeout );
12301269 const int mod = nano_matcharg (recvmode );
12311270 const int signal = ncv != NULL ;
1271+ const int promises = cb != NULL ;
12321272 nng_ctx * ctx = (nng_ctx * ) R_ExternalPtrAddr (con );
12331273 SEXP aio , env , fun ;
12341274 nano_buf buf ;
@@ -1267,8 +1307,15 @@ SEXP rnng_request_impl(const SEXP con, const SEXP data, const SEXP sendmode,
12671307 raio -> type = RECVAIO ;
12681308 raio -> mode = mod ;
12691309 raio -> next = saio ;
1270-
1271- if ((xc = nng_aio_alloc (& raio -> aio , signal ? request_complete_signal : raio_complete , raio )))
1310+ if (promises )
1311+ R_PreserveObject (cb );
1312+ raio -> cb = cb ;
1313+
1314+ if ((xc = nng_aio_alloc (& raio -> aio ,
1315+ promises ?
1316+ (signal ? request_complete_cb : raio_complete_cb ) :
1317+ (signal ? request_complete_signal : raio_complete ),
1318+ raio )))
12721319 goto exitlevel2 ;
12731320
12741321 nng_aio_set_timeout (raio -> aio , dur );
@@ -1306,7 +1353,7 @@ SEXP rnng_request(SEXP con, SEXP data, SEXP sendmode, SEXP recvmode, SEXP timeou
13061353 if (R_ExternalPtrTag (con ) != nano_ContextSymbol )
13071354 Rf_error ("'con' is not a valid Context" );
13081355
1309- return rnng_request_impl (con , data , sendmode , recvmode , timeout , clo , NULL );
1356+ return rnng_request_impl (con , data , sendmode , recvmode , timeout , clo , NULL , NULL );
13101357
13111358}
13121359
@@ -1318,7 +1365,18 @@ SEXP rnng_request_signal(SEXP con, SEXP data, SEXP cvar, SEXP sendmode, SEXP rec
13181365 Rf_error ("'cv' is not a valid Condition Variable" );
13191366 nano_cv * ncv = (nano_cv * ) R_ExternalPtrAddr (cvar );
13201367
1321- return rnng_request_impl (con , data , sendmode , recvmode , timeout , clo , ncv );
1368+ return rnng_request_impl (con , data , sendmode , recvmode , timeout , clo , ncv , NULL );
1369+
1370+ }
1371+
1372+ SEXP rnng_request_promise (SEXP con , SEXP data , SEXP cvar , SEXP sendmode , SEXP recvmode , SEXP timeout , SEXP clo , SEXP cb ) {
1373+
1374+ if (R_ExternalPtrTag (con ) != nano_ContextSymbol )
1375+ Rf_error ("'con' is not a valid Context" );
1376+
1377+ nano_cv * ncv = R_ExternalPtrTag (cvar ) == nano_CvSymbol ? (nano_cv * ) R_ExternalPtrAddr (cvar ) : NULL ;
1378+
1379+ return rnng_request_impl (con , data , sendmode , recvmode , timeout , clo , ncv , cb );
13221380
13231381}
13241382
0 commit comments