ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV-Glib/Glib.xs
Revision: 1.1
Committed: Sat Dec 8 02:49:42 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
Log Message:
*** empty log message ***

File Contents

# Content
1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include <stddef.h>
6
7 #include <glib.h>
8 #include "EVAPI.h"
9
10 static GMainContext *
11 get_gcontext (SV *context)
12 {
13 if (!SvOK (context))
14 return g_main_context_default ();
15
16 croak ("only the default context is currently supported.");
17 }
18
19 struct econtext
20 {
21 GPollFD *pfd;
22 ev_io *iow;
23 int nfd, afd;
24 gint maxpri;
25
26 ev_prepare pw;
27 ev_check cw;
28 ev_timer tw;
29
30 GMainContext *gc;
31 };
32
33 static void
34 timer_cb (ev_timer *w, int revents)
35 {
36 /* nop */
37 }
38
39 static void
40 io_cb (ev_io *w, int revents)
41 {
42 GPollFD *pfd = (GPollFD *)w->data;
43
44 pfd->revents |= pfd->events &
45 ((revents & EV_READ ? G_IO_IN : 0)
46 | (revents & EV_READ ? G_IO_OUT : 0));
47 }
48
49 static void
50 cleanup (struct econtext *ctx)
51 {
52 int i;
53
54 for (i = 0; i < ctx->nfd; ++i)
55 {
56 ev_ref ();
57 ev_io_stop (EV_A_ ctx->iow + i);
58 }
59
60 ctx->nfd = 0;
61
62 if (ev_is_active (&ctx->tw))
63 {
64 ev_ref ();
65 ev_timer_stop (EV_A_ &ctx->tw);
66 }
67 }
68
69 static void
70 prepare_cb (ev_prepare *w, int revents)
71 {
72 struct econtext *ctx = (struct econtext *)(((char *)w) - offsetof (struct econtext, pw));
73 gint timeout;
74 int n;
75
76 cleanup (ctx);
77
78 g_main_context_prepare (ctx->gc, &ctx->maxpri);
79
80 while (ctx->afd < (ctx->nfd = g_main_context_query (
81 ctx->gc,
82 ctx->maxpri,
83 &timeout,
84 ctx->pfd,
85 ctx->afd))
86 )
87 {
88 free (ctx->pfd);
89 free (ctx->iow);
90
91 ctx->afd = 1;
92 while (ctx->afd < ctx->nfd)
93 ctx->afd <<= 1;
94
95 ctx->pfd = malloc (ctx->afd * sizeof (GPollFD));
96 ctx->iow = malloc (ctx->afd * sizeof (ev_io));
97 }
98
99 for (n = 0; n < ctx->nfd; ++n)
100 {
101 GPollFD *pfd = ctx->pfd + n;
102 ev_io *iow = ctx->iow + n;
103
104 pfd->revents = 0;
105
106 ev_io_init (
107 iow,
108 io_cb,
109 pfd->fd,
110 (pfd->events & G_IO_IN ? EV_READ : 0)
111 | (pfd->events & G_IO_OUT ? EV_WRITE : 0)
112 );
113 iow->data = (void *)pfd;
114 ev_io_start (EV_A_ iow);
115 ev_unref ();
116 }
117
118 if (timeout >= 0)
119 {
120 ev_timer_set (&ctx->tw, timeout * 1e-3, 0.);
121 ev_timer_start (EV_A_ &ctx->tw);
122 }
123 }
124
125 static void
126 check_cb (ev_check *w, int revents)
127 {
128 struct econtext *ctx = (struct econtext *)(((char *)w) - offsetof (struct econtext, cw));
129
130 cleanup (ctx);
131
132 g_main_context_check (ctx->gc, ctx->maxpri, ctx->pfd, ctx->nfd);
133 g_main_context_dispatch (ctx->gc);
134 }
135
136 static struct econtext default_context;
137
138 MODULE = EV::Glib PACKAGE = EV::Glib
139
140 PROTOTYPES: ENABLE
141
142 BOOT:
143 {
144 I_EV_API ("EV::Glib");
145 }
146
147 long
148 install (SV *context)
149 CODE:
150 {
151 GMainContext *gc = get_gcontext (context);
152 struct econtext *ctx = &default_context;
153
154 ctx->gc = g_main_context_ref (gc);
155 ctx->nfd = 0;
156 ctx->afd = 0;
157 ctx->iow = 0;
158 ctx->pfd = 0;
159
160 ev_prepare_init (&ctx->pw, prepare_cb); ev_prepare_start (EV_DEFAULT_ &ctx->pw);
161 ev_check_init (&ctx->cw, check_cb); ev_check_start (EV_DEFAULT_ &ctx->cw);
162 ev_init (&ctx->tw, timer_cb); ev_set_priority (&ctx->tw, EV_MINPRI);
163 }
164 OUTPUT:
165 RETVAL
166
167
168