ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/util.h
(Generate patch)

Comparing deliantra/server/include/util.h (file contents):
Revision 1.117 by root, Tue Jan 3 11:23:41 2012 UTC vs.
Revision 1.126 by root, Sat Nov 17 23:33:18 2018 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * 5 *
6 * Deliantra is free software: you can redistribute it and/or modify it under 6 * Deliantra is free software: you can redistribute it and/or modify it under
7 * the terms of the Affero GNU General Public License as published by the 7 * the terms of the Affero GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or (at your 8 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version. 9 * option) any later version.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the Affero GNU General Public License 16 * You should have received a copy of the Affero GNU General Public License
17 * and the GNU General Public License along with this program. If not, see 17 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>. 18 * <http://www.gnu.org/licenses/>.
19 * 19 *
20 * The authors can be reached via e-mail to <support@deliantra.net> 20 * The authors can be reached via e-mail to <support@deliantra.net>
21 */ 21 */
22 22
23#ifndef UTIL_H__ 23#ifndef UTIL_H__
24#define UTIL_H__ 24#define UTIL_H__
55#endif 55#endif
56 56
57// use C0X decltype for auto declarations until ISO C++ sanctifies them (if ever) 57// use C0X decltype for auto declarations until ISO C++ sanctifies them (if ever)
58#define auto(var,expr) decltype(expr) var = (expr) 58#define auto(var,expr) decltype(expr) var = (expr)
59 59
60#if cplusplus_does_not_suck 60#if cplusplus_does_not_suck /* still sucks in codesize with gcc 6, although local types work now */
61// does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) 61// does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm)
62template<typename T, int N> 62template<typename T, int N>
63static inline int array_length (const T (&arr)[N]) 63static inline int array_length (const T (&arr)[N])
64{ 64{
65 return N; 65 return N;
81 81
82// in range excluding end 82// in range excluding end
83#define IN_RANGE_EXC(val,beg,end) \ 83#define IN_RANGE_EXC(val,beg,end) \
84 ((unsigned int)(val) - (unsigned int)(beg) < (unsigned int)(end) - (unsigned int)(beg)) 84 ((unsigned int)(val) - (unsigned int)(beg) < (unsigned int)(end) - (unsigned int)(beg))
85 85
86void cleanup (const char *cause, bool make_core = false); 86ecb_cold void cleanup (const char *cause, bool make_core = false);
87void fork_abort (const char *msg); 87ecb_cold void fork_abort (const char *msg);
88 88
89// rationale for using (U) not (T) is to reduce signed/unsigned issues, 89// rationale for using (U) not (T) is to reduce signed/unsigned issues,
90// as a is often a constant while b is the variable. it is still a bug, though. 90// as a is often a constant while b is the variable. it is still a bug, though.
91template<typename T, typename U> static inline T min (T a, U b) { return a < (T)b ? a : (T)b; } 91template<typename T, typename U> static inline T min (T a, U b) { return a < (T)b ? a : (T)b; }
92template<typename T, typename U> static inline T max (T a, U b) { return a > (T)b ? a : (T)b; } 92template<typename T, typename U> static inline T max (T a, U b) { return a > (T)b ? a : (T)b; }
237#if 0 237#if 0
238// and has a max. error of 6 in the range -100..+100. 238// and has a max. error of 6 in the range -100..+100.
239#else 239#else
240// and has a max. error of 9 in the range -100..+100. 240// and has a max. error of 9 in the range -100..+100.
241#endif 241#endif
242inline int 242inline int
243idistance (int dx, int dy) 243idistance (int dx, int dy)
244{ 244{
245 unsigned int dx_ = abs (dx); 245 unsigned int dx_ = abs (dx);
246 unsigned int dy_ = abs (dy); 246 unsigned int dy_ = abs (dy);
247 247
248#if 0 248#if 0
249 return dx_ > dy_ 249 return dx_ > dy_
283absdir (int d) 283absdir (int d)
284{ 284{
285 return ((d - 1) & 7) + 1; 285 return ((d - 1) & 7) + 1;
286} 286}
287 287
288// avoid ctz name because netbsd or freebsd spams it's namespace with it
289#if GCC_VERSION(3,4)
290static inline int least_significant_bit (uint32_t x)
291{
292 return __builtin_ctz (x);
293}
294#else
295int least_significant_bit (uint32_t x);
296#endif
297
298#define for_all_bits_sparse_32(mask, idxvar) \ 288#define for_all_bits_sparse_32(mask, idxvar) \
299 for (uint32_t idxvar, mask_ = mask; \ 289 for (uint32_t idxvar, mask_ = mask; \
300 mask_ && ((idxvar = least_significant_bit (mask_)), mask_ &= ~(1 << idxvar), 1);) 290 mask_ && ((idxvar = ecb_ctz32 (mask_)), mask_ &= ~(1 << idxvar), 1);)
301 291
302extern ssize_t slice_alloc; // statistics 292extern ssize_t slice_alloc; // statistics
303 293
304void *salloc_ (int n) throw (std::bad_alloc); 294void *salloc_ (int n);
305void *salloc_ (int n, void *src) throw (std::bad_alloc); 295void *salloc_ (int n, void *src);
306 296
307// strictly the same as g_slice_alloc, but never returns 0 297// strictly the same as g_slice_alloc, but never returns 0
308template<typename T> 298template<typename T>
309inline T *salloc (int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T)); } 299inline T *salloc (int n = 1) { return (T *)salloc_ (n * sizeof (T)); }
310 300
311// also copies src into the new area, like "memdup" 301// also copies src into the new area, like "memdup"
312// if src is 0, clears the memory 302// if src is 0, clears the memory
313template<typename T> 303template<typename T>
314inline T *salloc (int n, T *src) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), (void *)src); } 304inline T *salloc (int n, T *src) { return (T *)salloc_ (n * sizeof (T), (void *)src); }
315 305
316// clears the memory 306// clears the memory
317template<typename T> 307template<typename T>
318inline T *salloc0(int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), 0); } 308inline T *salloc0(int n = 1) { return (T *)salloc_ (n * sizeof (T), 0); }
319 309
320// for symmetry 310// for symmetry
321template<typename T> 311template<typename T>
322inline void sfree (T *ptr, int n = 1) throw () 312inline void sfree (T *ptr, int n = 1) noexcept
323{ 313{
324 if (expect_true (ptr)) 314 if (expect_true (ptr))
325 { 315 {
326 slice_alloc -= n * sizeof (T); 316 slice_alloc -= n * sizeof (T);
327 if (DEBUG_POISON) memset (ptr, DEBUG_POISON, n * sizeof (T)); 317 if (DEBUG_POISON) memset (ptr, DEBUG_POISON, n * sizeof (T));
329 } 319 }
330} 320}
331 321
332// nulls the pointer 322// nulls the pointer
333template<typename T> 323template<typename T>
334inline void sfree0 (T *&ptr, int n = 1) throw () 324inline void sfree0 (T *&ptr, int n = 1) noexcept
335{ 325{
336 sfree<T> (ptr, n); 326 sfree<T> (ptr, n);
337 ptr = 0; 327 ptr = 0;
338} 328}
339 329
407 typedef const Tp *const_pointer; 397 typedef const Tp *const_pointer;
408 typedef Tp &reference; 398 typedef Tp &reference;
409 typedef const Tp &const_reference; 399 typedef const Tp &const_reference;
410 typedef Tp value_type; 400 typedef Tp value_type;
411 401
412 template <class U> 402 template <class U>
413 struct rebind 403 struct rebind
414 { 404 {
415 typedef slice_allocator<U> other; 405 typedef slice_allocator<U> other;
416 }; 406 };
417 407
418 slice_allocator () throw () { } 408 slice_allocator () noexcept { }
419 slice_allocator (const slice_allocator &) throw () { } 409 slice_allocator (const slice_allocator &) noexcept { }
420 template<typename Tp2> 410 template<typename Tp2>
421 slice_allocator (const slice_allocator<Tp2> &) throw () { } 411 slice_allocator (const slice_allocator<Tp2> &) noexcept { }
422 412
423 ~slice_allocator () { } 413 ~slice_allocator () { }
424 414
425 pointer address (reference x) const { return &x; } 415 pointer address (reference x) const { return &x; }
426 const_pointer address (const_reference x) const { return &x; } 416 const_pointer address (const_reference x) const { return &x; }
433 void deallocate (pointer p, size_type n) 423 void deallocate (pointer p, size_type n)
434 { 424 {
435 sfree<Tp> (p, n); 425 sfree<Tp> (p, n);
436 } 426 }
437 427
438 size_type max_size () const throw () 428 size_type max_size () const noexcept
439 { 429 {
440 return size_t (-1) / sizeof (Tp); 430 return size_t (-1) / sizeof (Tp);
441 } 431 }
442 432
443 void construct (pointer p, const Tp &val) 433 void construct (pointer p, const Tp &val)
460 refcnt_buf (void *data, size_t size); 450 refcnt_buf (void *data, size_t size);
461 451
462 refcnt_buf (const refcnt_buf &src) 452 refcnt_buf (const refcnt_buf &src)
463 { 453 {
464 data = src.data; 454 data = src.data;
465 ++_refcnt (); 455 inc ();
466 } 456 }
467 457
468 ~refcnt_buf (); 458 ~refcnt_buf ();
469 459
470 refcnt_buf &operator =(const refcnt_buf &src); 460 refcnt_buf &operator =(const refcnt_buf &src);
479 return _size (); 469 return _size ();
480 } 470 }
481 471
482protected: 472protected:
483 enum { 473 enum {
484 overhead = sizeof (unsigned int) * 2 474 overhead = sizeof (uint32_t) * 2
485 }; 475 };
486 476
487 unsigned int &_size () const 477 uint32_t &_size () const
488 { 478 {
489 return ((unsigned int *)data)[-2]; 479 return ((unsigned int *)data)[-2];
490 } 480 }
491 481
492 unsigned int &_refcnt () const 482 uint32_t &_refcnt () const
493 { 483 {
494 return ((unsigned int *)data)[-1]; 484 return ((unsigned int *)data)[-1];
495 } 485 }
496 486
497 void _alloc (unsigned int size) 487 void _alloc (uint32_t size)
498 { 488 {
499 data = ((char *)salloc<char> (size + overhead)) + overhead; 489 data = ((char *)salloc<char> (size + overhead)) + overhead;
500 _size () = size; 490 _size () = size;
501 _refcnt () = 1; 491 _refcnt () = 1;
502 } 492 }
503 493
494 void _dealloc ();
495
496 void inc ()
497 {
498 ++_refcnt ();
499 }
500
504 void dec () 501 void dec ()
505 { 502 {
506 if (!--_refcnt ()) 503 if (!--_refcnt ())
507 sfree<char> (data - overhead, size () + overhead); 504 _dealloc ();
508 } 505 }
509}; 506};
510 507
511INTERFACE_CLASS (attachable) 508INTERFACE_CLASS (attachable)
512struct refcnt_base 509struct refcnt_base
529 // p if not null 526 // p if not null
530 refcnt_base::refcnt_t *refcnt_ref () { return p ? &p->refcnt : &refcnt_dummy; } 527 refcnt_base::refcnt_t *refcnt_ref () { return p ? &p->refcnt : &refcnt_dummy; }
531 528
532 void refcnt_dec () 529 void refcnt_dec ()
533 { 530 {
534 if (!is_constant (p)) 531 if (!ecb_is_constant (p))
535 --*refcnt_ref (); 532 --*refcnt_ref ();
536 else if (p) 533 else if (p)
537 --p->refcnt; 534 --p->refcnt;
538 } 535 }
539 536
540 void refcnt_inc () 537 void refcnt_inc ()
541 { 538 {
542 if (!is_constant (p)) 539 if (!ecb_is_constant (p))
543 ++*refcnt_ref (); 540 ++*refcnt_ref ();
544 else if (p) 541 else if (p)
545 ++p->refcnt; 542 ++p->refcnt;
546 } 543 }
547 544
590 // with good distribution. 587 // with good distribution.
591 // FNV-1a is faster on many cpus because the multiplication 588 // FNV-1a is faster on many cpus because the multiplication
592 // runs concurrently with the looping logic. 589 // runs concurrently with the looping logic.
593 // we modify the hash a bit to improve its distribution 590 // we modify the hash a bit to improve its distribution
594 uint32_t hash = STRHSH_NULL; 591 uint32_t hash = STRHSH_NULL;
595 592
596 while (*s) 593 while (*s)
597 hash = (hash ^ *s++) * 16777619U; 594 hash = (hash ^ *s++) * 16777619U;
598 595
599 return hash ^ (hash >> 16); 596 return hash ^ (hash >> 16);
600} 597}
601 598
602static inline uint32_t 599static inline uint32_t
603memhsh (const char *s, size_t len) 600memhsh (const char *s, size_t len)
604{ 601{
605 uint32_t hash = STRHSH_NULL; 602 uint32_t hash = STRHSH_NULL;
606 603
607 while (len--) 604 while (len--)
608 hash = (hash ^ *s++) * 16777619U; 605 hash = (hash ^ *s++) * 16777619U;
609 606
610 return hash; 607 return hash;
611} 608}
654 } 651 }
655}; 652};
656 653
657// This container blends advantages of linked lists 654// This container blends advantages of linked lists
658// (efficiency) with vectors (random access) by 655// (efficiency) with vectors (random access) by
659// by using an unordered vector and storing the vector 656// using an unordered vector and storing the vector
660// index inside the object. 657// index inside the object.
661// 658//
662// + memory-efficient on most 64 bit archs 659// + memory-efficient on most 64 bit archs
663// + O(1) insert/remove 660// + O(1) insert/remove
664// + free unique (but varying) id for inserted objects 661// + free unique (but varying) id for inserted objects
701 insert (&obj); 698 insert (&obj);
702 } 699 }
703 700
704 void erase (T *obj) 701 void erase (T *obj)
705 { 702 {
706 unsigned int pos = obj->*indexmember; 703 object_vector_index pos = obj->*indexmember;
707 obj->*indexmember = 0; 704 obj->*indexmember = 0;
708 705
709 if (pos < this->size ()) 706 if (pos < this->size ())
710 { 707 {
711 (*this)[pos - 1] = (*this)[this->size () - 1]; 708 (*this)[pos - 1] = (*this)[this->size () - 1];
807 804
808int similar_direction (int a, int b); 805int similar_direction (int a, int b);
809 806
810// like v?sprintf, but returns a "static" buffer 807// like v?sprintf, but returns a "static" buffer
811char *vformat (const char *format, va_list ap); 808char *vformat (const char *format, va_list ap);
812char *format (const char *format, ...) attribute ((format (printf, 1, 2))); 809char *format (const char *format, ...) ecb_attribute ((format (printf, 1, 2)));
813 810
814// safety-check player input which will become object->msg 811// safety-check player input which will become object->msg
815bool msg_is_safe (const char *msg); 812bool msg_is_safe (const char *msg);
816 813
817///////////////////////////////////////////////////////////////////////////// 814/////////////////////////////////////////////////////////////////////////////

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines