Mercurial > pidgin
annotate libgaim/stringref.c @ 15113:4a8c368df4ea
[gaim-migrate @ 17899]
Some touchups:
* If one of the parallel connection attempts fails immediately (i.e.
does not time out) then don't cancel the other one.
* Make sure we don't continue on to step 2 of the peer connection
process after we kick off the parallel gaim_proxy_connects(). It
looks like this would happen most of the time, because the
connect_timeout_timer would be added for the verified ip, so it
would NOT be added for the client ip, and so we wouldn't hit the
"return" call because it happens to be in the same block as the
second gaim_timeout_add() call.
* Add the connection timeout timer even if the gaim_proxy_connect() to
the verified ip returns NULL for some crazy reason.
I didn't actually test any of this. I should probably do that when
I get home.
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Wed, 06 Dec 2006 01:29:59 +0000 |
| parents | 500a8f54354e |
| children |
| rev | line source |
|---|---|
| 14192 | 1 /** |
| 2 * @file stringref.c Reference-counted immutable strings | |
| 3 * @ingroup core | |
| 4 * | |
| 5 * gaim | |
| 6 * | |
| 7 * Gaim is the legal property of its developers, whose names are too numerous | |
| 8 * to list here. Please refer to the COPYRIGHT file distributed with this | |
| 9 * source distribution. | |
| 10 * | |
| 11 * This program is free software; you can redistribute it and/or modify | |
| 12 * it under the terms of the GNU General Public License as published by | |
| 13 * the Free Software Foundation; either version 2 of the License, or | |
| 14 * (at your option) any later version. | |
| 15 * | |
| 16 * This program is distributed in the hope that it will be useful, | |
| 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 * GNU General Public License for more details. | |
| 20 * | |
| 21 * You should have received a copy of the GNU General Public License | |
| 22 * along with this program; if not, write to the Free Software | |
| 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 24 * | |
| 25 */ | |
| 26 | |
| 27 #include "internal.h" | |
| 28 | |
| 29 #include <string.h> | |
| 30 #include <stdarg.h> | |
| 31 | |
| 32 #include "debug.h" | |
| 33 #include "stringref.h" | |
| 34 | |
|
14926
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
35 /** |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
36 * The internal representation of a stringref. |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
37 * |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
38 * @note For this structure to be useful, the string contained within |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
39 * it must be immutable -- for this reason, do _not_ access it |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
40 * directly! |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
41 */ |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
42 struct _GaimStringref { |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
43 guint32 ref; /**< The reference count of this string. |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
44 * Note that reference counts are only |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
45 * 31 bits, and the high-order bit |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
46 * indicates whether this string is up |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
47 * for GC at the next idle handler... |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
48 * But you aren't going to touch this |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
49 * anyway, right? */ |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
50 char value[1]; /**< The string contained in this ref. |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
51 * Notice that it is simply "hanging |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
52 * off the end" of the ref ... this |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
53 * is to save an allocation. */ |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
54 }; |
|
500a8f54354e
[gaim-migrate @ 17698]
Richard Laager <rlaager@wiktel.com>
parents:
14192
diff
changeset
|
55 |
| 14192 | 56 #define REFCOUNT(x) ((x) & 0x7fffffff) |
| 57 | |
| 58 static GList *gclist = NULL; | |
| 59 | |
| 60 static void stringref_free(GaimStringref *stringref); | |
| 61 static gboolean gs_idle_cb(gpointer data); | |
| 62 | |
| 63 GaimStringref *gaim_stringref_new(const char *value) | |
| 64 { | |
| 65 GaimStringref *newref; | |
| 66 | |
| 67 if (value == NULL) | |
| 68 return NULL; | |
| 69 | |
| 70 newref = g_malloc(sizeof(GaimStringref) + strlen(value)); | |
| 71 strcpy(newref->value, value); | |
| 72 newref->ref = 1; | |
| 73 | |
| 74 return newref; | |
| 75 } | |
| 76 | |
| 77 GaimStringref *gaim_stringref_new_noref(const char *value) | |
| 78 { | |
| 79 GaimStringref *newref; | |
| 80 | |
| 81 if (value == NULL) | |
| 82 return NULL; | |
| 83 | |
| 84 newref = g_malloc(sizeof(GaimStringref) + strlen(value)); | |
| 85 strcpy(newref->value, value); | |
| 86 newref->ref = 0x80000000; | |
| 87 | |
| 88 if (gclist == NULL) | |
| 89 g_idle_add(gs_idle_cb, NULL); | |
| 90 gclist = g_list_prepend(gclist, newref); | |
| 91 | |
| 92 return newref; | |
| 93 } | |
| 94 | |
| 95 GaimStringref *gaim_stringref_printf(const char *format, ...) | |
| 96 { | |
| 97 GaimStringref *newref; | |
| 98 va_list ap; | |
| 99 | |
| 100 if (format == NULL) | |
| 101 return NULL; | |
| 102 | |
| 103 va_start(ap, format); | |
| 104 newref = g_malloc(sizeof(GaimStringref) + g_printf_string_upper_bound(format, ap)); | |
| 105 vsprintf(newref->value, format, ap); | |
| 106 va_end(ap); | |
| 107 newref->ref = 1; | |
| 108 | |
| 109 return newref; | |
| 110 } | |
| 111 | |
| 112 GaimStringref *gaim_stringref_ref(GaimStringref *stringref) | |
| 113 { | |
| 114 if (stringref == NULL) | |
| 115 return NULL; | |
| 116 stringref->ref++; | |
| 117 return stringref; | |
| 118 } | |
| 119 | |
| 120 void gaim_stringref_unref(GaimStringref *stringref) | |
| 121 { | |
| 122 if (stringref == NULL) | |
| 123 return; | |
| 124 if (REFCOUNT(--(stringref->ref)) == 0) { | |
| 125 if (stringref->ref & 0x80000000) | |
| 126 gclist = g_list_remove(gclist, stringref); | |
| 127 stringref_free(stringref); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 const char *gaim_stringref_value(const GaimStringref *stringref) | |
| 132 { | |
| 133 return (stringref == NULL ? NULL : stringref->value); | |
| 134 } | |
| 135 | |
| 136 int gaim_stringref_cmp(const GaimStringref *s1, const GaimStringref *s2) | |
| 137 { | |
| 138 return (s1 == s2 ? 0 : strcmp(gaim_stringref_value(s1), gaim_stringref_value(s2))); | |
| 139 } | |
| 140 | |
| 141 size_t gaim_stringref_len(const GaimStringref *stringref) | |
| 142 { | |
| 143 return strlen(gaim_stringref_value(stringref)); | |
| 144 } | |
| 145 | |
| 146 static void stringref_free(GaimStringref *stringref) | |
| 147 { | |
| 148 #ifdef DEBUG | |
| 149 if (REFCOUNT(stringref->ref) != 0) { | |
| 150 gaim_debug(GAIM_DEBUG_ERROR, "stringref", "Free of nonzero (%d) ref stringref!\n", REFCOUNT(stringref->ref)); | |
| 151 return; | |
| 152 } | |
| 153 #endif /* DEBUG */ | |
| 154 g_free(stringref); | |
| 155 } | |
| 156 | |
| 157 static gboolean gs_idle_cb(gpointer data) | |
| 158 { | |
| 159 GaimStringref *ref; | |
| 160 GList *del; | |
| 161 | |
| 162 while (gclist != NULL) { | |
| 163 ref = gclist->data; | |
| 164 if (REFCOUNT(ref->ref) == 0) { | |
| 165 stringref_free(ref); | |
| 166 } | |
| 167 del = gclist; | |
| 168 gclist = gclist->next; | |
| 169 g_list_free_1(del); | |
| 170 } | |
| 171 | |
| 172 return FALSE; | |
| 173 } |
