[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: suggestion on error returns, especially in callbacks from C?
- From: Asko Kauppi <askok@...>
- Date: Thu, 7 Dec 2006 00:20:54 +0200
First of all, gluax is a layer above the Lua C/API, which I
personally find too low level for most binding usage. Don't take me
wrong, it's perfect for really what it's for: embedding and
extending, it gives all the keys. But.. binding code made in pure Lua/
C API is not very readable. Gluax does things s.a. calculating the
number of return values pushed automatically; thus eliminating little
potential coding errors, and making bindings generally more pleasant
to write.
All one needs to use gluax is gluax.h and gluax.c (but more of that
some other time?).
The threading issue is but a little part of gluax features. It has a
C-side queue for this case, with the following functions:
void _glua_queue_attach( lua_State *L,
struct s_Glua_Queue** qref,
int closure_argn,
uint /*enum e_Glua_QueuePolicy*/ policy );
bool_int _glua_queue_add( struct s_Glua_Queue* queue,
void* p,
uint /*size_t*/ bytes,
uint style );
bool_int _glua_queue_run( lua_State *L,
struct s_Glua_Queue* queue );
#define glua_queue_detach( qref ) \
_glua_queue_attach( _lua_, qref, 0, 0 )
#define glua_queue_run(q) _glua_queue_run( _lua_, (q) )
Attach is called to set a callback, given a closure on the Lua stack.
Detach removes such binding.
Add takes no lua_State parameter, and can thus be called from other
threads; it collects the data provided to it, into a FIFO buffer (or
queue) which is emptied when the lua_State has time to go poll it.
Run reduces the FIFO, and calls the closure associated with the data
queue to actually handle the data, which was provided from the alien
thread, which in turn would come from an interrupt routine.
The 'run' call needs of course be actively polled by the lua_State.
There is no concept of asynchronous interrupts in Lua, but the queue
poll concept could easily be placed within a coroutine of its own,
thus suiting the Lua ideology rather nicely.
What I did, is have the SDL event loop call 'run' if no SDL events
were incoming. This keeps GUI responsiveness first, but handles the
interrupt-provided data flow very fluently, as well. In fact, I was
astound when running the SDL_Mixer demos. They're visually showing
music waveforms, while playing the sounds, in all Lua, in real time.
This requires about a 1GHz processor, with slower ones the sw works
fine but some of the samples are lost (that's why the queing has
parameters for allowing loss of data).
Below is the full API section dealing with these features of gluax.
It's only about 3% of all gluax API has to offer (60 lines out of
1800). (( This must be the first time I'm implying having lots of
lines would actually be good... :))
- Asko
/*--- Asynchronous callbacks -----------*/
//
// Async callbacks (those provided in a separate thread, s.a.
SDL_Mixer events)
// need to be passed to Lua through a queue. Lua state may not be
manipulated
// by the alien threads.
struct s_Glua_Queue; // opaque implementation details
enum e_Glua_QueuePolicy
{
// Note: don't change the values, they're part of module ABI!
GLUA_QUEUE_KEEP_ALL= 0, // default: keep all data (nothing lost)
GLUA_QUEUE_KEEP_FIRST= 1, // keep first data (lose later until
buffer read)
GLUA_QUEUE_KEEP_LAST= 2, // keep last data (lose earlier, non-
read data)
};
// Array style values are the same as SDL_Mixer's Uint16 'audio_format':
//
#define GLUA_QUEUE_ARRAY_SIGNED (0x8000)
//#define GLUA_QUEUE_ARRAY_TWISTED (0x1000) // MSB/LBS twist
#if (defined PLATFORM_WIN32) || (defined PLATFORM_WINCE)
#define GLUA_QUEUE_ARRAY_MESSEDUP (0x0800) // special flag to fix
an SDL_Mixer bug?
#endif
#define GLUA_QUEUE_ARRAY_S8 (8 | GLUA_QUEUE_ARRAY_SIGNED)
#define GLUA_QUEUE_ARRAY_U8 8
#define GLUA_QUEUE_ARRAY_S16 (16 | GLUA_QUEUE_ARRAY_SIGNED)
#define GLUA_QUEUE_ARRAY_U16 16
#define GLUA_QUEUE_ARRAY_S32 (32 | GLUA_QUEUE_ARRAY_SIGNED)
#define GLUA_QUEUE_ARRAY_U32 32
void _glua_queue_attach( lua_State *L,
struct s_Glua_Queue** qref,
int closure_argn,
uint /*enum e_Glua_QueuePolicy*/ policy );
bool_int _glua_queue_add( struct s_Glua_Queue* queue,
void* p,
uint /*size_t*/ bytes,
uint style );
bool_int _glua_queue_run( lua_State *L,
struct s_Glua_Queue* queue );
#define glua_queue_attach( qref, argn, policy ) \
_glua_queue_attach( _lua_, qref, argn, policy )
#define glua_queue_detach( qref ) \
_glua_queue_attach( _lua_, qref, 0, 0 )
#define glua_queue_add( q ) \
_glua_queue_add( q, NULL, 0, 0 )
#define glua_queue_add_int( q, v ) \
_glua_queue_add( q, &(v), sizeof(int), GLUA_QUEUE_ARRAY_S32 )
#define glua_queue_add_intarray _glua_queue_add
#define glua_queue_run(q) _glua_queue_run( _lua_, (q) )
Sam Roberts kirjoitti 6.12.2006 kello 21.22:
On Wed, Dec 06, 2006 at 12:57:48AM +0200, Asko Kauppi wrote:
Use a completely separate dispatch system, to also cover thread
issues.
Cover how?
Callbacks are often thrown from threads other than the one
^^^^^^^^^ errors?
where Lua state is running.
And what does gluax do when this occurs?
gluax has such. Lua/C API does not.
I can't even figure out what gluax is for... it appears to be a
duplicate of the lua c api, but minus the state parameter.
Sam
- References:
- suggestion on error returns, especially in callbacks from C?, Sam Roberts
- Re: suggestion on error returns, especially in callbacks from C?, Roberto Ierusalimschy
- Re: suggestion on error returns, especially in callbacks from C?, Roberto Ierusalimschy
- Re: suggestion on error returns, especially in callbacks from C?, Sam Roberts
- Re: suggestion on error returns, especially in callbacks from C?, Asko Kauppi
- Re: suggestion on error returns, especially in callbacks from C?, Sam Roberts