--- deliantra/server/lib/cf.pm 2011/05/03 17:12:14 1.568 +++ deliantra/server/lib/cf.pm 2011/05/08 11:44:43 1.572 @@ -133,7 +133,8 @@ our %CFG; our $UPTIME; $UPTIME ||= time; -our $RUNTIME; +our $RUNTIME = 0; +our $SERVER_TICK = 0; our $NOW; our (%PLAYER, %PLAYER_LOADING); # all users @@ -153,6 +154,9 @@ our $REATTACH_ON_RELOAD; # set to true to force object reattach on reload (slow) our $REALLY_UNLOOP; # never set to true, please :) +our $WAIT_FOR_TICK = new Coro::Signal; +our @WAIT_FOR_TICK_BEGIN; + binmode STDOUT; binmode STDERR; @@ -195,7 +199,22 @@ =item $cf::UPTIME -The timestamp of the server start (so not actually an uptime). +The timestamp of the server start (so not actually an "uptime"). + +=item $cf::SERVER_TICK + +An unsigned integer that starts at zero when the server is started and is +incremented on every tick. + +=item $cf::NOW + +The (real) time of the last (current) server tick - updated before and +after tick processing, so this is useful only as a rough "what time is it +now" estimate. + +=item $cf::TICK + +The interval between each server tick, in seconds. =item $cf::RUNTIME @@ -211,14 +230,6 @@ unique-items directory, player file directory, random maps directory and database environment. -=item $cf::NOW - -The time of the last (current) server tick. - -=item $cf::TICK - -The interval between server ticks, in seconds. - =item $cf::LOADAVG The current CPU load on the server (alpha-smoothed), as a value between 0 @@ -240,6 +251,18 @@ returns directly I the tick processing (and consequently, can only wake one thread per tick), while cf::wait_for_tick wakes up all waiters after tick processing. +Note that cf::Wait_for_tick will immediately return when the server is not +ticking, making it suitable for small pauses in threads that need to run +when the server is paused. If that is not applicable (i.e. you I +want to wait, use C<$cf::WAIT_FOR_TICK>). + +=item $cf::WAIT_FOR_TICK + +Note that C is probably the correct thing to use. This +variable contains a L that is broadcats after every server +tick. Calling C<< ->wait >> on it will suspend the caller until after the +next server tick. + =cut sub wait_for_tick(); @@ -547,8 +570,7 @@ if (@SLOT_QUEUE) { # we do not use wait_for_tick() as it returns immediately when tick is inactive - push @cf::WAIT_FOR_TICK, $signal; - $signal->wait; + $WAIT_FOR_TICK->wait; } else { $busy = 0; Coro::schedule; @@ -2173,9 +2195,7 @@ my $guard = cf::lock_acquire "map_data:$path"; return unless $self->valid; - return unless $self->in_memory == cf::MAP_SWAPPED; - - $self->in_memory (cf::MAP_LOADING); + return unless $self->state == cf::MAP_SWAPPED; $self->alloc; @@ -2208,6 +2228,8 @@ if delete $self->{load_original}; } + $self->state (cf::MAP_INACTIVE); + cf::cede_to_tick; # now do the right thing for maps $self->link_multipart_objects; @@ -2219,14 +2241,13 @@ $self->decay_objects; $self->fix_auto_apply; $self->update_buttons; + $self->post_load_physics; cf::cede_to_tick; #$self->activate; # no longer activate maps automatically } $self->{last_save} = $cf::RUNTIME; $self->last_access ($cf::RUNTIME); - - $self->in_memory (cf::MAP_ACTIVE); } $self->post_load; @@ -2279,6 +2300,7 @@ sub find_sync { my ($path, $origin) = @_; + # it's a bug to call this from the main context return cf::LOG cf::llevError | cf::logBacktrace, "do_find_sync" if $Coro::current == $Coro::main; @@ -2288,6 +2310,7 @@ sub do_load_sync { my ($map) = @_; + # it's a bug to call this from the main context return cf::LOG cf::llevError | cf::logBacktrace, "do_load_sync" if $Coro::current == $Coro::main; @@ -2302,8 +2325,10 @@ $path = normalise $path, $origin; + print "find async $path (from $origin)\n";#d# + if (my $map = $cf::MAP{$path}) { - return $map if !$load || $map->in_memory == cf::MAP_ACTIVE; + return $map if !$load || $map->linkable; } $MAP_PREFETCH{$path} |= $load; @@ -2372,14 +2397,14 @@ my $lock = cf::lock_acquire "map_data:$self->{path}"; - return if $self->in_memory != cf::MAP_ACTIVE; + return if !$self->linkable; return if $self->{deny_save}; return if $self->players; # first deactivate the map and "unlink" it from the core $self->deactivate; $_->clear_links_to ($self) for values %cf::MAP; - $self->in_memory (cf::MAP_SWAPPED); + $self->state (cf::MAP_SWAPPED); # then atomically save $self->_save; @@ -2415,7 +2440,7 @@ cf::trace "resetting map ", $self->path, "\n"; - $self->in_memory (cf::MAP_SWAPPED); + $self->state (cf::MAP_SWAPPED); # need to save uniques path unless ($self->{deny_save}) { @@ -2933,7 +2958,9 @@ my $guard = cf::lock_acquire "exit_prepare:$exit"; prepare_random_map $exit - if $slaying eq "/!"; # need to re-check after getting the lock + if $exit->slaying eq "/!"; # need to re-check after getting the lock + + $map = $exit->slaying; } elsif ($slaying eq '!up') { $map = $exit->map->tile_path (cf::TILE_UP); @@ -4093,19 +4120,14 @@ my $bug_warning = 0; -our @WAIT_FOR_TICK; -our @WAIT_FOR_TICK_BEGIN; - sub wait_for_tick() { - return Coro::cede if tick_inhibit || $Coro::current == $Coro::main; + return Coro::AnyEvent::poll if tick_inhibit || $Coro::current == $Coro::main; - my $signal = new Coro::Signal; - push @WAIT_FOR_TICK, $signal; - $signal->wait; + $WAIT_FOR_TICK->wait; } sub wait_for_tick_begin() { - return Coro::cede if tick_inhibit || $Coro::current == $Coro::main; + return Coro::AnyEvent::poll if tick_inhibit || $Coro::current == $Coro::main; my $signal = new Coro::Signal; push @WAIT_FOR_TICK_BEGIN, $signal; @@ -4119,7 +4141,7 @@ return; } - cf::server_tick; # one server iteration + cf::one_tick; # one server iteration #for(1..3e6){} AE::now_update; $NOW=AE::now; # generate load #d# @@ -4135,9 +4157,7 @@ if (my $sig = shift @WAIT_FOR_TICK_BEGIN) { $sig->send; } - while (my $sig = shift @WAIT_FOR_TICK) { - $sig->send; - } + $WAIT_FOR_TICK->broadcast; $LOAD = ($NOW - $TICK_START) / $TICK; $LOADAVG = $LOADAVG * 0.75 + $LOAD * 0.25;