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.113 by root, Fri Apr 22 02:03:11 2011 UTC vs.
Revision 1.127 by root, Sat Nov 17 23:40:02 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 (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 5 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * 6 *
6 * Deliantra is free software: you can redistribute it and/or modify it under 7 * 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 8 * 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 9 * Free Software Foundation, either version 3 of the License, or (at your
9 * option) any later version. 10 * option) any later version.
10 * 11 *
11 * This program is distributed in the hope that it will be useful, 12 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 15 * GNU General Public License for more details.
15 * 16 *
16 * You should have received a copy of the Affero GNU General Public License 17 * 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 18 * and the GNU General Public License along with this program. If not, see
18 * <http://www.gnu.org/licenses/>. 19 * <http://www.gnu.org/licenses/>.
19 * 20 *
20 * The authors can be reached via e-mail to <support@deliantra.net> 21 * The authors can be reached via e-mail to <support@deliantra.net>
21 */ 22 */
22 23
23#ifndef UTIL_H__ 24#ifndef UTIL_H__
24#define UTIL_H__ 25#define UTIL_H__
55#endif 56#endif
56 57
57// use C0X decltype for auto declarations until ISO C++ sanctifies them (if ever) 58// use C0X decltype for auto declarations until ISO C++ sanctifies them (if ever)
58#define auto(var,expr) decltype(expr) var = (expr) 59#define auto(var,expr) decltype(expr) var = (expr)
59 60
60#if cplusplus_does_not_suck 61#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) 62// does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm)
62template<typename T, int N> 63template<typename T, int N>
63static inline int array_length (const T (&arr)[N]) 64static inline int array_length (const T (&arr)[N])
64{ 65{
65 return N; 66 return N;
81 82
82// in range excluding end 83// in range excluding end
83#define IN_RANGE_EXC(val,beg,end) \ 84#define IN_RANGE_EXC(val,beg,end) \
84 ((unsigned int)(val) - (unsigned int)(beg) < (unsigned int)(end) - (unsigned int)(beg)) 85 ((unsigned int)(val) - (unsigned int)(beg) < (unsigned int)(end) - (unsigned int)(beg))
85 86
86void cleanup (const char *cause, bool make_core = false); 87ecb_cold void cleanup (const char *cause, bool make_core = false);
87void fork_abort (const char *msg); 88ecb_cold void fork_abort (const char *msg);
88 89
89// rationale for using (U) not (T) is to reduce signed/unsigned issues, 90// 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. 91// 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 (U)a < b ? (U)a : b; } 92template<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 (U)a > b ? (U)a : b; } 93template<typename T, typename U> static inline T max (T a, U b) { return a > (T)b ? a : (T)b; }
93template<typename T, typename U, typename V> static inline T clamp (T v, U a, V b) { return v < (T)a ? (T)a : v >(T)b ? (T)b : v; } 94template<typename T, typename U, typename V> static inline T clamp (T v, U a, V b) { return v < (T)a ? (T)a : v >(T)b ? (T)b : v; }
94 95
95template<typename T, typename U> static inline void min_it (T &v, U m) { v = min (v, (T)m); } 96template<typename T, typename U> static inline void min_it (T &v, U m) { v = min (v, (T)m); }
96template<typename T, typename U> static inline void max_it (T &v, U m) { v = max (v, (T)m); } 97template<typename T, typename U> static inline void max_it (T &v, U m) { v = max (v, (T)m); }
97template<typename T, typename U, typename V> static inline void clamp_it (T &v, U a, V b) { v = clamp (v, (T)a, (T)b); } 98template<typename T, typename U, typename V> static inline void clamp_it (T &v, U a, V b) { v = clamp (v, (T)a, (T)b); }
237#if 0 238#if 0
238// and has a max. error of 6 in the range -100..+100. 239// and has a max. error of 6 in the range -100..+100.
239#else 240#else
240// and has a max. error of 9 in the range -100..+100. 241// and has a max. error of 9 in the range -100..+100.
241#endif 242#endif
242inline int 243inline int
243idistance (int dx, int dy) 244idistance (int dx, int dy)
244{ 245{
245 unsigned int dx_ = abs (dx); 246 unsigned int dx_ = abs (dx);
246 unsigned int dy_ = abs (dy); 247 unsigned int dy_ = abs (dy);
247 248
248#if 0 249#if 0
249 return dx_ > dy_ 250 return dx_ > dy_
252#else 253#else
253 return dx_ + dy_ - min (dx_, dy_) * 5 / 8; 254 return dx_ + dy_ - min (dx_, dy_) * 5 / 8;
254#endif 255#endif
255} 256}
256 257
258// can be substantially faster than floor, if your value range allows for it
259template<typename T>
260inline T
261fastfloor (T x)
262{
263 return std::floor (x);
264}
265
266inline float
267fastfloor (float x)
268{
269 return sint32(x) - (x < 0);
270}
271
272inline double
273fastfloor (double x)
274{
275 return sint64(x) - (x < 0);
276}
277
257/* 278/*
258 * absdir(int): Returns a number between 1 and 8, which represent 279 * absdir(int): Returns a number between 1 and 8, which represent
259 * the "absolute" direction of a number (it actually takes care of 280 * the "absolute" direction of a number (it actually takes care of
260 * "overflow" in previous calculations of a direction). 281 * "overflow" in previous calculations of a direction).
261 */ 282 */
263absdir (int d) 284absdir (int d)
264{ 285{
265 return ((d - 1) & 7) + 1; 286 return ((d - 1) & 7) + 1;
266} 287}
267 288
268// avoid ctz name because netbsd or freebsd spams it's namespace with it
269#if GCC_VERSION(3,4)
270static inline int least_significant_bit (uint32_t x)
271{
272 return __builtin_ctz (x);
273}
274#else
275int least_significant_bit (uint32_t x);
276#endif
277
278#define for_all_bits_sparse_32(mask, idxvar) \ 289#define for_all_bits_sparse_32(mask, idxvar) \
279 for (uint32_t idxvar, mask_ = mask; \ 290 for (uint32_t idxvar, mask_ = mask; \
280 mask_ && ((idxvar = least_significant_bit (mask_)), mask_ &= ~(1 << idxvar), 1);) 291 mask_ && ((idxvar = ecb_ctz32 (mask_)), mask_ &= ~(1 << idxvar), 1);)
281 292
282extern ssize_t slice_alloc; // statistics 293extern ssize_t slice_alloc; // statistics
283 294
284void *salloc_ (int n) throw (std::bad_alloc); 295void *salloc_ (int n);
285void *salloc_ (int n, void *src) throw (std::bad_alloc); 296void *salloc_ (int n, void *src);
286 297
287// strictly the same as g_slice_alloc, but never returns 0 298// strictly the same as g_slice_alloc, but never returns 0
288template<typename T> 299template<typename T>
289inline T *salloc (int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T)); } 300inline T *salloc (int n = 1) { return (T *)salloc_ (n * sizeof (T)); }
290 301
291// also copies src into the new area, like "memdup" 302// also copies src into the new area, like "memdup"
292// if src is 0, clears the memory 303// if src is 0, clears the memory
293template<typename T> 304template<typename T>
294inline T *salloc (int n, T *src) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), (void *)src); } 305inline T *salloc (int n, T *src) { return (T *)salloc_ (n * sizeof (T), (void *)src); }
295 306
296// clears the memory 307// clears the memory
297template<typename T> 308template<typename T>
298inline T *salloc0(int n = 1) throw (std::bad_alloc) { return (T *)salloc_ (n * sizeof (T), 0); } 309inline T *salloc0(int n = 1) { return (T *)salloc_ (n * sizeof (T), 0); }
299 310
300// for symmetry 311// for symmetry
301template<typename T> 312template<typename T>
302inline void sfree (T *ptr, int n = 1) throw () 313inline void sfree (T *ptr, int n = 1) noexcept
303{ 314{
304 if (expect_true (ptr)) 315 if (expect_true (ptr))
305 { 316 {
306 slice_alloc -= n * sizeof (T); 317 slice_alloc -= n * sizeof (T);
307 if (DEBUG_POISON) memset (ptr, DEBUG_POISON, n * sizeof (T)); 318 if (DEBUG_POISON) memset (ptr, DEBUG_POISON, n * sizeof (T));
308 g_slice_free1 (n * sizeof (T), (void *)ptr); 319 g_slice_free1 (n * sizeof (T), (void *)ptr);
309 assert (slice_alloc >= 0);//D
310 } 320 }
311} 321}
312 322
313// nulls the pointer 323// nulls the pointer
314template<typename T> 324template<typename T>
315inline void sfree0 (T *&ptr, int n = 1) throw () 325inline void sfree0 (T *&ptr, int n = 1) noexcept
316{ 326{
317 sfree<T> (ptr, n); 327 sfree<T> (ptr, n);
318 ptr = 0; 328 ptr = 0;
319} 329}
320 330
388 typedef const Tp *const_pointer; 398 typedef const Tp *const_pointer;
389 typedef Tp &reference; 399 typedef Tp &reference;
390 typedef const Tp &const_reference; 400 typedef const Tp &const_reference;
391 typedef Tp value_type; 401 typedef Tp value_type;
392 402
393 template <class U> 403 template <class U>
394 struct rebind 404 struct rebind
395 { 405 {
396 typedef slice_allocator<U> other; 406 typedef slice_allocator<U> other;
397 }; 407 };
398 408
399 slice_allocator () throw () { } 409 slice_allocator () noexcept { }
400 slice_allocator (const slice_allocator &) throw () { } 410 slice_allocator (const slice_allocator &) noexcept { }
401 template<typename Tp2> 411 template<typename Tp2>
402 slice_allocator (const slice_allocator<Tp2> &) throw () { } 412 slice_allocator (const slice_allocator<Tp2> &) noexcept { }
403 413
404 ~slice_allocator () { } 414 ~slice_allocator () { }
405 415
406 pointer address (reference x) const { return &x; } 416 pointer address (reference x) const { return &x; }
407 const_pointer address (const_reference x) const { return &x; } 417 const_pointer address (const_reference x) const { return &x; }
414 void deallocate (pointer p, size_type n) 424 void deallocate (pointer p, size_type n)
415 { 425 {
416 sfree<Tp> (p, n); 426 sfree<Tp> (p, n);
417 } 427 }
418 428
419 size_type max_size () const throw () 429 size_type max_size () const noexcept
420 { 430 {
421 return size_t (-1) / sizeof (Tp); 431 return size_t (-1) / sizeof (Tp);
422 } 432 }
423 433
424 void construct (pointer p, const Tp &val) 434 void construct (pointer p, const Tp &val)
427 } 437 }
428 438
429 void destroy (pointer p) 439 void destroy (pointer p)
430 { 440 {
431 p->~Tp (); 441 p->~Tp ();
442 }
443};
444
445// basically a memory area, but refcounted
446struct refcnt_buf
447{
448 char *data;
449
450 refcnt_buf (size_t size = 0);
451 refcnt_buf (void *data, size_t size);
452
453 refcnt_buf (const refcnt_buf &src)
454 {
455 data = src.data;
456 inc ();
457 }
458
459 ~refcnt_buf ();
460
461 refcnt_buf &operator =(const refcnt_buf &src);
462
463 operator char *()
464 {
465 return data;
466 }
467
468 size_t size () const
469 {
470 return _size ();
471 }
472
473protected:
474 enum {
475 overhead = sizeof (uint32_t) * 2
476 };
477
478 uint32_t &_size () const
479 {
480 return ((unsigned int *)data)[-2];
481 }
482
483 uint32_t &_refcnt () const
484 {
485 return ((unsigned int *)data)[-1];
486 }
487
488 void _alloc (uint32_t size)
489 {
490 data = ((char *)salloc<char> (size + overhead)) + overhead;
491 _size () = size;
492 _refcnt () = 1;
493 }
494
495 void _dealloc ();
496
497 void inc ()
498 {
499 ++_refcnt ();
500 }
501
502 void dec ()
503 {
504 if (!--_refcnt ())
505 _dealloc ();
432 } 506 }
433}; 507};
434 508
435INTERFACE_CLASS (attachable) 509INTERFACE_CLASS (attachable)
436struct refcnt_base 510struct refcnt_base
453 // p if not null 527 // p if not null
454 refcnt_base::refcnt_t *refcnt_ref () { return p ? &p->refcnt : &refcnt_dummy; } 528 refcnt_base::refcnt_t *refcnt_ref () { return p ? &p->refcnt : &refcnt_dummy; }
455 529
456 void refcnt_dec () 530 void refcnt_dec ()
457 { 531 {
458 if (!is_constant (p)) 532 if (!ecb_is_constant (p))
459 --*refcnt_ref (); 533 --*refcnt_ref ();
460 else if (p) 534 else if (p)
461 --p->refcnt; 535 --p->refcnt;
462 } 536 }
463 537
464 void refcnt_inc () 538 void refcnt_inc ()
465 { 539 {
466 if (!is_constant (p)) 540 if (!ecb_is_constant (p))
467 ++*refcnt_ref (); 541 ++*refcnt_ref ();
468 else if (p) 542 else if (p)
469 ++p->refcnt; 543 ++p->refcnt;
470 } 544 }
471 545
514 // with good distribution. 588 // with good distribution.
515 // FNV-1a is faster on many cpus because the multiplication 589 // FNV-1a is faster on many cpus because the multiplication
516 // runs concurrently with the looping logic. 590 // runs concurrently with the looping logic.
517 // we modify the hash a bit to improve its distribution 591 // we modify the hash a bit to improve its distribution
518 uint32_t hash = STRHSH_NULL; 592 uint32_t hash = STRHSH_NULL;
519 593
520 while (*s) 594 while (*s)
521 hash = (hash ^ *s++) * 16777619U; 595 hash = (hash ^ *s++) * 16777619U;
522 596
523 return hash ^ (hash >> 16); 597 return hash ^ (hash >> 16);
524} 598}
525 599
526static inline uint32_t 600static inline uint32_t
527memhsh (const char *s, size_t len) 601memhsh (const char *s, size_t len)
528{ 602{
529 uint32_t hash = STRHSH_NULL; 603 uint32_t hash = STRHSH_NULL;
530 604
531 while (len--) 605 while (len--)
532 hash = (hash ^ *s++) * 16777619U; 606 hash = (hash ^ *s++) * 16777619U;
533 607
534 return hash; 608 return hash;
535} 609}
578 } 652 }
579}; 653};
580 654
581// This container blends advantages of linked lists 655// This container blends advantages of linked lists
582// (efficiency) with vectors (random access) by 656// (efficiency) with vectors (random access) by
583// by using an unordered vector and storing the vector 657// using an unordered vector and storing the vector
584// index inside the object. 658// index inside the object.
585// 659//
586// + memory-efficient on most 64 bit archs 660// + memory-efficient on most 64 bit archs
587// + O(1) insert/remove 661// + O(1) insert/remove
588// + free unique (but varying) id for inserted objects 662// + free unique (but varying) id for inserted objects
625 insert (&obj); 699 insert (&obj);
626 } 700 }
627 701
628 void erase (T *obj) 702 void erase (T *obj)
629 { 703 {
630 unsigned int pos = obj->*indexmember; 704 object_vector_index pos = obj->*indexmember;
631 obj->*indexmember = 0; 705 obj->*indexmember = 0;
632 706
633 if (pos < this->size ()) 707 if (pos < this->size ())
634 { 708 {
635 (*this)[pos - 1] = (*this)[this->size () - 1]; 709 (*this)[pos - 1] = (*this)[this->size () - 1];
731 805
732int similar_direction (int a, int b); 806int similar_direction (int a, int b);
733 807
734// like v?sprintf, but returns a "static" buffer 808// like v?sprintf, but returns a "static" buffer
735char *vformat (const char *format, va_list ap); 809char *vformat (const char *format, va_list ap);
736char *format (const char *format, ...) attribute ((format (printf, 1, 2))); 810char *format (const char *format, ...) ecb_attribute ((format (printf, 1, 2)));
737 811
738// safety-check player input which will become object->msg 812// safety-check player input which will become object->msg
739bool msg_is_safe (const char *msg); 813bool msg_is_safe (const char *msg);
740 814
741///////////////////////////////////////////////////////////////////////////// 815/////////////////////////////////////////////////////////////////////////////

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines