ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/include/util.h
Revision: 1.127
Committed: Sat Nov 17 23:40:02 2018 UTC (5 years, 6 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.126: +1 -0 lines
Log Message:
copyright update 2018

File Contents

# User Rev Content
1 root 1.46 /*
2 root 1.58 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 root 1.120 *
4 root 1.127 * Copyright (©) 2017,2018 Marc Alexander Lehmann / the Deliantra team
5 root 1.123 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,2016 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
6 root 1.120 *
7 root 1.90 * Deliantra is free software: you can redistribute it and/or modify it under
8     * the terms of the Affero GNU General Public License as published by the
9     * Free Software Foundation, either version 3 of the License, or (at your
10     * option) any later version.
11 root 1.120 *
12 root 1.51 * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16 root 1.120 *
17 root 1.90 * You should have received a copy of the Affero GNU General Public License
18     * and the GNU General Public License along with this program. If not, see
19     * <http://www.gnu.org/licenses/>.
20 root 1.120 *
21 root 1.58 * The authors can be reached via e-mail to <support@deliantra.net>
22 root 1.46 */
23    
24 root 1.1 #ifndef UTIL_H__
25     #define UTIL_H__
26    
27 root 1.93 #include <compiler.h>
28    
29 root 1.71 #define DEBUG_POISON 0x00 // poison memory before freeing it if != 0
30 root 1.70 #define DEBUG_SALLOC 0 // add a debug wrapper around all sallocs
31     #define PREFER_MALLOC 0 // use malloc and not the slice allocator
32 root 1.36
33 root 1.66 #include <pthread.h>
34    
35 root 1.11 #include <cstddef>
36 root 1.28 #include <cmath>
37 root 1.25 #include <new>
38     #include <vector>
39 root 1.11
40     #include <glib.h>
41    
42 root 1.25 #include <shstr.h>
43     #include <traits.h>
44    
45 root 1.65 #if DEBUG_SALLOC
46 root 1.60 # define g_slice_alloc0(s) debug_slice_alloc0(s)
47     # define g_slice_alloc(s) debug_slice_alloc(s)
48     # define g_slice_free1(s,p) debug_slice_free1(s,p)
49     void *g_slice_alloc (unsigned long size);
50     void *g_slice_alloc0 (unsigned long size);
51     void g_slice_free1 (unsigned long size, void *ptr);
52 root 1.67 #elif PREFER_MALLOC
53     # define g_slice_alloc0(s) calloc (1, (s))
54     # define g_slice_alloc(s) malloc ((s))
55 root 1.68 # define g_slice_free1(s,p) free ((p))
56 root 1.60 #endif
57    
58 root 1.49 // use C0X decltype for auto declarations until ISO C++ sanctifies them (if ever)
59 root 1.47 #define auto(var,expr) decltype(expr) var = (expr)
60 root 1.14
61 root 1.124 #if cplusplus_does_not_suck /* still sucks in codesize with gcc 6, although local types work now */
62 root 1.105 // does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm)
63 root 1.101 template<typename T, int N>
64 root 1.105 static inline int array_length (const T (&arr)[N])
65 root 1.101 {
66     return N;
67     }
68 root 1.105 #else
69     #define array_length(name) (sizeof (name) / sizeof (name [0]))
70     #endif
71 root 1.101
72 root 1.81 // very ugly macro that basically declares and initialises a variable
73 root 1.26 // that is in scope for the next statement only
74     // works only for stuff that can be assigned 0 and converts to false
75     // (note: works great for pointers)
76     // most ugly macro I ever wrote
77 root 1.48 #define statementvar(type, name, value) if (type name = 0) { } else if (((name) = (value)), 1)
78 root 1.26
79 root 1.27 // in range including end
80     #define IN_RANGE_INC(val,beg,end) \
81     ((unsigned int)(val) - (unsigned int)(beg) <= (unsigned int)(end) - (unsigned int)(beg))
82    
83     // in range excluding end
84     #define IN_RANGE_EXC(val,beg,end) \
85     ((unsigned int)(val) - (unsigned int)(beg) < (unsigned int)(end) - (unsigned int)(beg))
86    
87 root 1.126 ecb_cold void cleanup (const char *cause, bool make_core = false);
88     ecb_cold void fork_abort (const char *msg);
89 root 1.31
90 root 1.35 // rationale for using (U) not (T) is to reduce signed/unsigned issues,
91     // as a is often a constant while b is the variable. it is still a bug, though.
92 root 1.116 template<typename T, typename U> static inline T min (T a, U b) { return a < (T)b ? a : (T)b; }
93     template<typename T, typename U> static inline T max (T a, U b) { return a > (T)b ? a : (T)b; }
94 root 1.35 template<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; }
95 root 1.32
96 root 1.80 template<typename T, typename U> static inline void min_it (T &v, U m) { v = min (v, (T)m); }
97     template<typename T, typename U> static inline void max_it (T &v, U m) { v = max (v, (T)m); }
98     template<typename T, typename U, typename V> static inline void clamp_it (T &v, U a, V b) { v = clamp (v, (T)a, (T)b); }
99 root 1.78
100 root 1.32 template<typename T, typename U> static inline void swap (T& a, U& b) { T t=a; a=(T)b; b=(U)t; }
101    
102 root 1.63 template<typename T, typename U, typename V> static inline T min (T a, U b, V c) { return min (a, min (b, c)); }
103     template<typename T, typename U, typename V> static inline T max (T a, U b, V c) { return max (a, max (b, c)); }
104    
105 root 1.79 // sign returns -1 or +1
106     template<typename T>
107     static inline T sign (T v) { return v < 0 ? -1 : +1; }
108     // relies on 2c representation
109     template<>
110 root 1.103 inline sint8 sign (sint8 v) { return 1 - (sint8 (uint8 (v) >> 7) * 2); }
111     template<>
112     inline sint16 sign (sint16 v) { return 1 - (sint16 (uint16 (v) >> 15) * 2); }
113     template<>
114     inline sint32 sign (sint32 v) { return 1 - (sint32 (uint32 (v) >> 31) * 2); }
115 root 1.79
116     // sign0 returns -1, 0 or +1
117     template<typename T>
118     static inline T sign0 (T v) { return v ? sign (v) : 0; }
119    
120 root 1.113 //clashes with C++0x
121 root 1.99 template<typename T, typename U>
122     static inline T copysign (T a, U b) { return a > 0 ? b : -b; }
123    
124 root 1.88 // div* only work correctly for div > 0
125 root 1.78 // div, with correct rounding (< 0.5 downwards, >=0.5 upwards)
126 root 1.88 template<typename T> static inline T div (T val, T div)
127     {
128     return expect_false (val < 0) ? - ((-val + (div - 1) / 2) / div) : (val + div / 2) / div;
129     }
130 root 1.105
131     template<> inline float div (float val, float div) { return val / div; }
132     template<> inline double div (double val, double div) { return val / div; }
133    
134 root 1.78 // div, round-up
135 root 1.88 template<typename T> static inline T div_ru (T val, T div)
136     {
137     return expect_false (val < 0) ? - ((-val ) / div) : (val + div - 1) / div;
138     }
139 root 1.78 // div, round-down
140 root 1.88 template<typename T> static inline T div_rd (T val, T div)
141     {
142     return expect_false (val < 0) ? - ((-val + (div - 1) ) / div) : (val ) / div;
143     }
144 root 1.78
145 root 1.88 // lerp* only work correctly for min_in < max_in
146     // Linear intERPolate, scales val from min_in..max_in to min_out..max_out
147 root 1.44 template<typename T>
148     static inline T
149     lerp (T val, T min_in, T max_in, T min_out, T max_out)
150     {
151 root 1.78 return min_out + div <T> ((val - min_in) * (max_out - min_out), max_in - min_in);
152     }
153    
154     // lerp, round-down
155     template<typename T>
156     static inline T
157     lerp_rd (T val, T min_in, T max_in, T min_out, T max_out)
158     {
159     return min_out + div_rd<T> ((val - min_in) * (max_out - min_out), max_in - min_in);
160     }
161    
162     // lerp, round-up
163     template<typename T>
164     static inline T
165     lerp_ru (T val, T min_in, T max_in, T min_out, T max_out)
166     {
167     return min_out + div_ru<T> ((val - min_in) * (max_out - min_out), max_in - min_in);
168 root 1.44 }
169    
170 root 1.37 // lots of stuff taken from FXT
171    
172     /* Rotate right. This is used in various places for checksumming */
173 root 1.38 //TODO: that sucks, use a better checksum algo
174 root 1.37 static inline uint32_t
175 root 1.38 rotate_right (uint32_t c, uint32_t count = 1)
176 root 1.37 {
177 root 1.38 return (c << (32 - count)) | (c >> count);
178     }
179    
180     static inline uint32_t
181     rotate_left (uint32_t c, uint32_t count = 1)
182     {
183     return (c >> (32 - count)) | (c << count);
184 root 1.37 }
185    
186     // Return abs(a-b)
187     // Both a and b must not have the most significant bit set
188     static inline uint32_t
189     upos_abs_diff (uint32_t a, uint32_t b)
190     {
191     long d1 = b - a;
192     long d2 = (d1 & (d1 >> 31)) << 1;
193    
194     return d1 - d2; // == (b - d) - (a + d);
195     }
196    
197     // Both a and b must not have the most significant bit set
198     static inline uint32_t
199     upos_min (uint32_t a, uint32_t b)
200     {
201     int32_t d = b - a;
202     d &= d >> 31;
203     return a + d;
204     }
205    
206     // Both a and b must not have the most significant bit set
207     static inline uint32_t
208     upos_max (uint32_t a, uint32_t b)
209     {
210     int32_t d = b - a;
211     d &= d >> 31;
212     return b - d;
213     }
214    
215 root 1.94 // this is much faster than crossfire's original algorithm
216 root 1.28 // on modern cpus
217     inline int
218     isqrt (int n)
219     {
220     return (int)sqrtf ((float)n);
221     }
222    
223 root 1.92 // this is kind of like the ^^ operator, if it would exist, without sequence point.
224     // more handy than it looks like, due to the implicit !! done on its arguments
225     inline bool
226     logical_xor (bool a, bool b)
227     {
228     return a != b;
229     }
230    
231     inline bool
232     logical_implies (bool a, bool b)
233     {
234     return a <= b;
235     }
236    
237 root 1.28 // this is only twice as fast as naive sqrtf (dx*dy+dy*dy)
238     #if 0
239     // and has a max. error of 6 in the range -100..+100.
240     #else
241     // and has a max. error of 9 in the range -100..+100.
242     #endif
243 root 1.122 inline int
244 root 1.28 idistance (int dx, int dy)
245 root 1.122 {
246 root 1.28 unsigned int dx_ = abs (dx);
247     unsigned int dy_ = abs (dy);
248    
249     #if 0
250     return dx_ > dy_
251     ? (dx_ * 61685 + dy_ * 26870) >> 16
252     : (dy_ * 61685 + dx_ * 26870) >> 16;
253     #else
254 root 1.30 return dx_ + dy_ - min (dx_, dy_) * 5 / 8;
255 root 1.28 #endif
256     }
257    
258 root 1.115 // can be substantially faster than floor, if your value range allows for it
259     template<typename T>
260     inline T
261     fastfloor (T x)
262     {
263     return std::floor (x);
264     }
265    
266     inline float
267     fastfloor (float x)
268     {
269     return sint32(x) - (x < 0);
270     }
271    
272     inline double
273     fastfloor (double x)
274     {
275     return sint64(x) - (x < 0);
276     }
277    
278 root 1.29 /*
279     * absdir(int): Returns a number between 1 and 8, which represent
280     * the "absolute" direction of a number (it actually takes care of
281     * "overflow" in previous calculations of a direction).
282     */
283     inline int
284     absdir (int d)
285     {
286     return ((d - 1) & 7) + 1;
287     }
288 root 1.28
289 root 1.96 #define for_all_bits_sparse_32(mask, idxvar) \
290     for (uint32_t idxvar, mask_ = mask; \
291 root 1.126 mask_ && ((idxvar = ecb_ctz32 (mask_)), mask_ &= ~(1 << idxvar), 1);)
292 root 1.96
293 root 1.67 extern ssize_t slice_alloc; // statistics
294    
295 root 1.125 void *salloc_ (int n);
296     void *salloc_ (int n, void *src);
297 root 1.67
298     // strictly the same as g_slice_alloc, but never returns 0
299     template<typename T>
300 root 1.125 inline T *salloc (int n = 1) { return (T *)salloc_ (n * sizeof (T)); }
301 root 1.67
302     // also copies src into the new area, like "memdup"
303     // if src is 0, clears the memory
304     template<typename T>
305 root 1.125 inline T *salloc (int n, T *src) { return (T *)salloc_ (n * sizeof (T), (void *)src); }
306 root 1.67
307     // clears the memory
308     template<typename T>
309 root 1.125 inline T *salloc0(int n = 1) { return (T *)salloc_ (n * sizeof (T), 0); }
310 root 1.67
311     // for symmetry
312     template<typename T>
313 root 1.125 inline void sfree (T *ptr, int n = 1) noexcept
314 root 1.67 {
315     if (expect_true (ptr))
316     {
317     slice_alloc -= n * sizeof (T);
318 root 1.70 if (DEBUG_POISON) memset (ptr, DEBUG_POISON, n * sizeof (T));
319 root 1.67 g_slice_free1 (n * sizeof (T), (void *)ptr);
320     }
321     }
322 root 1.57
323 root 1.72 // nulls the pointer
324     template<typename T>
325 root 1.125 inline void sfree0 (T *&ptr, int n = 1) noexcept
326 root 1.72 {
327     sfree<T> (ptr, n);
328     ptr = 0;
329     }
330    
331 root 1.1 // makes dynamically allocated objects zero-initialised
332     struct zero_initialised
333     {
334 root 1.11 void *operator new (size_t s, void *p)
335     {
336     memset (p, 0, s);
337     return p;
338     }
339    
340     void *operator new (size_t s)
341     {
342 root 1.67 return salloc0<char> (s);
343 root 1.11 }
344    
345     void *operator new[] (size_t s)
346     {
347 root 1.67 return salloc0<char> (s);
348 root 1.11 }
349    
350     void operator delete (void *p, size_t s)
351     {
352 root 1.67 sfree ((char *)p, s);
353 root 1.11 }
354    
355     void operator delete[] (void *p, size_t s)
356     {
357 root 1.67 sfree ((char *)p, s);
358 root 1.11 }
359     };
360    
361 root 1.73 // makes dynamically allocated objects zero-initialised
362     struct slice_allocated
363     {
364     void *operator new (size_t s, void *p)
365     {
366     return p;
367     }
368    
369     void *operator new (size_t s)
370     {
371     return salloc<char> (s);
372     }
373    
374     void *operator new[] (size_t s)
375     {
376     return salloc<char> (s);
377     }
378    
379     void operator delete (void *p, size_t s)
380     {
381     sfree ((char *)p, s);
382     }
383    
384     void operator delete[] (void *p, size_t s)
385     {
386     sfree ((char *)p, s);
387     }
388     };
389    
390 root 1.11 // a STL-compatible allocator that uses g_slice
391     // boy, this is verbose
392     template<typename Tp>
393     struct slice_allocator
394     {
395     typedef size_t size_type;
396     typedef ptrdiff_t difference_type;
397     typedef Tp *pointer;
398     typedef const Tp *const_pointer;
399     typedef Tp &reference;
400     typedef const Tp &const_reference;
401     typedef Tp value_type;
402    
403 root 1.122 template <class U>
404 root 1.11 struct rebind
405     {
406     typedef slice_allocator<U> other;
407     };
408    
409 root 1.125 slice_allocator () noexcept { }
410     slice_allocator (const slice_allocator &) noexcept { }
411 root 1.11 template<typename Tp2>
412 root 1.125 slice_allocator (const slice_allocator<Tp2> &) noexcept { }
413 root 1.11
414     ~slice_allocator () { }
415    
416     pointer address (reference x) const { return &x; }
417     const_pointer address (const_reference x) const { return &x; }
418    
419     pointer allocate (size_type n, const_pointer = 0)
420     {
421 root 1.18 return salloc<Tp> (n);
422 root 1.11 }
423    
424     void deallocate (pointer p, size_type n)
425     {
426 root 1.19 sfree<Tp> (p, n);
427 root 1.11 }
428    
429 root 1.125 size_type max_size () const noexcept
430 root 1.11 {
431     return size_t (-1) / sizeof (Tp);
432     }
433    
434     void construct (pointer p, const Tp &val)
435     {
436     ::new (p) Tp (val);
437     }
438    
439     void destroy (pointer p)
440     {
441     p->~Tp ();
442     }
443 root 1.1 };
444    
445 root 1.117 // basically a memory area, but refcounted
446     struct 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 root 1.121 inc ();
457 root 1.117 }
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    
473     protected:
474     enum {
475 root 1.121 overhead = sizeof (uint32_t) * 2
476 root 1.117 };
477    
478 root 1.121 uint32_t &_size () const
479 root 1.117 {
480     return ((unsigned int *)data)[-2];
481     }
482    
483 root 1.121 uint32_t &_refcnt () const
484 root 1.117 {
485     return ((unsigned int *)data)[-1];
486     }
487    
488 root 1.121 void _alloc (uint32_t size)
489 root 1.117 {
490     data = ((char *)salloc<char> (size + overhead)) + overhead;
491     _size () = size;
492     _refcnt () = 1;
493     }
494    
495 root 1.121 void _dealloc ();
496    
497     void inc ()
498     {
499     ++_refcnt ();
500     }
501    
502 root 1.117 void dec ()
503     {
504     if (!--_refcnt ())
505 root 1.121 _dealloc ();
506 root 1.117 }
507     };
508    
509 root 1.54 INTERFACE_CLASS (attachable)
510     struct refcnt_base
511     {
512     typedef int refcnt_t;
513     mutable refcnt_t ACC (RW, refcnt);
514    
515     MTH void refcnt_inc () const { ++refcnt; }
516     MTH void refcnt_dec () const { --refcnt; }
517    
518     refcnt_base () : refcnt (0) { }
519     };
520    
521 root 1.56 // to avoid branches with more advanced compilers
522 root 1.54 extern refcnt_base::refcnt_t refcnt_dummy;
523    
524 root 1.7 template<class T>
525     struct refptr
526     {
527 root 1.54 // p if not null
528     refcnt_base::refcnt_t *refcnt_ref () { return p ? &p->refcnt : &refcnt_dummy; }
529    
530     void refcnt_dec ()
531     {
532 root 1.126 if (!ecb_is_constant (p))
533 root 1.54 --*refcnt_ref ();
534     else if (p)
535     --p->refcnt;
536     }
537    
538     void refcnt_inc ()
539     {
540 root 1.126 if (!ecb_is_constant (p))
541 root 1.54 ++*refcnt_ref ();
542     else if (p)
543     ++p->refcnt;
544     }
545    
546 root 1.7 T *p;
547    
548     refptr () : p(0) { }
549 root 1.54 refptr (const refptr<T> &p) : p(p.p) { refcnt_inc (); }
550     refptr (T *p) : p(p) { refcnt_inc (); }
551     ~refptr () { refcnt_dec (); }
552 root 1.7
553     const refptr<T> &operator =(T *o)
554     {
555 root 1.54 // if decrementing ever destroys we need to reverse the order here
556     refcnt_dec ();
557 root 1.7 p = o;
558 root 1.54 refcnt_inc ();
559 root 1.7 return *this;
560     }
561    
562 root 1.54 const refptr<T> &operator =(const refptr<T> &o)
563 root 1.7 {
564     *this = o.p;
565     return *this;
566     }
567    
568     T &operator * () const { return *p; }
569 root 1.54 T *operator ->() const { return p; }
570 root 1.7
571     operator T *() const { return p; }
572     };
573    
574 root 1.24 typedef refptr<maptile> maptile_ptr;
575 root 1.22 typedef refptr<object> object_ptr;
576     typedef refptr<archetype> arch_ptr;
577 root 1.24 typedef refptr<client> client_ptr;
578     typedef refptr<player> player_ptr;
579 root 1.102 typedef refptr<region> region_ptr;
580 root 1.22
581 root 1.95 #define STRHSH_NULL 2166136261
582    
583     static inline uint32_t
584     strhsh (const char *s)
585     {
586     // use FNV-1a hash (http://isthe.com/chongo/tech/comp/fnv/)
587     // it is about twice as fast as the one-at-a-time one,
588     // with good distribution.
589     // FNV-1a is faster on many cpus because the multiplication
590     // runs concurrently with the looping logic.
591 root 1.112 // we modify the hash a bit to improve its distribution
592 root 1.95 uint32_t hash = STRHSH_NULL;
593 root 1.122
594 root 1.95 while (*s)
595 root 1.98 hash = (hash ^ *s++) * 16777619U;
596 root 1.95
597 root 1.112 return hash ^ (hash >> 16);
598 root 1.95 }
599    
600     static inline uint32_t
601     memhsh (const char *s, size_t len)
602     {
603     uint32_t hash = STRHSH_NULL;
604 root 1.122
605 root 1.95 while (len--)
606 root 1.98 hash = (hash ^ *s++) * 16777619U;
607 root 1.95
608     return hash;
609     }
610    
611 root 1.4 struct str_hash
612     {
613     std::size_t operator ()(const char *s) const
614     {
615 root 1.95 return strhsh (s);
616     }
617 root 1.4
618 root 1.95 std::size_t operator ()(const shstr &s) const
619     {
620     return strhsh (s);
621 root 1.4 }
622     };
623    
624     struct str_equal
625     {
626     bool operator ()(const char *a, const char *b) const
627     {
628     return !strcmp (a, b);
629     }
630     };
631    
632 root 1.49 // Mostly the same as std::vector, but insert/erase can reorder
633 root 1.52 // the elements, making append(=insert)/remove O(1) instead of O(n).
634 root 1.49 //
635 root 1.52 // NOTE: only some forms of erase are available
636 root 1.26 template<class T>
637     struct unordered_vector : std::vector<T, slice_allocator<T> >
638 root 1.6 {
639 root 1.11 typedef typename unordered_vector::iterator iterator;
640 root 1.6
641     void erase (unsigned int pos)
642     {
643     if (pos < this->size () - 1)
644     (*this)[pos] = (*this)[this->size () - 1];
645    
646     this->pop_back ();
647     }
648    
649     void erase (iterator i)
650     {
651     erase ((unsigned int )(i - this->begin ()));
652     }
653     };
654    
655 root 1.49 // This container blends advantages of linked lists
656     // (efficiency) with vectors (random access) by
657 root 1.119 // using an unordered vector and storing the vector
658 root 1.49 // index inside the object.
659     //
660     // + memory-efficient on most 64 bit archs
661     // + O(1) insert/remove
662     // + free unique (but varying) id for inserted objects
663     // + cache-friendly iteration
664     // - only works for pointers to structs
665     //
666     // NOTE: only some forms of erase/insert are available
667 root 1.50 typedef int object_vector_index;
668    
669     template<class T, object_vector_index T::*indexmember>
670 root 1.26 struct object_vector : std::vector<T *, slice_allocator<T *> >
671     {
672 root 1.48 typedef typename object_vector::iterator iterator;
673    
674     bool contains (const T *obj) const
675     {
676 root 1.50 return obj->*indexmember;
677 root 1.48 }
678    
679     iterator find (const T *obj)
680     {
681 root 1.50 return obj->*indexmember
682     ? this->begin () + obj->*indexmember - 1
683 root 1.48 : this->end ();
684     }
685    
686 root 1.53 void push_back (T *obj)
687     {
688     std::vector<T *, slice_allocator<T *> >::push_back (obj);
689     obj->*indexmember = this->size ();
690     }
691    
692 root 1.26 void insert (T *obj)
693     {
694     push_back (obj);
695     }
696    
697     void insert (T &obj)
698     {
699     insert (&obj);
700     }
701    
702     void erase (T *obj)
703     {
704 root 1.119 object_vector_index pos = obj->*indexmember;
705 root 1.50 obj->*indexmember = 0;
706 root 1.26
707     if (pos < this->size ())
708     {
709     (*this)[pos - 1] = (*this)[this->size () - 1];
710 root 1.50 (*this)[pos - 1]->*indexmember = pos;
711 root 1.26 }
712    
713     this->pop_back ();
714     }
715    
716     void erase (T &obj)
717     {
718 root 1.50 erase (&obj);
719 root 1.26 }
720     };
721    
722 root 1.111 /////////////////////////////////////////////////////////////////////////////
723    
724     // something like a vector or stack, but without
725     // out of bounds checking
726     template<typename T>
727     struct fixed_stack
728     {
729     T *data;
730     int size;
731     int max;
732    
733     fixed_stack ()
734     : size (0), data (0)
735     {
736     }
737    
738     fixed_stack (int max)
739     : size (0), max (max)
740     {
741     data = salloc<T> (max);
742     }
743    
744     void reset (int new_max)
745     {
746     sfree (data, max);
747     size = 0;
748     max = new_max;
749     data = salloc<T> (max);
750     }
751    
752     void free ()
753     {
754     sfree (data, max);
755     data = 0;
756     }
757    
758     ~fixed_stack ()
759     {
760     sfree (data, max);
761     }
762    
763     T &operator[](int idx)
764     {
765     return data [idx];
766     }
767    
768     void push (T v)
769     {
770     data [size++] = v;
771     }
772    
773     T &pop ()
774     {
775     return data [--size];
776     }
777    
778     T remove (int idx)
779     {
780     T v = data [idx];
781    
782     data [idx] = data [--size];
783    
784     return v;
785     }
786     };
787    
788     /////////////////////////////////////////////////////////////////////////////
789    
790 root 1.10 // basically does what strncpy should do, but appends "..." to strings exceeding length
791 root 1.87 // returns the number of bytes actually used (including \0)
792     int assign (char *dst, const char *src, int maxsize);
793 root 1.10
794     // type-safe version of assign
795 root 1.9 template<int N>
796 root 1.87 inline int assign (char (&dst)[N], const char *src)
797 root 1.9 {
798 root 1.87 return assign ((char *)&dst, src, N);
799 root 1.9 }
800    
801 root 1.17 typedef double tstamp;
802    
803 root 1.59 // return current time as timestamp
804 root 1.17 tstamp now ();
805    
806 root 1.25 int similar_direction (int a, int b);
807    
808 root 1.91 // like v?sprintf, but returns a "static" buffer
809     char *vformat (const char *format, va_list ap);
810 root 1.126 char *format (const char *format, ...) ecb_attribute ((format (printf, 1, 2)));
811 root 1.43
812 sf-marcmagus 1.89 // safety-check player input which will become object->msg
813     bool msg_is_safe (const char *msg);
814    
815 root 1.66 /////////////////////////////////////////////////////////////////////////////
816     // threads, very very thin wrappers around pthreads
817    
818     struct thread
819     {
820     pthread_t id;
821    
822     void start (void *(*start_routine)(void *), void *arg = 0);
823    
824     void cancel ()
825     {
826     pthread_cancel (id);
827     }
828    
829     void *join ()
830     {
831     void *ret;
832    
833     if (pthread_join (id, &ret))
834     cleanup ("pthread_join failed", 1);
835    
836     return ret;
837     }
838     };
839    
840     // note that mutexes are not classes
841     typedef pthread_mutex_t smutex;
842    
843     #if __linux && defined (PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP)
844     #define SMUTEX_INITIALISER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
845     #else
846     #define SMUTEX_INITIALISER PTHREAD_MUTEX_INITIALIZER
847     #endif
848    
849     #define SMUTEX(name) smutex name = SMUTEX_INITIALISER
850 root 1.68 #define SMUTEX_LOCK(name) pthread_mutex_lock (&(name))
851 root 1.66 #define SMUTEX_UNLOCK(name) pthread_mutex_unlock (&(name))
852    
853 root 1.68 typedef pthread_cond_t scond;
854    
855     #define SCOND(name) scond name = PTHREAD_COND_INITIALIZER
856     #define SCOND_SIGNAL(name) pthread_cond_signal (&(name))
857     #define SCOND_BROADCAST(name) pthread_cond_broadcast (&(name))
858     #define SCOND_WAIT(name,mutex) pthread_cond_wait (&(name), &(mutex))
859    
860 root 1.1 #endif
861