Pol  Revision:cb584c9
tasks.cpp
Go to the documentation of this file.
1 
12 #include "tasks.h"
13 
14 #include <time.h>
15 
16 #include "../bscript/berror.h"
17 #include "../bscript/escriptv.h"
18 #include "../clib/logfacility.h"
19 #include "../plib/systemstate.h"
20 #include "cmbtcfg.h"
21 #include "gameclck.h"
23 #include "globals/settings.h"
24 #include "globals/state.h"
25 #include "globals/uvars.h"
26 #include "mobile/charactr.h"
27 #include "polclock.h"
28 #include "polsig.h"
29 #include "profile.h"
30 #include "realms/realm.h"
31 #include "uworld.h"
32 #include "vital.h"
33 
34 #ifdef _MSC_VER
35 #pragma warning( \
36  disable : 4127 ) // conditional expression is constant (needed because of TICK_PROFILEVAR)
37 #endif
38 
39 namespace Pol
40 {
41 namespace Core
42 {
44 {
45  THREAD_CHECKPOINT( tasks, 400 );
46  time_t now = poltime();
47  gameclock_t now_gameclock = read_gameclock();
48  THREAD_CHECKPOINT( tasks, 401 );
49 
50  unsigned empty_zones = 0;
51  unsigned nonempty_zones = 0;
52 
53  unsigned wgridx, wgridy;
54 
55  auto stat_regen = [&now_gameclock, &now]( Mobile::Character* chr ) {
56  THREAD_CHECKPOINT( tasks, 402 );
57 
58  if ( chr->has_lightoverride() )
59  {
60  auto light_until = chr->lightoverride_until();
61  if ( light_until < now_gameclock && light_until != ~0u )
62  {
63  chr->lightoverride( -1 );
64  chr->lightoverride_until( 0 );
65  THREAD_CHECKPOINT( tasks, 403 );
66  chr->check_region_changes();
67  }
68  }
69 
70  if ( chr->has_dblclick_wait() )
71  {
72  if ( chr->dblclick_wait() < now_gameclock )
73  chr->dblclick_wait( 0 );
74  }
75  if ( chr->has_disable_skills_until() )
76  {
77  if ( chr->disable_skills_until() < now )
78  chr->disable_skills_until( 0 );
79  }
80  THREAD_CHECKPOINT( tasks, 404 );
81 
82  // If in warmode, don't regenerate.
83  // If regeneration is currently disabled, don't do it either.
84  if ( ( chr->warmode() && settingsManager.combat_config.warmode_inhibits_regen ) ||
85  ( now <= chr->disable_regeneration_until ) )
86  {
87  return;
88  }
89 
90  THREAD_CHECKPOINT( tasks, 405 );
91  for ( const Vital* pVital = FindVital( 0 ); pVital; pVital = pVital->next )
92  {
93  THREAD_CHECKPOINT( tasks, 406 );
94  if ( !chr->dead() || pVital->regen_while_dead )
95  chr->regen_vital( pVital );
96  THREAD_CHECKPOINT( tasks, 407 );
97  }
98 
99  if ( !chr->dead() )
100  {
101  THREAD_CHECKPOINT( tasks, 408 );
102  chr->check_undamaged();
103  THREAD_CHECKPOINT( tasks, 409 );
104  }
105  };
106 
107 
108  for ( auto& realm : gamestate.Realms )
109  {
110  wgridx = realm->grid_width();
111  wgridy = realm->grid_height();
112 
113  for ( unsigned wx = 0; wx < wgridx; ++wx )
114  {
115  for ( unsigned wy = 0; wy < wgridy; ++wy )
116  {
117  bool any = false;
118  for ( auto& chr : realm->zone[wx][wy].characters )
119  {
120  any = true;
121  stat_regen( chr );
122  }
123  for ( auto& chr : realm->zone[wx][wy].npcs )
124  {
125  any = true;
126  stat_regen( chr );
127  }
128  if ( any )
129  ++nonempty_zones;
130  else
131  ++empty_zones;
132  }
133  }
134  }
135  THREAD_CHECKPOINT( tasks, 499 );
136 }
137 
138 #ifdef _WIN32
139 static HANDLE m_CurrentProcessHandle;
140 #endif
141 
142 void setup_update_rpm( void )
143 {
144 #ifdef _WIN32
145  m_CurrentProcessHandle = GetCurrentProcess();
146  FILETIME d1, d2, k, u;
147  GetProcessTimes( m_CurrentProcessHandle, &d1, &d2, &k, &u );
148  __int64 kt = *(__int64*)&k;
149  __int64 ut = *(__int64*)&u;
150  __int64 tot = ( kt + ut ) / 10; // convert to microseconds
153 #endif
154 }
155 
156 void update_rpm( void )
157 {
158  THREAD_CHECKPOINT( tasks, 300 );
159  stateManager.profilevars.last_sipm = static_cast<unsigned int>(
162 
163  stateManager.profilevars.last_scpm = static_cast<unsigned int>(
166 
173 
174  TICK_PROFILEVAR( events );
175  TICK_PROFILEVAR( skill_checks );
176  TICK_PROFILEVAR( combat_operations );
177 
178  TICK_PROFILEVAR( los_checks );
179  TICK_PROFILEVAR( polmap_walkheight_calculations );
180  TICK_PROFILEVAR( uomap_walkheight_calculations );
181  TICK_PROFILEVAR( mobile_movements );
182 
183 
184  SET_PROFILEVAR( error_creations, Bscript::BError::creations() );
185  TICK_PROFILEVAR( error_creations );
186 
187  TICK_PROFILEVAR( tasks_ontime );
188  TICK_PROFILEVAR( tasks_late );
189  TICK_PROFILEVAR( tasks_late_ticks );
190 
191  TICK_PROFILEVAR( scripts_ontime );
192  TICK_PROFILEVAR( scripts_late );
193 
194  TICK_PROFILEVAR( npc_searches );
195  ROLL_PROFILECLOCK( npc_search );
196 
197  TICK_PROFILEVAR( container_adds );
198  TICK_PROFILEVAR( container_removes );
199 
200 #ifdef _WIN32
201  FILETIME d1, d2, k, u;
202  GetProcessTimes( m_CurrentProcessHandle, &d1, &d2, &k, &u );
203  __int64 kt = *(__int64*)&k;
204  __int64 ut = *(__int64*)&u;
205  __int64 tot = ( kt + ut ) / 10; // convert to microseconds
207  static_cast<unsigned int>( tot - stateManager.profilevars.last_cpu_total );
209 #endif
210 
214  size_t total_cycles = stateManager.profilevars.busy_sysload_cycles +
216  if ( total_cycles )
217  {
219  stateManager.profilevars.busy_sysload_cycles * 100 / total_cycles;
221  stateManager.profilevars.sysload_nprocs * 10 / total_cycles;
222  }
223  // else don't adjust
227  if ( Plib::systemstate.config.watch_sysload )
228  INFO_PRINT.Format( "sysload={} ({}) cputime={}\n" )
231  if ( Plib::systemstate.config.log_sysload )
232  POLLOG.Format( "sysload={} ({}) cputime={}\n" )
235  // cout << "npc_searches:" << GET_PROFILEVAR_PER_MIN( npc_searches ) << " in " <<
236  // GET_PROFILECLOCK_MS( npc_search ) << " ms" << endl;
237  // cout << "container_adds:" << GET_PROFILEVAR_PER_MIN( container_adds ) << endl;
238  // cout << "container_removes:" << GET_PROFILEVAR_PER_MIN( container_removes ) << endl;
239 
240 #ifndef NDEBUG
242  << " noactivity: " << stateManager.profilevars.last_script_passes_noactivity << "\n";
243 #endif
246  if ( Plib::systemstate.config.watch_mapcache )
247  INFO_PRINT << "mapcache: hits=" << stateManager.profilevars.mapcache_hits
248  << ", misses=" << stateManager.profilevars.mapcache_misses << ", rate="
253  : 0 )
254  << "%\n";
257 
258  if ( Plib::systemstate.config.multithread )
259  {
260  stateManager.profilevars.last_sppm = static_cast<unsigned int>(
263 
264  TICK_PROFILEVAR( scheduler_passes );
265  TICK_PROFILEVAR( noactivity_scheduler_passes );
266 
267  if ( Plib::systemstate.config.watch_rpm )
269  << " task: " << ( GET_PROFILEVAR_PER_MIN( scheduler_passes ) ) << "("
270  << ( GET_PROFILEVAR_PER_MIN( noactivity_scheduler_passes ) ) << ")"
271  << " scin: " << stateManager.profilevars.last_sipm
272  << " scsl: " << stateManager.profilevars.last_scpm
273  << " MOB: " << get_mobile_count() << " TLI: " << get_toplevel_item_count()
274  << "\n";
275 
276  if ( Plib::systemstate.config.show_realm_info )
277  {
278  INFO_PRINT << "\nRealm info: \n";
279  for ( auto realm : gamestate.Realms )
280  {
281  INFO_PRINT << " - " << realm->name() << " (mob: " << realm->mobile_count()
282  << ", off: " << realm->offline_mobile_count()
283  << ", tli: " << realm->toplevel_item_count() << ", mlt: " << realm->multi_count()
284  << ")\n";
285  }
286  }
287  }
288  else
289  {
293 
294  // fixme realms
295  // fixme max realm size?
296  unsigned int grid_x = gamestate.main_realm->grid_width();
297  unsigned int grid_y = gamestate.main_realm->grid_height();
299  stateManager.profilevars.last_rpm / ( grid_x * grid_y / 10 );
303 
304  if ( Plib::systemstate.config.watch_rpm )
306  << " SIPM: " << stateManager.profilevars.last_sipm
307  << " SCPM: " << stateManager.profilevars.last_scpm << " SI/R: "
310  : 0 )
311  << " SC/R: "
314  : 0 )
315  << "\n";
316  }
317  THREAD_CHECKPOINT( tasks, 399 );
318 }
319 
321 {
322  THREAD_CHECKPOINT( tasks, 201 );
323  if ( scriptScheduler.getRunlist().empty() )
324  {
326  }
327  else
328  {
331  }
332  THREAD_CHECKPOINT( tasks, 299 );
333 }
334 
336 {
338  gamestate.update_rpm_task->start();
339  gamestate.regen_stats_task->start();
344 }
345 
346 // script loads
347 // script starts
348 // combat operations
349 // skill checks
350 }
351 }
unsigned int gameclock_t
Definition: gameclck.h:14
int get_toplevel_item_count()
Definition: uworld.cpp:109
size_t last_script_passes_activity
Definition: profile.h:78
Vital * FindVital(const std::string &str)
Definition: vital.cpp:83
int get_mobile_count()
Definition: uworld.cpp:117
SystemState systemstate
Definition: systemstate.cpp:12
std::unique_ptr< PeriodicTask > update_rpm_task
Definition: uvars.h:168
#define ROLL_PROFILECLOCK(timer)
Definition: profile.h:108
size_t last_mapcache_misses
Definition: profile.h:82
#define THREAD_CHECKPOINT(thread, check)
Definition: polsig.h:48
void regen_stats()
Definition: tasks.cpp:43
size_t cycles_per_decay_worldzone
Definition: state.h:35
#define SET_PROFILEVAR(counter, newvalue)
Definition: profile.h:86
size_t last_nonbusy_sysload_cycles
Definition: profile.h:62
std::atomic< size_t > script_passes_activity
Definition: profile.h:76
void setup_update_rpm(void)
Definition: tasks.cpp:142
void update_sysload()
Definition: tasks.cpp:320
static unsigned int creations()
Definition: berror.cpp:17
const ExecList & getRunlist()
size_t last_script_passes_noactivity
Definition: profile.h:79
ProfileVars profilevars
Definition: state.h:47
u64 escript_instr_cycles
Definition: escriptv.cpp:22
std::vector< Realms::Realm * > Realms
Definition: uvars.h:163
size_t mapcache_misses
Definition: profile.h:82
unsigned short grid_width() const
Definition: realm.cpp:105
#define GET_PROFILEVAR_PER_MIN(counter)
Definition: profile.h:100
unsigned short grid_height() const
Definition: realm.cpp:109
#define TICK_PROFILEVAR(counter)
Definition: profile.h:89
size_t cycles_until_decay_worldzone
Definition: state.h:36
#define POLLOG
Definition: logfacility.h:219
gameclock_t read_gameclock()
Reads the current value of the game clock.
Definition: gameclck.cpp:57
size_t nonbusy_sysload_cycles
Definition: profile.h:62
GameState gamestate
Definition: uvars.cpp:74
time_t poltime()
Definition: polclock.cpp:102
SettingsManager settingsManager
Definition: settings.cpp:14
size_t last_sysload_nprocs
Definition: profile.h:63
size_t last_mapcache_hits
Definition: profile.h:81
std::unique_ptr< PeriodicTask > regen_resources_task
Definition: uvars.h:170
Vital * next
Definition: vital.h:39
StateManager stateManager
Definition: state.cpp:8
ScriptScheduler scriptScheduler
std::unique_ptr< PeriodicTask > update_sysload_task
Definition: uvars.h:173
CombatConfig combat_config
Definition: settings.h:28
std::unique_ptr< PeriodicTask > regen_stats_task
Definition: uvars.h:169
size_t last_busy_sysload_cycles
Definition: profile.h:61
std::atomic< size_t > script_passes_noactivity
Definition: profile.h:77
void update_rpm(void)
Definition: tasks.cpp:156
#define INFO_PRINT
Definition: logfacility.h:223
void start_tasks()
Definition: tasks.cpp:335
Realms::Realm * main_realm
Definition: uvars.h:162
Definition: berror.cpp:12
std::unique_ptr< PeriodicTask > reload_pol_cfg_task
Definition: uvars.h:174
size_t busy_sysload_cycles
Definition: profile.h:61
std::unique_ptr< PeriodicTask > reload_accounts_task
Definition: uvars.h:171