ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/evthread.C
Revision: 1.11
Committed: Fri Mar 26 01:04:45 2010 UTC (14 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.10: +1 -1 lines
Log Message:
update copyright for up to 2010

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3     *
4 root 1.11 * Copyright (©) 2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.1 *
6 root 1.9 * Deliantra is free software: you can redistribute it and/or modify it under
7     * the terms of the Affero GNU General Public License as published by the
8     * Free Software Foundation, either version 3 of the License, or (at your
9     * option) any later version.
10 root 1.1 *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16 root 1.9 * You should have received a copy of the Affero GNU General Public License
17     * and the GNU General Public License along with this program. If not, see
18     * <http://www.gnu.org/licenses/>.
19 root 1.1 *
20     * The authors can be reached via e-mail to <support@deliantra.net>
21     */
22    
23     #include "global.h"
24     #include "evthread.h"
25     #include "cfperl.h"
26    
27     thread evthread;
28     static ev_loop *loop;
29    
30 root 1.2 #define TICK_CYCLES 4
31 root 1.1
32 root 1.4 // the tick watcher is activated every TICK_CYCLES
33     ev_async tick_watcher;
34     EV_ATOMIC_T coroapi::cede_pending;
35    
36 root 1.1 // the ticker runs TICK_CYCLES times as fast as the main server tick
37     static ev_periodic cede_watcher;
38    
39 root 1.4 /////////////////////////////////////////////////////////////////////////////
40 root 1.1
41     // it is a bit silly to have to use a mutex, but contention
42     // is basically non-existant, favouring good mutex implementations.
43     static SMUTEX (evthread_mutex);
44     static NV next_tick;
45    
46     NV get_next_tick ()
47     {
48     SMUTEX_LOCK (evthread_mutex);
49     NV retval = next_tick;
50     SMUTEX_UNLOCK (evthread_mutex);
51     return retval;
52     }
53    
54     static void
55     cede_cb (EV_P_ ev_periodic *w, int revents)
56     {
57     static int cycle = 0;
58    
59     if (++cycle == TICK_CYCLES)
60     {
61     cycle = 0;
62    
63     SMUTEX_LOCK (evthread_mutex);
64     next_tick = w->at + TICK / TICK_CYCLES * (TICK_CYCLES - 1);
65     SMUTEX_UNLOCK (evthread_mutex);
66    
67 root 1.4 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
68 root 1.1 }
69    
70     coroapi::cede_pending = 1;
71     }
72    
73     static void
74     tick_cb (EV_P_ ev_async *w, int revents)
75     {
76     cfperl_tick ();
77     }
78    
79 root 1.4 /////////////////////////////////////////////////////////////////////////////
80    
81     static ev_async async_watcher;
82     static ev_io aio1_watcher;
83     static ev_idle aio2_watcher;
84     static EV_ATOMIC_T aio_pending;
85    
86     static void
87     aio2_cb (EV_P_ ev_idle *w, int revents)
88     {
89 root 1.7 IV reqs;
90    
91 root 1.4 CALL_BEGIN (0);
92     CALL_CALL ("IO::AIO::poll_cb", G_SCALAR);
93    
94 root 1.7 reqs = POPi;
95     if (count > 0 && reqs < 0)
96 root 1.4 ev_idle_start (EV_A, w);
97     else
98     ev_idle_stop (EV_A, w);
99    
100     CALL_END;
101     }
102    
103     static void
104     async_cb (EV_P_ ev_async *w, int revents)
105     {
106     aio2_cb (EV_A, &aio2_watcher, 0);
107     }
108    
109     static void
110     aio1_cb (EV_P_ ev_io *w, int revents)
111     {
112 root 1.8 char dummy[9];
113 root 1.4
114 root 1.8 if (read (w->fd, dummy, sizeof (dummy)) > 0)
115 root 1.4 {
116     ev_async_send (EV_DEFAULT_UC, &async_watcher);
117     coroapi::cede_pending = 1;
118     }
119     }
120    
121     /////////////////////////////////////////////////////////////////////////////
122    
123 root 1.1 static void *
124     evthread_proc (void *arg)
125     {
126     ev_loop (loop, 0);
127    
128     return 0;
129     }
130    
131 root 1.4 void evthread_start (int aiofd)
132 root 1.1 {
133     I_EV_API ("evthread");
134 root 1.3
135 root 1.4 // main loop
136 root 1.3 ev_async_init (&tick_watcher, tick_cb);
137     ev_set_priority (&tick_watcher, 1);
138 root 1.4 ev_async_start (EV_DEFAULT_UC, &tick_watcher);
139    
140     ev_async_init (&async_watcher, async_cb);
141     ev_set_priority (&async_watcher, 1);
142     ev_async_start (EV_DEFAULT_UC, &async_watcher);
143    
144     ev_idle_init (&aio2_watcher, aio2_cb);
145    
146     // secondary loop
147     loop = ev_loop_new (0);
148    
149     ev_periodic_init (&cede_watcher, cede_cb, 0, TICK / TICK_CYCLES, 0);
150     ev_periodic_start (loop, &cede_watcher);
151    
152     ev_io_init (&aio1_watcher, aio1_cb, aiofd, EV_READ);
153     ev_io_start (loop, &aio1_watcher);
154 root 1.3
155 root 1.1 evthread.start (evthread_proc);
156     }
157    
158    
159