ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/EV-Glib/Glib.xs
Revision: 1.2
Committed: Sat Dec 8 02:59:43 2007 UTC (16 years, 10 months ago) by root
Branch: MAIN
Changes since 1.1: +11 -10 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 cleanup (EV_P_ struct econtext *ctx)
51 {
52 int i;
53
54 for (i = 0; i < ctx->nfd; ++i)
55 {
56 ev_ref (EV_A);
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 (EV_A);
65 ev_timer_stop (EV_A_ &ctx->tw);
66 }
67 }
68
69 static void
70 prepare_cb (EV_P_ 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 (EV_A_ 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 (EV_A);
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 ev_unref (EV_A);
123 }
124 }
125
126 static void
127 check_cb (EV_P_ ev_check *w, int revents)
128 {
129 struct econtext *ctx = (struct econtext *)(((char *)w) - offsetof (struct econtext, cw));
130
131 cleanup (EV_A_ ctx);
132
133 g_main_context_check (ctx->gc, ctx->maxpri, ctx->pfd, ctx->nfd);
134 g_main_context_dispatch (ctx->gc);
135 }
136
137 static struct econtext default_context;
138
139 MODULE = EV::Glib PACKAGE = EV::Glib
140
141 PROTOTYPES: ENABLE
142
143 BOOT:
144 {
145 I_EV_API ("EV::Glib");
146 }
147
148 long
149 install (SV *context)
150 CODE:
151 {
152 GMainContext *gc = get_gcontext (context);
153 struct econtext *ctx = &default_context;
154
155 ctx->gc = g_main_context_ref (gc);
156 ctx->nfd = 0;
157 ctx->afd = 0;
158 ctx->iow = 0;
159 ctx->pfd = 0;
160
161 ev_prepare_init (&ctx->pw, prepare_cb); ev_prepare_start (EV_DEFAULT_ &ctx->pw);
162 ev_check_init (&ctx->cw, check_cb); ev_check_start (EV_DEFAULT_ &ctx->cw);
163 ev_init (&ctx->tw, timer_cb); ev_set_priority (&ctx->tw, EV_MINPRI);
164 }
165 OUTPUT:
166 RETVAL
167
168
169