In your applications, you may need to manage other input/output channels than an Ivy bus: a serial driver, the channels defined by a graphical toolkit, or simply stdin and stdout. The same applies for timers. You can either manage those channels or timers from the Ivy main loop, or instead use the main loop provided by another library.
You can get a channel to be managed from the Ivy main loop by using functions
IvyChannelSetUp
and IvyChannelClose
.
Channel IvyChannelSetUp (HANDLE fd,
void* data,
ChannelHandleDelete handle_delete,
ChannelHandleRead handle_read);
ensures that function handle_read
is called whenever data is read on file
descriptor fd
, and function handle_delete
whenever fd
is
closed, and
void IvyChannelClose (Channel ch);
terminates the management of channel ch
.
In what precedes, Channel
is an opaque type defined by the Ivy C library, data
is a pointer that will be passed to functions handle_read
and handle_delete
. It can be defined at will by users.
The types HANDLE, ChannelHandleDelete and
ChannelHandleRead are as follows:
Unix:
typedef int HANDLE;
Windows:
typedef SOCKET HANDLE;
typedef void (*ChannelHandleDelete)(void *data);
typedef void (*ChannelHandleRead)(Channel ch, HANDLE fd, void* data);
You can get a function to be repeatedly called by using function
TimerRepeatAfter
:
TimerId TimerRepeatAfter (int nbticks, long delay, TimerCb handle_timer, void* data);
ensures that function handle_timer
is called nbticks
times at
intervals of delay
seconds, thus creating a timer.
void TimerModify (TimerId id, long delay);
changes the delay used for timer id
.
void TimerRemove (TimerId id);
deletes timer id
, thus stopping it.
In what precedes, data
is passed to handle_timer
every time it is
called. delay
is expressed in milliseconds.
If nbticks
is set to TIMER_LOOP
, then handle_timer
will
be called forever. TimerCb
is as follows:
typedef void (*TimerCb)(TimerId id, void *data, unsigned long delta);
You can decide to use the main loop from another toolkit such as the X Toolkit or the Tk toolkit. If you do that, you'll have to define three functions that Ivy will use to get its own channels managed by the other toolkit. The three following global variables should be defined:
ChannelInit channel_init;
ChannelSetUp channel_setup;
ChannelClose channel_close;
They should point to functions that respectively:
The types ChannelInit
, ChannelSetUp
and ChannelClose
are defined
as follows:
typedef void (*ChannelInit)(void);
typedef Channel (*ChannelSetUp)(
HANDLE fd,
void *data,
ChannelHandleDelete handle_delete,
ChannelHandleRead handle_read);
typedef void (*ChannelClose)( Channel channel );
In order to implement the three previous functions, you will need to define the
hidden type struct _channel
(the type Channel
is defined as struct _channel*
). Use it to store the data provided by the other toolkit.
In order to override the default definition of the three previous variables, you will need:
ivyloop.o
with the file
that contains your definitions