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.135 by root, Thu Jan 4 20:29:46 2007 UTC vs.
Revision 1.139 by root, Fri Jan 5 19:12:03 2007 UTC

26use Event; $Event::Eval = 1; # no idea why this is required, but it is 26use Event; $Event::Eval = 1; # no idea why this is required, but it is
27 27
28# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode? 28# work around bug in YAML::Syck - bad news for perl6, will it be as broken wrt. unicode?
29$YAML::Syck::ImplicitUnicode = 1; 29$YAML::Syck::ImplicitUnicode = 1;
30 30
31$Coro::main->prio (2); # run main coroutine ("the server") with very high priority 31$Coro::main->prio (Coro::PRIO_MAX); # run main coroutine ("the server") with very high priority
32 32
33sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload 33sub WF_AUTOCANCEL () { 1 } # automatically cancel this watcher on reload
34 34
35our %COMMAND = (); 35our %COMMAND = ();
36our %COMMAND_TIME = (); 36our %COMMAND_TIME = ();
221 # wake up all waiters, to be on the safe side 221 # wake up all waiters, to be on the safe side
222 $_->ready for @{ delete $LOCK{$key} }; 222 $_->ready for @{ delete $LOCK{$key} };
223 } 223 }
224} 224}
225 225
226=item cf::async { BLOCK }
227
228Like C<Coro::async>, but runs the given BLOCK in an eval and only logs the
229error instead of exiting the server in case of a problem.
230
231=cut
232
233sub async(&) {
234 my ($cb) = @_;
235
236 Coro::async {
237 eval { $cb->() };
238 warn $@ if $@;
239 }
240}
241
242sub freeze_mainloop { 226sub freeze_mainloop {
243 return unless $TICK_WATCHER->is_active; 227 return unless $TICK_WATCHER->is_active;
244 228
245 my $guard = Coro::guard { $TICK_WATCHER->start }; 229 my $guard = Coro::guard { $TICK_WATCHER->start };
246 $TICK_WATCHER->stop; 230 $TICK_WATCHER->stop;
272 my $freeze_guard = freeze_mainloop; 256 my $freeze_guard = freeze_mainloop;
273 257
274 my $busy = 1; 258 my $busy = 1;
275 my @res; 259 my @res;
276 260
277 (Coro::async { 261 (Coro::async_pool {
278 @res = eval { $job->() }; 262 @res = eval { $job->() };
279 warn $@ if $@; 263 warn $@ if $@;
280 undef $busy; 264 undef $busy;
281 })->prio (Coro::PRIO_MAX); 265 })->prio (Coro::PRIO_MAX);
282 266
283 while ($busy) { 267 while ($busy) {
284 Coro::cede_notself; 268 unless (Coro::cede) {
285 Event::one_event unless Coro::nready; 269 Coro::nready ? Event::one_event 0 : Event::one_event;
270 Coro::cede_notself unless Coro::cede;
271 }
286 } 272 }
287 273
288 wantarray ? @res : $res[0] 274 wantarray ? @res : $res[0]
289 } else { 275 } else {
290 # we are in another coroutine, how wonderful, everything just works 276 # we are in another coroutine, how wonderful, everything just works
293 } 279 }
294} 280}
295 281
296=item $coro = cf::coro { BLOCK } 282=item $coro = cf::coro { BLOCK }
297 283
298Creates and returns a new coro. This coro is automcatially being canceled 284Creates (and readies) and returns a new coro. This coro is automcatially
299when the extension calling this is being unloaded. 285being canceled when the extension calling this is being unloaded.
300 286
301=cut 287=cut
302 288
303sub coro(&) { 289sub coro(&) {
304 my $cb = shift; 290 my $cb = shift;
305 291
306 my $coro = &cf::async ($cb); 292 my $coro = &Coro::async_pool ($cb);
307 293
308 $coro->on_destroy (sub { 294 $coro->on_destroy (sub {
309 delete $EXT_CORO{$coro+0}; 295 delete $EXT_CORO{$coro+0};
310 }); 296 });
311 $EXT_CORO{$coro+0} = $coro; 297 $EXT_CORO{$coro+0} = $coro;
1284} 1270}
1285 1271
1286sub find_sync { 1272sub find_sync {
1287 my ($path, $origin) = @_; 1273 my ($path, $origin) = @_;
1288 1274
1289 cf::sync_job { cf::map::find $path, $origin } 1275 cf::sync_job {
1276 my $map = cf::map::find $path, $origin;
1277 $map
1278 }
1290} 1279}
1291 1280
1292sub do_load_sync { 1281sub do_load_sync {
1293 my ($map) = @_; 1282 my ($map) = @_;
1294 1283
1295 cf::sync_job { $map->load }; 1284 cf::sync_job { $map->load };
1296} 1285}
1297 1286
1298sub save { 1287sub save {
1299 my ($self) = @_; 1288 my ($self) = @_;
1289
1290 my $lock = cf::lock_acquire "map_data:" . $self->path;
1300 1291
1301 $self->{last_save} = $cf::RUNTIME; 1292 $self->{last_save} = $cf::RUNTIME;
1302 1293
1303 return unless $self->dirty; 1294 return unless $self->dirty;
1304 1295
1323 my ($self) = @_; 1314 my ($self) = @_;
1324 1315
1325 # save first because save cedes 1316 # save first because save cedes
1326 $self->save; 1317 $self->save;
1327 1318
1319 my $lock = cf::lock_acquire "map_data:" . $self->path;
1320
1328 return if $self->players; 1321 return if $self->players;
1329 return if $self->in_memory != cf::MAP_IN_MEMORY; 1322 return if $self->in_memory != cf::MAP_IN_MEMORY;
1330 return if $self->{deny_save}; 1323 return if $self->{deny_save};
1331 1324
1332 $self->clear; 1325 $self->clear;
1373 $self->save; 1366 $self->save;
1374} 1367}
1375 1368
1376sub reset { 1369sub reset {
1377 my ($self) = @_; 1370 my ($self) = @_;
1371
1372 my $lock = cf::lock_acquire "map_data:" . $self->path;
1378 1373
1379 return if $self->players; 1374 return if $self->players;
1380 return if $self->{path}{user_rel};#d# 1375 return if $self->{path}{user_rel};#d#
1381 1376
1382 warn "resetting map ", $self->path;#d# 1377 warn "resetting map ", $self->path;#d#
1548 my ($pl) = @_; 1543 my ($pl) = @_;
1549 1544
1550 # try to abort aborted map switching on player login :) 1545 # try to abort aborted map switching on player login :)
1551 # should happen only on crashes 1546 # should happen only on crashes
1552 if ($pl->ob->{_link_pos}) { 1547 if ($pl->ob->{_link_pos}) {
1548
1553 $pl->ob->enter_link; 1549 $pl->ob->enter_link;
1554 cf::async { 1550 (Coro::async_pool {
1555 # we need this sleep as the login has a concurrent enter_exit running 1551 # we need this sleep as the login has a concurrent enter_exit running
1556 # and this sleep increases chances of the player not ending up in scorn 1552 # and this sleep increases chances of the player not ending up in scorn
1557 Coro::Timer::sleep 1; 1553 Coro::Timer::sleep 1;
1558 $pl->ob->leave_link; 1554 $pl->ob->leave_link;
1559 }; 1555 })->prio (2);
1560 } 1556 }
1561 }, 1557 },
1562); 1558);
1563 1559
1564=item $player_object->goto_map ($path, $x, $y) 1560=item $player_object->goto ($path, $x, $y)
1565 1561
1566=cut 1562=cut
1567 1563
1568sub cf::object::player::goto_map { 1564sub cf::object::player::goto {
1569 my ($self, $path, $x, $y) = @_; 1565 my ($self, $path, $x, $y) = @_;
1570 1566
1571 $self->enter_link; 1567 $self->enter_link;
1572 1568
1573 (cf::async { 1569 (Coro::async_pool {
1574 $path = new cf::path $path; 1570 $path = new cf::path $path;
1575 1571
1576 my $map = cf::map::find $path->as_string; 1572 my $map = cf::map::find $path->as_string;
1577 $map = $map->customise_for ($self) if $map; 1573 $map = $map->customise_for ($self) if $map;
1578 1574
1640 1636
1641 return unless $self->type == cf::PLAYER; 1637 return unless $self->type == cf::PLAYER;
1642 1638
1643 $self->enter_link; 1639 $self->enter_link;
1644 1640
1645 (cf::async { 1641 (Coro::async_pool {
1646 $self->deactivate_recursive; # just to be sure 1642 $self->deactivate_recursive; # just to be sure
1647 unless (eval { 1643 unless (eval {
1648 prepare_random_map $exit 1644 prepare_random_map $exit
1649 if $exit->slaying eq "/!"; 1645 if $exit->slaying eq "/!";
1650 1646
1651 my $path = new cf::path $exit->slaying, $exit->map && $exit->map->path; 1647 my $path = new cf::path $exit->slaying, $exit->map && $exit->map->path;
1652 $self->goto_map ($path, $exit->stats->hp, $exit->stats->sp); 1648 $self->goto ($path, $exit->stats->hp, $exit->stats->sp);
1653 1649
1654 1; 1650 1;
1655 }) { 1651 }) {
1656 $self->message ("Something went wrong deep within the crossfire server. " 1652 $self->message ("Something went wrong deep within the crossfire server. "
1657 . "I'll try to bring you back to the map you were before. " 1653 . "I'll try to bring you back to the map you were before. "
1742=cut 1738=cut
1743 1739
1744sub cf::client::coro { 1740sub cf::client::coro {
1745 my ($self, $cb) = @_; 1741 my ($self, $cb) = @_;
1746 1742
1747 my $coro = &cf::async ($cb); 1743 my $coro = &Coro::async_pool ($cb);
1748 1744
1749 $coro->on_destroy (sub { 1745 $coro->on_destroy (sub {
1750 delete $self->{_coro}{$coro+0}; 1746 delete $self->{_coro}{$coro+0};
1751 }); 1747 });
1752 1748
1990 local $/; 1986 local $/;
1991 *CFG = YAML::Syck::Load <$fh>; 1987 *CFG = YAML::Syck::Load <$fh>;
1992 1988
1993 $EMERGENCY_POSITION = $CFG{emergency_position} || ["/world/world_105_115", 5, 37]; 1989 $EMERGENCY_POSITION = $CFG{emergency_position} || ["/world/world_105_115", 5, 37];
1994 1990
1991 $cf::map::MAX_RESET = $CFG{map_max_reset} if exists $CFG{map_max_reset};
1992 $cf::map::DEFAULT_RESET = $CFG{map_default_reset} if exists $CFG{map_default_reset};
1993
1995 if (exists $CFG{mlockall}) { 1994 if (exists $CFG{mlockall}) {
1996 eval { 1995 eval {
1997 $CFG{mlockall} ? &mlockall : &munlockall 1996 $CFG{mlockall} ? &mlockall : &munlockall
1998 and die "WARNING: m(un)lockall failed: $!\n"; 1997 and die "WARNING: m(un)lockall failed: $!\n";
1999 }; 1998 };
2003 2002
2004sub main { 2003sub main {
2005 # we must not ever block the main coroutine 2004 # we must not ever block the main coroutine
2006 local $Coro::idle = sub { 2005 local $Coro::idle = sub {
2007 Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d# 2006 Carp::cluck "FATAL: Coro::idle was called, major BUG, use cf::sync_job!\n";#d#
2008 (Coro::unblock_sub { 2007 Coro::async_pool { Event::one_event };
2009 Event::one_event;
2010 })->();
2011 }; 2008 };
2012 2009
2013 cfg_load; 2010 cfg_load;
2014 db_load; 2011 db_load;
2015 load_extensions; 2012 load_extensions;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines