1. concurrent-native-callbacks
    1. Requirements
    2. Introduction
    3. Programming interface
    4. Dispatcher API
    5. Version History
    6. License

concurrent-native-callbacks

Requirements

typed-records matchable bind miscmacros

Introduction

This extension provides a callback-facility that allows invoking Scheme code from native threads other than the thread that was used to start and execute the CHICKEN runtime system. The callbacks are intended for Scheme applications that are embedded in a C/C++ program, but can of course also be used from Scheme code that spawns native threads. A UNIX pipe is used to transfer blocks of arguments (or pointers to arguments) between the different execution contexts.

The usage is very similar to define-external:

(define-concurrent-native-callback (signal_to_scheme (int eventcode))
  (print "I got signal number " eventcode))

(foreign-declare #<<EOF

static void *start_thread(void *arg)
{
  signal_to_scheme(42);
}

EOF
)

(foreign-code #<<EOF

pthread_t t1;

pthread_create(&t1, NULL, start_thread, NULL);

EOF
)

(dispatch)     ; waits for default dispatcher, alternatively use "thread-sleep!"

This egg is part of the chicken-mobile project. The sources are available here: https://github.com/chicken-mobile/concurrent-native-callbacks

Programming interface

[syntax] (define-concurrent-native-callback (NAME (FOREIGNTYPE1 ARGUMENT1) ...) BODY ...)

Defines an external entry-point. Any concurrently executing native thread can invoke this entry-point which will collect the arguments and send them to a background (user-level) Scheme thread, called a "dispatcher", that subsequently executes BODY. Each callback is associated with a dispatcher thread, either the default one or one that is explicitly given in the callback definition:

 (define-concurrent-native-callback ((NAME DISPATCHER-ID) (FOREIGNTYPE1 ARGUMENT1) ...) BODY ...)

It is possible to use a single dispatcher for all callback definitions in a running Scheme process or use one dispatcher for every callback. Dispatcher threads are created on demand, once a callback-definition referes to a particular dispatcher-ID.

A callback defined with define-concurrent-native-callback has no return value and will return immediately.

[syntax] (define-synchronous-concurrent-native-callback (NAME (FOREIGNTYPE1 ARGUMENT1) ...) RESULTTYPE BODY ...)

Defines a "synchronous" callback that will wait until the Scheme handler returns with a result. Only result-types that do not refer to data on the garbage-collected Scheme heap are valid The compiler will emit a warning should a such a result-type occur in RESULTTYPE (data like byte-vectors can be allocated statically, which would be valid in this case).

Synchronous callbacks must not be invoked from the same (native) thread that is executing the Scheme runtime system or the process will hang indefinitely.

Dispatcher API

[procedure] (dispatcher ID)

Returns the dispatcher with the name ID, which should be a symbol. If a dispatcher with this name does not exist, create a new one and start a dispatcher thread.

[procedure] (dispatcher? X)

Returns true if X is a dispatcher-object or false otherwise.

[procedure] (dispatcher-ID DISPATCHER)

Returns the name of DISPATCHER.

[procedure] (dispatcher-thread DISPATCHER)

Returns the SRFI-18 thread associated with DISPATCHER.

[procedure] (dispatcher-argument-input-fileno DISPATCHER)
[procedure] (dispatcher-argument-output-fileno DISPATCHER)
[procedure] (dispatcher-result-input-fileno DISPATCHER)
[procedure] (dispatcher-result-output-fileno DISPATCHER)

Return the file-descriptors that are used to communicate between native threads and the CHICKEN runtime.

[procedure] (dispatcher-add! DISPATCHER CALLBACKNAME PROCEDURE)

Adds a new callback to DISPATCHER with the name CALLBACKNAME (a symbol). PROCEDURE is the raw callback procedure, taking a dispatcher object and pointer to an argument block as parameters.

[procedure] (dispatcher-terminate! DISPATCHER)

Sends a termination message to the dispatcher to make it finish waiting for incoming callbacks. Further invocations of callbacks associated with the dispatcher will have no effect.

[procedure] (dispatch [ID])

Starts a dispatcher thread, optionally with an ID, which defaults to default. The procedure does not return until the dispatching thread receives a termination-message.

Version History

0.5
fixed various bugs, dispatch waits by joining dispatcher thread (thanks to Hugo Arregui)
0.2
added dispatch
0.1
initial release

License

 Copyright (c) 2013, Bevuta IT GmbH
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
 conditions are met:
 
   Redistributions of source code must retain the above copyright notice, this list of conditions and the following
     disclaimer.
   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
     disclaimer in the documentation and/or other materials provided with the distribution.
   Neither the name of the author nor the names of its contributors may be used to endorse or promote
     products derived from this software without specific prior written permission.
 
 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 POSSIBILITY OF SUCH DAMAGE.