ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/evthread.C
Revision: 1.8
Committed: Thu Jul 16 21:42:56 2009 UTC (14 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_80, rel-2_79
Changes since 1.7: +2 -2 lines
Log Message:
*** empty log message ***

File Contents

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