ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/cf.pm
(Generate patch)

Comparing deliantra/server/lib/cf.pm (file contents):
Revision 1.126 by root, Tue Jan 2 23:12:47 2007 UTC vs.
Revision 1.130 by root, Thu Jan 4 00:08:08 2007 UTC

8use Storable; 8use Storable;
9use Opcode; 9use Opcode;
10use Safe; 10use Safe;
11use Safe::Hole; 11use Safe::Hole;
12 12
13use Coro 3.3; 13use Coro 3.3 ();
14use Coro::Event; 14use Coro::Event;
15use Coro::Timer; 15use Coro::Timer;
16use Coro::Signal; 16use Coro::Signal;
17use Coro::Semaphore; 17use Coro::Semaphore;
18use Coro::AIO; 18use Coro::AIO;
245 # wake up all waiters, to be on the safe side 245 # wake up all waiters, to be on the safe side
246 $_->ready for @{ delete $LOCK{$key} }; 246 $_->ready for @{ delete $LOCK{$key} };
247 } 247 }
248} 248}
249 249
250=item cf::async { BLOCK }
251
252Like C<Coro::async>, but runs the given BLOCK in an eval and only logs the
253error instead of exiting the server in case of a problem.
254
255=cut
256
257sub async(&) {
258 my ($cb) = @_;
259
260 Coro::async {
261 eval { $cb->() };
262 warn $@ if $@;
263 }
264}
265
250=item cf::sync_job { BLOCK } 266=item cf::sync_job { BLOCK }
251 267
252The design of crossfire+ requires that the main coro ($Coro::main) is 268The design of crossfire+ requires that the main coro ($Coro::main) is
253always able to handle events or runnable, as crossfire+ is only partly 269always able to handle events or runnable, as crossfire+ is only partly
254reentrant. Thus "blocking" it by e.g. waiting for I/O is not acceptable. 270reentrant. Thus "blocking" it by e.g. waiting for I/O is not acceptable.
301=cut 317=cut
302 318
303sub coro(&) { 319sub coro(&) {
304 my $cb = shift; 320 my $cb = shift;
305 321
306 my $coro; $coro = async { 322 my $coro = &cf::async ($cb);
307 eval {
308 $cb->();
309 };
310 warn $@ if $@;
311 };
312 323
313 $coro->on_destroy (sub { 324 $coro->on_destroy (sub {
314 delete $EXT_CORO{$coro+0}; 325 delete $EXT_CORO{$coro+0};
315 }); 326 });
316 $EXT_CORO{$coro+0} = $coro; 327 $EXT_CORO{$coro+0} = $coro;
1311} 1322}
1312 1323
1313sub swap_out { 1324sub swap_out {
1314 my ($self) = @_; 1325 my ($self) = @_;
1315 1326
1327 # save first because save cedes
1328 $self->save;
1329
1316 return if $self->players; 1330 return if $self->players;
1317 return if $self->in_memory != cf::MAP_IN_MEMORY; 1331 return if $self->in_memory != cf::MAP_IN_MEMORY;
1318 return if $self->{deny_save}; 1332 return if $self->{deny_save};
1319 1333
1320 $self->save;
1321 $self->clear; 1334 $self->clear;
1322 $self->in_memory (cf::MAP_SWAPPED); 1335 $self->in_memory (cf::MAP_SWAPPED);
1323} 1336}
1324 1337
1325sub reset_at { 1338sub reset_at {
1538 1551
1539 # try to abort aborted map switching on player login :) 1552 # try to abort aborted map switching on player login :)
1540 # should happen only on crashes 1553 # should happen only on crashes
1541 if ($pl->ob->{_link_pos}) { 1554 if ($pl->ob->{_link_pos}) {
1542 $pl->ob->enter_link; 1555 $pl->ob->enter_link;
1543 Coro::async { 1556 cf::async {
1544 # we need this sleep as the login has a concurrent enter_exit running 1557 # we need this sleep as the login has a concurrent enter_exit running
1545 # and this sleep increases chances of the player not ending up in scorn 1558 # and this sleep increases chances of the player not ending up in scorn
1546 Coro::Timer::sleep 1; 1559 Coro::Timer::sleep 1;
1547 $pl->ob->leave_link; 1560 $pl->ob->leave_link;
1548 }; 1561 };
1557sub cf::object::player::goto_map { 1570sub cf::object::player::goto_map {
1558 my ($self, $path, $x, $y) = @_; 1571 my ($self, $path, $x, $y) = @_;
1559 1572
1560 $self->enter_link; 1573 $self->enter_link;
1561 1574
1562 (Coro::async { 1575 (cf::async {
1563 $path = new cf::path $path; 1576 $path = new cf::path $path;
1564 1577
1565 my $map = cf::map::find_map $path->as_string; 1578 my $map = cf::map::find_map $path->as_string;
1566 $map = $map->customise_for ($self) if $map; 1579 $map = $map->customise_for ($self) if $map;
1567 1580
1629 1642
1630 return unless $self->type == cf::PLAYER; 1643 return unless $self->type == cf::PLAYER;
1631 1644
1632 $self->enter_link; 1645 $self->enter_link;
1633 1646
1634 (Coro::async { 1647 (cf::async {
1635 unless (eval { 1648 unless (eval {
1636
1637 prepare_random_map $exit 1649 prepare_random_map $exit
1638 if $exit->slaying eq "/!"; 1650 if $exit->slaying eq "/!";
1639 1651
1640 my $path = new cf::path $exit->slaying, $exit->map && $exit->map->path; 1652 my $path = new cf::path $exit->slaying, $exit->map && $exit->map->path;
1641 $self->goto_map ($path, $exit->stats->hp, $exit->stats->sp); 1653 $self->goto_map ($path, $exit->stats->hp, $exit->stats->sp);
1703 on_reply => sub { 1715 on_reply => sub {
1704 my ($ns, $msg) = @_; 1716 my ($ns, $msg) = @_;
1705 1717
1706 # this weird shuffling is so that direct followup queries 1718 # this weird shuffling is so that direct followup queries
1707 # get handled first 1719 # get handled first
1708 my $queue = delete $ns->{query_queue}; 1720 my $queue = delete $ns->{query_queue}
1721 or return; # be conservative, not sure how that can happen, but we saw a crash here
1709 1722
1710 (shift @$queue)->[1]->($msg); 1723 (shift @$queue)->[1]->($msg);
1711 1724
1712 push @{ $ns->{query_queue} }, @$queue; 1725 push @{ $ns->{query_queue} }, @$queue;
1713 1726
1730=cut 1743=cut
1731 1744
1732sub cf::client::coro { 1745sub cf::client::coro {
1733 my ($self, $cb) = @_; 1746 my ($self, $cb) = @_;
1734 1747
1735 my $coro; $coro = async { 1748 my $coro = &cf::async ($cb);
1736 eval {
1737 $cb->();
1738 };
1739 warn $@ if $@;
1740 };
1741 1749
1742 $coro->on_destroy (sub { 1750 $coro->on_destroy (sub {
1743 delete $self->{_coro}{$coro+0}; 1751 delete $self->{_coro}{$coro+0};
1744 }); 1752 });
1745 1753

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines