ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/evthread.C
Revision: 1.18
Committed: Wed Nov 16 23:42:02 2016 UTC (7 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.17: +1 -1 lines
Log Message:
copyright update 2016

File Contents

# User Rev Content
1 root 1.1 /*
2     * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.17 *
4 root 1.18 * Copyright (©) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.17 *
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.17 *
11 root 1.1 * 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 root 1.17 *
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.17 *
20 root 1.1 * 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.12 /////////////////////////////////////////////////////////////////////////////
31 root 1.1
32 root 1.4 ev_async tick_watcher;
33     EV_ATOMIC_T coroapi::cede_pending;
34    
35 root 1.1 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 root 1.12 SMUTEX_LOCK (evthread_mutex);
54     next_tick = w->at;
55     SMUTEX_UNLOCK (evthread_mutex);
56 root 1.1
57 root 1.12 coroapi::cede_pending = 1;
58 root 1.1
59 root 1.12 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
60 root 1.1 }
61    
62     static void
63     tick_cb (EV_P_ ev_async *w, int revents)
64     {
65     cfperl_tick ();
66     }
67    
68 root 1.4 /////////////////////////////////////////////////////////////////////////////
69    
70 root 1.12 static SMUTEX(cb_mutex);
71     static SCOND(cb_done);
72    
73 root 1.4 static ev_async async_watcher;
74 root 1.12 static ev_io aio_watcher;
75 root 1.4
76     static void
77 root 1.12 async_cb (EV_P_ ev_async *w, int revents)
78 root 1.4 {
79     CALL_BEGIN (0);
80     CALL_CALL ("IO::AIO::poll_cb", G_SCALAR);
81 root 1.12 IV reqs = POPi;
82     CALL_END;
83 root 1.4
84 root 1.12 SMUTEX_LOCK (cb_mutex);
85     SCOND_SIGNAL (cb_done);
86     SMUTEX_UNLOCK (cb_mutex);
87 root 1.4 }
88    
89     static void
90 root 1.12 aio_cb (EV_P_ ev_io *w, int revents)
91 root 1.4 {
92 root 1.12 ev_async_send (EV_DEFAULT_UC, &async_watcher);
93 root 1.4
94 root 1.12 coroapi::cede_pending = 1; // to decrease latency
95 root 1.4
96 root 1.12 SCOND_WAIT (cb_done, cb_mutex);
97 root 1.4 }
98    
99     /////////////////////////////////////////////////////////////////////////////
100    
101 root 1.1 static void *
102     evthread_proc (void *arg)
103     {
104 root 1.12 SMUTEX_LOCK (cb_mutex);
105    
106 root 1.13 ev_run (loop, 0);
107 root 1.1
108     return 0;
109     }
110    
111 root 1.4 void evthread_start (int aiofd)
112 root 1.1 {
113     I_EV_API ("evthread");
114 root 1.3
115 root 1.4 // main loop
116 root 1.3 ev_async_init (&tick_watcher, tick_cb);
117     ev_set_priority (&tick_watcher, 1);
118 root 1.4 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 root 1.14 // 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 root 1.4
128 root 1.12 ev_periodic_init (&cede_watcher, cede_cb, 0, TICK, 0);
129 root 1.4 ev_periodic_start (loop, &cede_watcher);
130    
131 root 1.12 ev_io_init (&aio_watcher, aio_cb, aiofd, EV_READ);
132     ev_io_start (loop, &aio_watcher);
133 root 1.3
134 root 1.1 evthread.start (evthread_proc);
135     }
136    
137    
138