Athos Bacchiocchi wrote:
[...]
> It would be really useful and much appreciated, in the meanwhile I will
> study the references you and Dianne gave me and try to come up with
> something working. Thank you both for the hints, they really helped me.
This is cut-and-pasted and bodged a bit, so there may be typos; and
there may also be subtle bugs in the logic. All I can say is that it
works for me...
struct Message { ... };
static int messagePipe[2];
static const int LOOPER_ID_MESSAGEPIPE = LOOPER_ID_USER;
/* Call from engine thread */
void post_message(Message* msg)
{
if (write(messagePipe[1], msg, sizeof(msg)) != sizeof(msg))
{
/* This may never happen if the writing end of the
* pipe is blocking. If it's non-blocking, then if
* the buffer is full the write will fail. */
LOGI("panic! callback buffer overrun!");
}
}
/* Invoked by ALooper to process a message */
static int messagepipe_cb(int fd, int events, void* user)
{
Message msg;
while (read(fd, &msg, sizeof(msg)) == sizeof(msg))
{
/* Do whatever needs doing when a message is
* received. Provided sizeof(msg) <= PIPE_BUF
* you should never get short reads. */
HandleMessage(msg);
}
return 1;
}
/* Call this from your main thread to set up the callback pipe. */
void setup_callback_pipe(void)
{
int i = pipe2(messagePipe, O_NONBLOCK | O_CLOEXEC);
assert(i != -1); /* I can't imagine why this would ever fail */
/* You may want to make messagePipe[1] blocking here,
* if you want the engine thread to block if the buffer
* fills up (rather than failing to send the message).
* I've never done this. YMMV. */
/* Register the file descriptor to listen on. */
ALooper_addFd(appState->looper,
messagePipe[0], LOOPER_ID_MESSAGEPIPE,
ALOOPER_EVENT_INPUT, messagepipe_cb, NULL);
│ "Parents let children ride bicycles on the street. But parents do not
│ allow children to hear vulgar words. Therefore we can deduce that
│ cursing is more dangerous than being hit by a car." --- Scott Adams