ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/evthread.C
Revision: 1.14
Committed: Sun Oct 31 22:26:56 2010 UTC (13 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.13: +3 -2 lines
Log Message:
*** empty log message ***

File Contents

# Content
1 /*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 *
4 * Copyright (©) 2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 *
6 * 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 *
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 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 *
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 /////////////////////////////////////////////////////////////////////////////
31
32 ev_async tick_watcher;
33 EV_ATOMIC_T coroapi::cede_pending;
34
35 static ev_periodic cede_watcher;
36
37 // it is a bit silly to have to use a mutex, but contention
38 // is basically non-existant, favouring good mutex implementations.
39 static SMUTEX (evthread_mutex);
40 static NV next_tick;
41
42 NV get_next_tick ()
43 {
44 SMUTEX_LOCK (evthread_mutex);
45 NV retval = next_tick;
46 SMUTEX_UNLOCK (evthread_mutex);
47 return retval;
48 }
49
50 static void
51 cede_cb (EV_P_ ev_periodic *w, int revents)
52 {
53 SMUTEX_LOCK (evthread_mutex);
54 next_tick = w->at;
55 SMUTEX_UNLOCK (evthread_mutex);
56
57 coroapi::cede_pending = 1;
58
59 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
60 }
61
62 static void
63 tick_cb (EV_P_ ev_async *w, int revents)
64 {
65 cfperl_tick ();
66 }
67
68 /////////////////////////////////////////////////////////////////////////////
69
70 static SMUTEX(cb_mutex);
71 static SCOND(cb_done);
72
73 static ev_async async_watcher;
74 static ev_io aio_watcher;
75
76 static void
77 async_cb (EV_P_ ev_async *w, int revents)
78 {
79 CALL_BEGIN (0);
80 CALL_CALL ("IO::AIO::poll_cb", G_SCALAR);
81 IV reqs = POPi;
82 CALL_END;
83
84 SMUTEX_LOCK (cb_mutex);
85 SCOND_SIGNAL (cb_done);
86 SMUTEX_UNLOCK (cb_mutex);
87 }
88
89 static void
90 aio_cb (EV_P_ ev_io *w, int revents)
91 {
92 ev_async_send (EV_DEFAULT_UC, &async_watcher);
93
94 coroapi::cede_pending = 1; // to decrease latency
95
96 SCOND_WAIT (cb_done, cb_mutex);
97 }
98
99 /////////////////////////////////////////////////////////////////////////////
100
101 static void *
102 evthread_proc (void *arg)
103 {
104 SMUTEX_LOCK (cb_mutex);
105
106 ev_run (loop, 0);
107
108 return 0;
109 }
110
111 void evthread_start (int aiofd)
112 {
113 I_EV_API ("evthread");
114
115 // main loop
116 ev_async_init (&tick_watcher, tick_cb);
117 ev_set_priority (&tick_watcher, 1);
118 ev_async_start (EV_DEFAULT_UC, &tick_watcher);
119
120 ev_async_init (&async_watcher, async_cb);
121 ev_set_priority (&async_watcher, 1);
122 ev_async_start (EV_DEFAULT_UC, &async_watcher);
123
124 // secondary loop, we use select/poll as epoll has very
125 // bad timing characteristics and we only watch a single low fd.
126 loop = ev_loop_new (EVBACKEND_SELECT);
127
128 ev_periodic_init (&cede_watcher, cede_cb, 0, TICK, 0);
129 ev_periodic_start (loop, &cede_watcher);
130
131 ev_io_init (&aio_watcher, aio_cb, aiofd, EV_READ);
132 ev_io_start (loop, &aio_watcher);
133
134 evthread.start (evthread_proc);
135 }
136
137
138