ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/evthread.C
Revision: 1.19
Committed: Sat Nov 17 23:40:03 2018 UTC (5 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.18: +1 -0 lines
Log Message:
copyright update 2018

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.19 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
5 root 1.18 * Copyright (©) 2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
6 root 1.17 *
7 root 1.9 * Deliantra is free software: you can redistribute it and/or modify it under
8     * the terms of the Affero GNU General Public License as published by the
9     * Free Software Foundation, either version 3 of the License, or (at your
10     * option) any later version.
11 root 1.17 *
12 root 1.1 * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16 root 1.17 *
17 root 1.9 * You should have received a copy of the Affero GNU General Public License
18     * and the GNU General Public License along with this program. If not, see
19     * <http://www.gnu.org/licenses/>.
20 root 1.17 *
21 root 1.1 * The authors can be reached via e-mail to <support@deliantra.net>
22     */
23    
24     #include "global.h"
25     #include "evthread.h"
26     #include "cfperl.h"
27    
28     thread evthread;
29     static ev_loop *loop;
30    
31 root 1.12 /////////////////////////////////////////////////////////////////////////////
32 root 1.1
33 root 1.4 ev_async tick_watcher;
34     EV_ATOMIC_T coroapi::cede_pending;
35    
36 root 1.1 static ev_periodic cede_watcher;
37    
38     // it is a bit silly to have to use a mutex, but contention
39     // is basically non-existant, favouring good mutex implementations.
40     static SMUTEX (evthread_mutex);
41     static NV next_tick;
42    
43     NV get_next_tick ()
44     {
45     SMUTEX_LOCK (evthread_mutex);
46     NV retval = next_tick;
47     SMUTEX_UNLOCK (evthread_mutex);
48     return retval;
49     }
50    
51     static void
52     cede_cb (EV_P_ ev_periodic *w, int revents)
53     {
54 root 1.12 SMUTEX_LOCK (evthread_mutex);
55     next_tick = w->at;
56     SMUTEX_UNLOCK (evthread_mutex);
57 root 1.1
58 root 1.12 coroapi::cede_pending = 1;
59 root 1.1
60 root 1.12 ev_async_send (EV_DEFAULT_UC, &tick_watcher);
61 root 1.1 }
62    
63     static void
64     tick_cb (EV_P_ ev_async *w, int revents)
65     {
66     cfperl_tick ();
67     }
68    
69 root 1.4 /////////////////////////////////////////////////////////////////////////////
70    
71 root 1.12 static SMUTEX(cb_mutex);
72     static SCOND(cb_done);
73    
74 root 1.4 static ev_async async_watcher;
75 root 1.12 static ev_io aio_watcher;
76 root 1.4
77     static void
78 root 1.12 async_cb (EV_P_ ev_async *w, int revents)
79 root 1.4 {
80     CALL_BEGIN (0);
81     CALL_CALL ("IO::AIO::poll_cb", G_SCALAR);
82 root 1.12 IV reqs = POPi;
83     CALL_END;
84 root 1.4
85 root 1.12 SMUTEX_LOCK (cb_mutex);
86     SCOND_SIGNAL (cb_done);
87     SMUTEX_UNLOCK (cb_mutex);
88 root 1.4 }
89    
90     static void
91 root 1.12 aio_cb (EV_P_ ev_io *w, int revents)
92 root 1.4 {
93 root 1.12 ev_async_send (EV_DEFAULT_UC, &async_watcher);
94 root 1.4
95 root 1.12 coroapi::cede_pending = 1; // to decrease latency
96 root 1.4
97 root 1.12 SCOND_WAIT (cb_done, cb_mutex);
98 root 1.4 }
99    
100     /////////////////////////////////////////////////////////////////////////////
101    
102 root 1.1 static void *
103     evthread_proc (void *arg)
104     {
105 root 1.12 SMUTEX_LOCK (cb_mutex);
106    
107 root 1.13 ev_run (loop, 0);
108 root 1.1
109     return 0;
110     }
111    
112 root 1.4 void evthread_start (int aiofd)
113 root 1.1 {
114     I_EV_API ("evthread");
115 root 1.3
116 root 1.4 // main loop
117 root 1.3 ev_async_init (&tick_watcher, tick_cb);
118     ev_set_priority (&tick_watcher, 1);
119 root 1.4 ev_async_start (EV_DEFAULT_UC, &tick_watcher);
120    
121     ev_async_init (&async_watcher, async_cb);
122     ev_set_priority (&async_watcher, 1);
123     ev_async_start (EV_DEFAULT_UC, &async_watcher);
124    
125 root 1.14 // secondary loop, we use select/poll as epoll has very
126     // bad timing characteristics and we only watch a single low fd.
127     loop = ev_loop_new (EVBACKEND_SELECT);
128 root 1.4
129 root 1.12 ev_periodic_init (&cede_watcher, cede_cb, 0, TICK, 0);
130 root 1.4 ev_periodic_start (loop, &cede_watcher);
131    
132 root 1.12 ev_io_init (&aio_watcher, aio_cb, aiofd, EV_READ);
133     ev_io_start (loop, &aio_watcher);
134 root 1.3
135 root 1.1 evthread.start (evthread_proc);
136     }
137    
138    
139