ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV-Glib/Glib.xs
Revision: 1.5
Committed: Sat Dec 8 03:40:32 2007 UTC (16 years, 5 months ago) by root
Branch: MAIN
Changes since 1.4: +23 -5 lines
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_P_ ev_timer *w, int revents)
35 {
36 /* nop */
37 }
38
39 static void
40 io_cb (EV_P_ 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 check_cb (EV_P_ ev_check *w, int revents)
51 {
52 struct econtext *ctx = (struct econtext *)(((char *)w) - offsetof (struct econtext, cw));
53
54 if (ctx->nfd >= 0)
55 {
56 int i;
57
58 for (i = 0; i < ctx->nfd; ++i)
59 ev_io_stop (EV_A_ ctx->iow + i);
60
61 if (ev_is_active (&ctx->tw))
62 ev_timer_stop (EV_A_ &ctx->tw);
63
64 g_main_context_check (ctx->gc, ctx->maxpri, ctx->pfd, ctx->nfd);
65
66 ctx->nfd = -1;
67 }
68 }
69
70 static void
71 prepare_cb (EV_P_ ev_prepare *w, int revents)
72 {
73 struct econtext *ctx = (struct econtext *)(((char *)w) - offsetof (struct econtext, pw));
74 gint timeout;
75 int i;
76
77 check_cb (EV_A_ &ctx->cw, 0);
78
79 g_main_context_dispatch (ctx->gc);
80
81 g_main_context_prepare (ctx->gc, &ctx->maxpri);
82
83 while (ctx->afd < (ctx->nfd = g_main_context_query (
84 ctx->gc,
85 ctx->maxpri,
86 &timeout,
87 ctx->pfd,
88 ctx->afd))
89 )
90 {
91 free (ctx->pfd);
92 free (ctx->iow);
93
94 ctx->afd = 1;
95 while (ctx->afd < ctx->nfd)
96 ctx->afd <<= 1;
97
98 ctx->pfd = malloc (ctx->afd * sizeof (GPollFD));
99 ctx->iow = malloc (ctx->afd * sizeof (ev_io));
100 }
101
102 for (i = 0; i < ctx->nfd; ++i)
103 {
104 GPollFD *pfd = ctx->pfd + i;
105 ev_io *iow = ctx->iow + i;
106
107 pfd->revents = 0;
108
109 ev_io_init (
110 iow,
111 io_cb,
112 pfd->fd,
113 (pfd->events & G_IO_IN ? EV_READ : 0)
114 | (pfd->events & G_IO_OUT ? EV_WRITE : 0)
115 );
116 iow->data = (void *)pfd;
117 ev_set_priority (&ctx->cw, ev_priority (w) + 1);
118 ev_io_start (EV_A_ iow);
119 }
120
121 if (timeout >= 0)
122 {
123 ev_timer_set (&ctx->tw, timeout * 1e-3, 0.);
124 ev_timer_start (EV_A_ &ctx->tw);
125 }
126 }
127
128 static struct econtext default_context;
129
130 MODULE = EV::Glib PACKAGE = EV::Glib
131
132 PROTOTYPES: ENABLE
133
134 BOOT:
135 {
136 I_EV_API ("EV::Glib");
137 }
138
139 long
140 install (SV *context)
141 CODE:
142 {
143 GMainContext *gc = get_gcontext (context);
144 struct econtext *ctx = &default_context;
145
146 ctx->gc = g_main_context_ref (gc);
147 ctx->nfd = -1;
148 ctx->afd = 0;
149 ctx->iow = 0;
150 ctx->pfd = 0;
151
152 ev_prepare_init (&ctx->pw, prepare_cb);
153 ev_prepare_start (EV_DEFAULT_ &ctx->pw);
154
155 ev_check_init (&ctx->cw, check_cb);
156 ev_set_priority (&ctx->cw, EV_MAXPRI - 1);
157 ev_check_start (EV_DEFAULT_ &ctx->cw);
158
159 ev_init (&ctx->tw, timer_cb);
160 ev_set_priority (&ctx->tw, EV_MINPRI);
161 }
162 OUTPUT:
163 RETVAL
164
165
166