ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/common/shstr.C
Revision: 1.7
Committed: Sun Sep 3 23:33:00 2006 UTC (17 years, 8 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.6: +20 -16 lines
Log Message:
use alternative shstr representation, might or might not be faster, but does save code

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.3 * shstr.C
3 elmex 1.1 */
4    
5 root 1.3 #include <cstring>
6     #include <cstdlib>
7    
8     #include <tr1/unordered_set>
9 elmex 1.1
10     #include "shstr.h"
11    
12 root 1.3 struct hash
13     {
14     std::size_t operator ()(const char *s) const
15     {
16 elmex 1.1 unsigned long hash = 0;
17 root 1.3 unsigned int i = 0;
18 elmex 1.1
19 root 1.3 /* use the one-at-a-time hash function, which supposedly is
20     * better than the djb2-like one used by perl5.005, but
21     * certainly is better then the bug used here before.
22     * see http://burtleburtle.net/bob/hash/doobs.html
23 elmex 1.1 */
24 root 1.3 while (*s)
25     {
26     hash += *s++;
27     hash += hash << 10;
28     hash ^= hash >> 6;
29     }
30    
31     hash += hash << 3;
32     hash ^= hash >> 11;
33     hash += hash << 15;
34    
35     return hash;
36     }
37     };
38 elmex 1.1
39 root 1.3 struct equal
40     {
41     bool operator ()(const char *a, const char *b) const
42     {
43     return !strcmp (a, b);
44     }
45     };
46 elmex 1.1
47 root 1.3 typedef std::tr1::unordered_set<const char *, hash, equal> HT;
48 elmex 1.1
49 root 1.3 static HT ht;
50 elmex 1.1
51 root 1.7 static const char *makevec (const char *s)
52     {
53     int len = strlen (s);
54    
55     const char *v = (const char *)(2 + (int *)malloc (sizeof (int) * 2 + len + 1));
56    
57     shstr::length (v) = len;
58     shstr::refcnt (v) = 1;
59    
60     memcpy ((char *)v, s, len + 1);
61    
62     return s;
63     }
64    
65     const char *shstr::null = makevec ("<nil>");
66    
67 elmex 1.1 const char *
68 root 1.3 shstr::find (const char *s)
69     {
70 root 1.4 if (!s)
71     return s;
72    
73 root 1.3 HT::iterator i = ht.find (s);
74 elmex 1.1
75 root 1.3 return i != ht.end ()
76 root 1.5 ? *i
77 root 1.3 : 0;
78 elmex 1.1 }
79    
80     const char *
81 root 1.3 shstr::intern (const char *s)
82     {
83 root 1.4 if (!s)
84 root 1.7 return null;
85 elmex 1.1
86 root 1.4 if (const char *found = find (s))
87 root 1.5 {
88     ++refcnt (found);
89     return found;
90     }
91 elmex 1.1
92 root 1.7 s = makevec (s);
93     ht.insert (s);
94     return s;
95 elmex 1.1 }
96    
97 root 1.5 // periodically test refcounts == 0 for a few strings
98     // this is the ONLY thing that erases stuff from ht. keep it that way.
99 elmex 1.1 void
100 root 1.3 shstr::gc ()
101     {
102 root 1.5 static const char *curpos;
103    
104     HT::iterator i = curpos ? ht.find (curpos) : ht.begin ();
105    
106     if (i == ht.end ())
107     i = ht.begin ();
108    
109     // go through all strings roughly once every 4 minutes
110 root 1.6 int n = ht.size () / 256 + 16;
111    
112     for (;;)
113 root 1.5 {
114     if (i == ht.end ())
115     {
116     curpos = 0;
117     return;
118     }
119 root 1.6 else if (!--n)
120     break;
121     else if (!refcnt (*i))
122 root 1.5 {
123     HT::iterator o = i++;
124     const char *s = *o;
125     ht.erase (o);
126    
127     //printf ("GC %4d %3d %d >%s<%d\n", (int)ht.size (), n, shstr::refcnt (s), s, shstr::length (s));
128     free (-2 + (int *)s);
129     }
130     else
131     ++i;
132     }
133    
134     curpos = *i;
135 elmex 1.1 }
136    
137 root 1.5 //TODO: this should of course not be here
138 elmex 1.1 /* buf_overflow() - we don't want to exceed the buffer size of
139     * buf1 by adding on buf2! Returns true if overflow will occur.
140     */
141    
142     int
143     buf_overflow (const char *buf1, const char *buf2, int bufsize)
144     {
145 root 1.3 int len1 = 0, len2 = 0;
146 elmex 1.1
147     if (buf1)
148 root 1.2 len1 = strlen (buf1);
149 elmex 1.1 if (buf2)
150 root 1.2 len2 = strlen (buf2);
151 elmex 1.1 if ((len1 + len2) >= bufsize)
152 root 1.2 return 1;
153 elmex 1.1 return 0;
154     }
155