aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llcommon
diff options
context:
space:
mode:
authorJacek Antonelli2011-05-08 15:13:37 -0500
committerJacek Antonelli2011-05-08 15:50:49 -0500
commit7278f0254a3944bd2bcbf1e855fb0d90c3086a27 (patch)
tree5d7ecb81ebf1a07482f0a7d3d13acd7f18360c0b /linden/indra/llcommon
parentImprudence 1.3.1 released. (diff)
parentChanged version to Experimental 2011.04.19 (diff)
downloadmeta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.zip
meta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.tar.gz
meta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.tar.bz2
meta-impy-7278f0254a3944bd2bcbf1e855fb0d90c3086a27.tar.xz
Merged Experimental branch (exp) back into main line (next).
Git thought many files (almost 100) had merge conflicts. But, after resolving the conflicts (which were mostly trivial), almost all the files turned out to be the same as in the exp branch. So, the conflicts are not listed here. Check the diff between commit 244ffe8 and this commit to see what really changed.
Diffstat (limited to 'linden/indra/llcommon')
-rw-r--r--linden/indra/llcommon/CMakeLists.txt24
-rw-r--r--linden/indra/llcommon/aiaprpool.cpp198
-rw-r--r--linden/indra/llcommon/aiaprpool.h240
-rw-r--r--linden/indra/llcommon/aithreadsafe.h463
-rw-r--r--linden/indra/llcommon/imageids.cpp79
-rw-r--r--linden/indra/llcommon/imageids.h58
-rw-r--r--linden/indra/llcommon/indra_constants.cpp47
-rw-r--r--linden/indra/llcommon/indra_constants.h22
-rw-r--r--linden/indra/llcommon/linden_common.h19
-rw-r--r--linden/indra/llcommon/llapp.cpp7
-rw-r--r--linden/indra/llcommon/llapp.h13
-rw-r--r--linden/indra/llcommon/llapr.cpp299
-rw-r--r--linden/indra/llcommon/llapr.h83
-rw-r--r--linden/indra/llcommon/llassettype.h2
-rw-r--r--linden/indra/llcommon/llavatarname.cpp150
-rw-r--r--linden/indra/llcommon/llavatarname.h105
-rw-r--r--linden/indra/llcommon/llbase32.h2
-rw-r--r--linden/indra/llcommon/llbase64.h2
-rw-r--r--linden/indra/llcommon/llcommon.cpp13
-rw-r--r--linden/indra/llcommon/llcommon.h4
-rw-r--r--linden/indra/llcommon/llcrc.h2
-rw-r--r--linden/indra/llcommon/llcriticaldamp.h2
-rw-r--r--linden/indra/llcommon/llcursortypes.h2
-rw-r--r--linden/indra/llcommon/lldate.cpp2
-rw-r--r--linden/indra/llcommon/lldate.h11
-rw-r--r--linden/indra/llcommon/llerror.cpp12
-rw-r--r--linden/indra/llcommon/llerror.h10
-rw-r--r--linden/indra/llcommon/llerrorcontrol.h45
-rw-r--r--linden/indra/llcommon/llerrorthread.cpp1
-rw-r--r--linden/indra/llcommon/llerrorthread.h2
-rw-r--r--linden/indra/llcommon/llevent.h10
-rw-r--r--linden/indra/llcommon/llfasttimer.cpp1
-rw-r--r--linden/indra/llcommon/llfasttimer.h4
-rw-r--r--linden/indra/llcommon/llfile.cpp2
-rw-r--r--linden/indra/llcommon/llfile.h10
-rw-r--r--linden/indra/llcommon/llfindlocale.cpp2
-rw-r--r--linden/indra/llcommon/llfindlocale.h4
-rw-r--r--linden/indra/llcommon/llfixedbuffer.cpp3
-rw-r--r--linden/indra/llcommon/llfixedbuffer.h2
-rw-r--r--linden/indra/llcommon/llformat.h2
-rw-r--r--linden/indra/llcommon/llframetimer.h2
-rw-r--r--linden/indra/llcommon/llheartbeat.h2
-rw-r--r--linden/indra/llcommon/llliveappconfig.h2
-rw-r--r--linden/indra/llcommon/lllivefile.h2
-rw-r--r--linden/indra/llcommon/lllog.h2
-rwxr-xr-x[-rw-r--r--]linden/indra/llcommon/lllslconstants.h5
-rw-r--r--linden/indra/llcommon/llmd5.cpp1
-rw-r--r--linden/indra/llcommon/llmd5.h2
-rw-r--r--linden/indra/llcommon/llmemory.cpp15
-rw-r--r--linden/indra/llcommon/llmemory.h10
-rw-r--r--linden/indra/llcommon/llmemorystream.h4
-rw-r--r--linden/indra/llcommon/llmemtype.h2
-rw-r--r--linden/indra/llcommon/llmetrics.h2
-rw-r--r--linden/indra/llcommon/llmortician.h2
-rw-r--r--linden/indra/llcommon/llpreprocessor.h62
-rw-r--r--linden/indra/llcommon/llprocesslauncher.cpp346
-rw-r--r--linden/indra/llcommon/llprocesslauncher.h91
-rw-r--r--linden/indra/llcommon/llqueuedthread.cpp1
-rw-r--r--linden/indra/llcommon/llqueuedthread.h4
-rw-r--r--linden/indra/llcommon/llrand.h12
-rw-r--r--linden/indra/llcommon/llrun.h6
-rw-r--r--linden/indra/llcommon/llscopedvolatileaprpool.h58
-rw-r--r--linden/indra/llcommon/llsd.cpp12
-rw-r--r--linden/indra/llcommon/llsd.h4
-rw-r--r--linden/indra/llcommon/llsdserialize.h18
-rw-r--r--linden/indra/llcommon/llsdserialize_xml.cpp2
-rw-r--r--linden/indra/llcommon/llsdutil.h22
-rw-r--r--linden/indra/llcommon/llsecondlifeurls.h8
-rw-r--r--linden/indra/llcommon/llsimplehash.h2
-rw-r--r--linden/indra/llcommon/llstat.h14
-rw-r--r--linden/indra/llcommon/llstreamtools.h36
-rw-r--r--linden/indra/llcommon/llstring.cpp37
-rw-r--r--linden/indra/llcommon/llstring.h114
-rw-r--r--linden/indra/llcommon/llstringtable.h8
-rw-r--r--linden/indra/llcommon/llsys.cpp186
-rw-r--r--linden/indra/llcommon/llsys.h25
-rw-r--r--linden/indra/llcommon/llthread.cpp117
-rw-r--r--linden/indra/llcommon/llthread.h194
-rw-r--r--linden/indra/llcommon/lltimer.cpp32
-rw-r--r--linden/indra/llcommon/lltimer.h28
-rw-r--r--linden/indra/llcommon/lluri.h4
-rw-r--r--linden/indra/llcommon/lluuid.h9
-rw-r--r--linden/indra/llcommon/llworkerthread.cpp3
-rw-r--r--linden/indra/llcommon/llworkerthread.h6
-rw-r--r--linden/indra/llcommon/metaclass.h2
-rw-r--r--linden/indra/llcommon/metaproperty.h2
-rw-r--r--linden/indra/llcommon/reflective.h2
-rw-r--r--linden/indra/llcommon/stdtypes.h9
-rw-r--r--linden/indra/llcommon/timing.h2
-rw-r--r--linden/indra/llcommon/u64.h10
90 files changed, 2731 insertions, 769 deletions
diff --git a/linden/indra/llcommon/CMakeLists.txt b/linden/indra/llcommon/CMakeLists.txt
index 3f14be6..ed04ca6 100644
--- a/linden/indra/llcommon/CMakeLists.txt
+++ b/linden/indra/llcommon/CMakeLists.txt
@@ -4,6 +4,7 @@ project(llcommon)
4 4
5include(00-Common) 5include(00-Common)
6include(LLCommon) 6include(LLCommon)
7include(Linking)
7 8
8include_directories( 9include_directories(
9 ${EXPAT_INCLUDE_DIRS} 10 ${EXPAT_INCLUDE_DIRS}
@@ -12,9 +13,13 @@ include_directories(
12 ) 13 )
13 14
14set(llcommon_SOURCE_FILES 15set(llcommon_SOURCE_FILES
16 aiaprpool.cpp
17 imageids.cpp
18 indra_constants.cpp
15 llapp.cpp 19 llapp.cpp
16 llapr.cpp 20 llapr.cpp
17 llassettype.cpp 21 llassettype.cpp
22 llavatarname.cpp
18 llbase32.cpp 23 llbase32.cpp
19 llbase64.cpp 24 llbase64.cpp
20 llcommon.cpp 25 llcommon.cpp
@@ -42,6 +47,7 @@ set(llcommon_SOURCE_FILES
42 llmetrics.cpp 47 llmetrics.cpp
43 llmortician.cpp 48 llmortician.cpp
44 llprocessor.cpp 49 llprocessor.cpp
50 llprocesslauncher.cpp
45 llqueuedthread.cpp 51 llqueuedthread.cpp
46 llrand.cpp 52 llrand.cpp
47 llrun.cpp 53 llrun.cpp
@@ -70,6 +76,8 @@ set(llcommon_SOURCE_FILES
70set(llcommon_HEADER_FILES 76set(llcommon_HEADER_FILES
71 CMakeLists.txt 77 CMakeLists.txt
72 78
79 aiaprpool.h
80 aithreadsafe.h
73 bitpack.h 81 bitpack.h
74 ctype_workaround.h 82 ctype_workaround.h
75 doublelinkedlist.h 83 doublelinkedlist.h
@@ -83,6 +91,7 @@ set(llcommon_HEADER_FILES
83 llassettype.h 91 llassettype.h
84 llassoclist.h 92 llassoclist.h
85 llavatarconstants.h 93 llavatarconstants.h
94 llavatarname.h
86 llbase32.h 95 llbase32.h
87 llbase64.h 96 llbase64.h
88 llboost.h 97 llboost.h
@@ -136,12 +145,14 @@ set(llcommon_HEADER_FILES
136 llnametable.h 145 llnametable.h
137 llpreprocessor.h 146 llpreprocessor.h
138 llpriqueuemap.h 147 llpriqueuemap.h
148 llprocesslauncher.h
139 llprocessor.h 149 llprocessor.h
140 llptrskiplist.h 150 llptrskiplist.h
141 llptrskipmap.h 151 llptrskipmap.h
142 llqueuedthread.h 152 llqueuedthread.h
143 llrand.h 153 llrand.h
144 llrun.h 154 llrun.h
155 llscopedvolatileaprpool.h
145 llsd.h 156 llsd.h
146 llsdserialize.h 157 llsdserialize.h
147 llsdserialize_xml.h 158 llsdserialize_xml.h
@@ -188,11 +199,22 @@ set_source_files_properties(${llcommon_HEADER_FILES}
188 199
189list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) 200list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
190 201
191add_library (llcommon ${llcommon_SOURCE_FILES}) 202add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
192target_link_libraries( 203target_link_libraries(
193 llcommon 204 llcommon
194 ${APRUTIL_LIBRARIES} 205 ${APRUTIL_LIBRARIES}
195 ${APR_LIBRARIES} 206 ${APR_LIBRARIES}
196 ${EXPAT_LIBRARIES} 207 ${EXPAT_LIBRARIES}
197 ${ZLIB_LIBRARIES} 208 ${ZLIB_LIBRARIES}
209 ${WINDOWS_LIBRARIES}
198 ) 210 )
211
212if (DARWIN)
213 # don't embed a full path in the library's install name
214 set_target_properties(
215 llcommon
216 PROPERTIES
217 BUILD_WITH_INSTALL_RPATH 1
218 INSTALL_NAME_DIR "@executable_path/../Resources"
219 )
220endif (DARWIN)
diff --git a/linden/indra/llcommon/aiaprpool.cpp b/linden/indra/llcommon/aiaprpool.cpp
new file mode 100644
index 0000000..d3748e9
--- /dev/null
+++ b/linden/indra/llcommon/aiaprpool.cpp
@@ -0,0 +1,198 @@
1/**
2 * @file aiaprpool.cpp
3 *
4 * Copyright (c) 2010, Aleric Inglewood.
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * There are special exceptions to the terms and conditions of the GPL as
20 * it is applied to this Source Code. View the full text of the exception
21 * in the file doc/FLOSS-exception.txt in this software distribution.
22 *
23 * CHANGELOG
24 * and additional copyright holders.
25 *
26 * 04/04/2010
27 * - Initial version, written by Aleric Inglewood @ SL
28 *
29 * 10/11/2010
30 * - Changed filename, class names and license to a more
31 * company-neutral format.
32 * - Added APR_HAS_THREADS #if's to allow creation and destruction
33 * of subpools by threads other than the parent pool owner.
34 */
35
36#include "linden_common.h"
37
38#include "llerror.h"
39#include "aiaprpool.h"
40#include "llthread.h"
41
42// Create a subpool from parent.
43void AIAPRPool::create(AIAPRPool& parent)
44{
45 llassert(!mPool); // Must be non-initialized.
46 mParent = &parent;
47 if (!mParent) // Using the default parameter?
48 {
49 // By default use the root pool of the current thread.
50 mParent = &AIThreadLocalData::tldata().mRootPool;
51 }
52 llassert(mParent->mPool); // Parent must be initialized.
53#if APR_HAS_THREADS
54 // As per the documentation of APR (ie http://apr.apache.org/docs/apr/1.4/apr__pools_8h.html):
55 //
56 // Note that most operations on pools are not thread-safe: a single pool should only be
57 // accessed by a single thread at any given time. The one exception to this rule is creating
58 // a subpool of a given pool: one or more threads can safely create subpools at the same
59 // time that another thread accesses the parent pool.
60 //
61 // In other words, it's safe for any thread to create a (sub)pool, independent of who
62 // owns the parent pool.
63 mOwner = apr_os_thread_current();
64#else
65 mOwner = mParent->mOwner;
66 llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
67#endif
68 apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool);
69 llassert_always(apr_pool_create_status == APR_SUCCESS);
70 llassert(mPool); // Initialized.
71 apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
72}
73
74// Destroy the (sub)pool, if any.
75void AIAPRPool::destroy(void)
76{
77 // Only do anything if we are not already (being) destroyed.
78 if (mPool)
79 {
80#if !APR_HAS_THREADS
81 // If we are a root pool, then every thread may destruct us: in that case
82 // we have to assume that no other thread will use this pool concurrently,
83 // of course. Otherwise, if we are a subpool, only the thread that owns
84 // the parent may destruct us, since that is the pool that is still alive,
85 // possibly being used by others and being altered here.
86 llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current()));
87#endif
88 apr_pool_t* pool = mPool;
89 mPool = NULL; // Mark that we are BEING destructed.
90 apr_pool_cleanup_kill(pool, this, &s_plain_cleanup);
91 apr_pool_destroy(pool);
92 }
93}
94
95bool AIAPRPool::parent_is_being_destructed(void)
96{
97 return mParent && (!mParent->mPool || mParent->parent_is_being_destructed());
98}
99
100AIAPRInitialization::AIAPRInitialization(void)
101{
102 static bool apr_initialized = false;
103
104 if (!apr_initialized)
105 {
106 apr_initialize();
107 }
108
109 apr_initialized = true;
110}
111
112bool AIAPRRootPool::sCountInitialized = false;
113apr_uint32_t volatile AIAPRRootPool::sCount;
114
115extern apr_thread_mutex_t* gLogMutexp;
116extern apr_thread_mutex_t* gCallStacksLogMutexp;
117
118AIAPRRootPool::AIAPRRootPool(void) : AIAPRInitialization(), AIAPRPool(0)
119{
120 // sCountInitialized don't need locking because when we get here there is still only a single thread.
121 if (!sCountInitialized)
122 {
123 // Initialize the logging mutex
124 apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
125 apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
126
127 apr_status_t status = apr_atomic_init(mPool);
128 llassert_always(status == APR_SUCCESS);
129 apr_atomic_set32(&sCount, 1); // Set to 1 to account for the global root pool.
130 sCountInitialized = true;
131
132 // Initialize thread-local APR pool support.
133 // Because this recursively calls AIAPRRootPool::AIAPRRootPool(void)
134 // it must be done last, so that sCount is already initialized.
135 AIThreadLocalData::init();
136 }
137 apr_atomic_inc32(&sCount);
138}
139
140AIAPRRootPool::~AIAPRRootPool()
141{
142 if (!apr_atomic_dec32(&sCount))
143 {
144 // The last pool was destructed. Cleanup remainder of APR.
145 LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
146
147 if (gLogMutexp)
148 {
149 // Clean up the logging mutex
150
151 // All other threads NEED to be done before we clean up APR, so this is okay.
152 apr_thread_mutex_destroy(gLogMutexp);
153 gLogMutexp = NULL;
154 }
155 if (gCallStacksLogMutexp)
156 {
157 // Clean up the logging mutex
158
159 // All other threads NEED to be done before we clean up APR, so this is okay.
160 apr_thread_mutex_destroy(gCallStacksLogMutexp);
161 gCallStacksLogMutexp = NULL;
162 }
163
164 // Must destroy ALL, and therefore this last AIAPRRootPool, before terminating APR.
165 static_cast<AIAPRRootPool*>(this)->destroy();
166
167 apr_terminate();
168 }
169}
170
171//static
172AIAPRRootPool& AIAPRRootPool::get(void)
173{
174 static AIAPRRootPool global_APRpool(0); // This is what used to be gAPRPoolp.
175 return global_APRpool;
176}
177
178void AIVolatileAPRPool::clearVolatileAPRPool()
179{
180 llassert_always(mNumActiveRef > 0);
181 if (--mNumActiveRef == 0)
182 {
183 if (isOld())
184 {
185 destroy();
186 mNumTotalRef = 0 ;
187 }
188 else
189 {
190 // This does not actually free the memory,
191 // it just allows the pool to re-use this memory for the next allocation.
192 clear();
193 }
194 }
195
196 // Paranoia check if the pool is jammed.
197 llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
198}
diff --git a/linden/indra/llcommon/aiaprpool.h b/linden/indra/llcommon/aiaprpool.h
new file mode 100644
index 0000000..ac523a9
--- /dev/null
+++ b/linden/indra/llcommon/aiaprpool.h
@@ -0,0 +1,240 @@
1/**
2 * @file aiaprpool.h
3 * @brief Implementation of AIAPRPool.
4 *
5 * Copyright (c) 2010, Aleric Inglewood.
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * 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 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 * There are special exceptions to the terms and conditions of the GPL as
21 * it is applied to this Source Code. View the full text of the exception
22 * in the file doc/FLOSS-exception.txt in this software distribution.
23 *
24 * CHANGELOG
25 * and additional copyright holders.
26 *
27 * 04/04/2010
28 * - Initial version, written by Aleric Inglewood @ SL
29 *
30 * 10/11/2010
31 * - Changed filename, class names and license to a more
32 * company-neutral format.
33 * - Added APR_HAS_THREADS #if's to allow creation and destruction
34 * of subpools by threads other than the parent pool owner.
35 */
36
37#ifndef AIAPRPOOL_H
38#define AIAPRPOOL_H
39
40#ifdef LL_WINDOWS
41//#include <ws2tcpip.h>
42# define WIN32_LEAN_AND_MEAN
43# include <winsock2.h> // Needed before including apr_portable.h
44#endif
45
46#include "apr_portable.h"
47#include "apr_pools.h"
48#include "llerror.h"
49
50extern void ll_init_apr();
51
52/**
53 * @brief A wrapper around the APR memory pool API.
54 *
55 * Usage of this class should be restricted to passing it to libapr-1 function calls that need it.
56 *
57 */
58class LL_COMMON_API AIAPRPool
59{
60protected:
61 apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized.
62 AIAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero.
63 apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero.
64
65public:
66 //! Construct an uninitialized (destructed) pool.
67 AIAPRPool(void) : mPool(NULL) { }
68
69 //! Construct a subpool from an existing pool.
70 // This is not a copy-constructor, this class doesn't have one!
71 AIAPRPool(AIAPRPool& parent) : mPool(NULL) { create(parent); }
72
73 //! Destruct the memory pool (free all of it's subpools and allocated memory).
74 ~AIAPRPool() { destroy(); }
75
76protected:
77 // Create a pool that is allocated from the Operating System. Only used by AIAPRRootPool.
78 AIAPRPool(int) : mPool(NULL), mParent(NULL), mOwner(apr_os_thread_current())
79 {
80 apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, NULL);
81 llassert_always(apr_pool_create_status == APR_SUCCESS);
82 llassert(mPool);
83 apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
84 }
85
86public:
87 //! Create a subpool from parent. May only be called for an uninitialized/destroyed pool.
88 // The default parameter causes the root pool of the current thread to be used.
89 void create(AIAPRPool& parent = *static_cast<AIAPRPool*>(NULL));
90
91 //! Destroy the (sub)pool, if any.
92 void destroy(void);
93
94 // Use some safebool idiom (http://www.artima.com/cppsource/safebool.html) rather than operator bool.
95 typedef apr_pool_t* const AIAPRPool::* const bool_type;
96 //! Return true if the pool is initialized.
97 operator bool_type() const { return mPool ? &AIAPRPool::mPool : 0; }
98
99 // Painful, but we have to either provide access to this, or wrap
100 // every APR function call that needs a apr_pool_t* to be passed.
101 // NEVER destroy a pool that is returned by this function!
102 apr_pool_t* operator()(void) const
103 {
104 llassert(mPool);
105 llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
106 return mPool;
107 }
108
109 // Free all memory without destructing the pool.
110 void clear(void)
111 {
112 llassert(mPool);
113 llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
114 apr_pool_clear(mPool);
115 }
116
117// These methods would make this class 'complete' (as wrapper around the libapr
118// pool functions), but we don't use memory pools in the viewer (only when
119// we are forced to pass one to a libapr call), so don't define them in order
120// not to encourage people to use them.
121#if 0
122 void* palloc(size_t size)
123 {
124 llassert(mPool);
125 llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
126 return apr_palloc(mPool, size);
127 }
128 void* pcalloc(size_t size)
129 {
130 llassert(mPool);
131 llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
132 return apr_pcalloc(mPool, size);
133 }
134#endif
135
136private:
137 bool parent_is_being_destructed(void);
138 static apr_status_t s_plain_cleanup(void* userdata) { return static_cast<AIAPRPool*>(userdata)->plain_cleanup(); }
139
140 apr_status_t plain_cleanup(void)
141 {
142 if (mPool && // We are not being destructed,
143 parent_is_being_destructed()) // but our parent is.
144 // This means the pool is being destructed recursively by libapr
145 // because one of it's parents is being destructed.
146 {
147 mPool = NULL; // Stop destroy() from destructing the pool again.
148 }
149 return APR_SUCCESS;
150 }
151};
152
153class AIAPRInitialization
154{
155public:
156 AIAPRInitialization(void);
157};
158
159/**
160 * @brief Root memory pool (allocates memory from the operating system).
161 *
162 * This class should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase
163 * (and LLMutexRootPool when APR_HAS_THREADS isn't defined).
164 */
165class LL_COMMON_API AIAPRRootPool : public AIAPRInitialization, public AIAPRPool
166{
167private:
168 friend class AIThreadLocalData;
169 friend class AIThreadSafeSimpleDCRootPool_pbase;
170#if !APR_HAS_THREADS
171 friend class LLMutexRootPool;
172#endif
173 //! Construct a root memory pool.
174 // Should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase.
175 AIAPRRootPool(void);
176 ~AIAPRRootPool();
177
178private:
179 // Keep track of how many root pools exist and when the last one is destructed.
180 static bool sCountInitialized;
181 static apr_uint32_t volatile sCount;
182
183public:
184 // Return a global root pool that is independent of AIThreadLocalData.
185 // Normally you should not use this. Only use for early initialization
186 // (before main) and deinitialization (after main).
187 static AIAPRRootPool& get(void);
188
189#if APR_POOL_DEBUG
190 void grab_ownership(void)
191 {
192 // You need a patched libapr to use this.
193 // See http://web.archiveorange.com/archive/v/5XO9y2zoxUOMt6Gmi1OI
194 apr_pool_owner_set(mPool);
195 }
196#endif
197
198private:
199 // Used for constructing the Special Global Root Pool (returned by AIAPRRootPool::get).
200 // It is the same as the default constructor but omits to increment sCount. As a result,
201 // we must be sure that at least one other AIAPRRootPool is created before termination
202 // of the application (which is the case: we create one AIAPRRootPool per thread).
203 AIAPRRootPool(int) : AIAPRInitialization(), AIAPRPool(0) { }
204};
205
206//! Volatile memory pool
207//
208// 'Volatile' APR memory pool which normally only clears memory,
209// and does not destroy the pool (the same pool is reused) for
210// greater efficiency. However, as a safe guard the apr pool
211// is destructed every FULL_VOLATILE_APR_POOL uses to allow
212// the system memory to be allocated more efficiently and not
213// get scattered through RAM.
214//
215class LL_COMMON_API AIVolatileAPRPool : protected AIAPRPool
216{
217public:
218 AIVolatileAPRPool(void) : mNumActiveRef(0), mNumTotalRef(0) { }
219
220 apr_pool_t* getVolatileAPRPool(void)
221 {
222 if (!mPool) create();
223 ++mNumActiveRef;
224 ++mNumTotalRef;
225 return AIAPRPool::operator()();
226 }
227 void clearVolatileAPRPool(void);
228
229 bool isOld(void) const { return mNumTotalRef > FULL_VOLATILE_APR_POOL; }
230 bool isUnused() const { return mNumActiveRef == 0; }
231
232private:
233 S32 mNumActiveRef; // Number of active uses of the pool.
234 S32 mNumTotalRef; // Number of total uses of the pool since last creation.
235
236 // Maximum number of references to AIVolatileAPRPool until the pool is recreated.
237 static S32 const FULL_VOLATILE_APR_POOL = 1024;
238};
239
240#endif // AIAPRPOOL_H
diff --git a/linden/indra/llcommon/aithreadsafe.h b/linden/indra/llcommon/aithreadsafe.h
new file mode 100644
index 0000000..e1b93ba
--- /dev/null
+++ b/linden/indra/llcommon/aithreadsafe.h
@@ -0,0 +1,463 @@
1/**
2 * @file aithreadsafe.h
3 * @brief Implementation of AIThreadSafe, AIReadAccessConst, AIReadAccess and AIWriteAccess.
4 *
5 * CHANGELOG
6 * and additional copyright holders.
7 *
8 * 31/03/2010
9 * Initial version, written by Aleric Inglewood @ SL
10 */
11
12#ifndef AITHREADSAFE_H
13#define AITHREADSAFE_H
14
15#include <new>
16
17#include "llthread.h"
18#include "llerror.h"
19
20template<typename T> struct AIReadAccessConst;
21template<typename T> struct AIReadAccess;
22template<typename T> struct AIWriteAccess;
23template<typename T> struct AIAccess;
24
25template<typename T>
26class AIThreadSafeBits
27{
28private:
29 // AIThreadSafe is a wrapper around an instance of T.
30 // Because T might not have a default constructor, it is constructed
31 // 'in place', with placement new, in the memory reserved here.
32 //
33 // Make sure that the memory that T will be placed in is properly
34 // aligned by using an array of long's.
35 long mMemory[(sizeof(T) + sizeof(long) - 1) / sizeof(long)];
36
37public:
38 // The wrapped objects are constructed in-place with placement new *outside*
39 // of this object (by AITHREADSAFE macro(s) or derived classes).
40 // However, we are responsible for the destruction of the wrapped object.
41 ~AIThreadSafeBits() { ptr()->~T(); }
42
43 // Only for use by AITHREADSAFE, see below.
44 void* memory() const { return const_cast<long*>(&mMemory[0]); }
45
46protected:
47 // Accessors.
48 T const* ptr() const { return reinterpret_cast<T const*>(mMemory); }
49 T* ptr() { return reinterpret_cast<T*>(mMemory); }
50};
51
52/**
53 * @brief A wrapper class for objects that need to be accessed by more than one thread, allowing concurrent readers.
54 *
55 * Use AITHREADSAFE to define instances of any type, and use AIReadAccessConst,
56 * AIReadAccess and AIWriteAccess to get access to the instance.
57 *
58 * For example,
59 *
60 * <code>
61 * class Foo { public: Foo(int, int); };
62 *
63 * AITHREADSAFE(Foo, foo, (2, 3));
64 *
65 * AIReadAccess<Foo> foo_r(foo);
66 * // Use foo_r-> for read access.
67 *
68 * AIWriteAccess<Foo> foo_w(foo);
69 * // Use foo_w-> for write access.
70 * </code>
71 *
72 * If <code>foo</code> is constant, you have to use <code>AIReadAccessConst<Foo></code>.
73 *
74 * It is possible to pass access objects to a function that
75 * downgrades the access, for example:
76 *
77 * <code>
78 * void readfunc(AIReadAccess const& access);
79 *
80 * AIWriteAccess<Foo> foo_w(foo);
81 * readfunc(foo_w); // readfunc will perform read access to foo_w.
82 * </code>
83 *
84 * If <code>AIReadAccess</code> is non-const, you can upgrade the access by creating
85 * an <code>AIWriteAccess</code> object from it. For example:
86 *
87 * <code>
88 * AIWriteAccess<Foo> foo_w(foo_r);
89 * </code>
90 *
91 * This API is Robust(tm). If you try anything that could result in problems,
92 * it simply won't compile. The only mistake you can still easily make is
93 * to obtain write access to an object when it is not needed, or to unlock
94 * an object in between accesses while the state of the object should be
95 * preserved. For example:
96 *
97 * <code>
98 * // This resets foo to point to the first file and then returns that.
99 * std::string filename = AIWriteAccess<Foo>(foo)->get_first_filename();
100 *
101 * // WRONG! The state between calling get_first_filename and get_next_filename should be preserved!
102 *
103 * AIWriteAccess<Foo> foo_w(foo); // Wrong. The code below only needs read-access.
104 * while (!filename.empty())
105 * {
106 * something(filename);
107 * filename = foo_w->next_filename();
108 * }
109 * </code>
110 *
111 * Correct would be
112 *
113 * <code>
114 * AIReadAccess<Foo> foo_r(foo);
115 * std::string filename = AIWriteAccess<Foo>(foo_r)->get_first_filename();
116 * while (!filename.empty())
117 * {
118 * something(filename);
119 * filename = foo_r->next_filename();
120 * }
121 * </code>
122 *
123 */
124template<typename T>
125class AIThreadSafe : public AIThreadSafeBits<T>
126{
127protected:
128 // Only these may access the object (through ptr()).
129 friend struct AIReadAccessConst<T>;
130 friend struct AIReadAccess<T>;
131 friend struct AIWriteAccess<T>;
132
133 // Locking control.
134 AIRWLock mRWLock;
135
136 // For use by AIThreadSafeDC
137 AIThreadSafe(void) { }
138 AIThreadSafe(AIAPRPool& parent) : mRWLock(parent) { }
139
140public:
141 // Only for use by AITHREADSAFE, see below.
142 AIThreadSafe(T* object) { llassert(object == AIThreadSafeBits<T>::ptr()); }
143};
144
145/**
146 * @brief Instantiate an static, global or local object of a given type wrapped in AIThreadSafe, using an arbitrary constructor.
147 *
148 * For example, instead of doing
149 *
150 * <code>
151 * Foo foo(x, y);
152 * static Bar bar;
153 * </code>
154 *
155 * One can instantiate a thread-safe instance with
156 *
157 * <code>
158 * AITHREADSAFE(Foo, foo, (x, y));
159 * static AITHREADSAFE(Bar, bar, );
160 * </code>
161 *
162 * Note: This macro does not allow to allocate such object on the heap.
163 * If that is needed, have a look at AIThreadSafeDC.
164 */
165#define AITHREADSAFE(type, var, paramlist) AIThreadSafe<type> var(new (var.memory()) type paramlist)
166
167/**
168 * @brief A wrapper class for objects that need to be accessed by more than one thread.
169 *
170 * This class is the same as an AIThreadSafe wrapper, except that it can only
171 * be used for default constructed objects.
172 *
173 * For example, instead of
174 *
175 * <code>
176 * Foo foo;
177 * </code>
178 *
179 * One would use
180 *
181 * <code>
182 * AIThreadSafeDC<Foo> foo;
183 * </code>
184 *
185 * The advantage over AITHREADSAFE is that this object can be allocated with
186 * new on the heap. For example:
187 *
188 * <code>
189 * AIThreadSafeDC<Foo>* ptr = new AIThreadSafeDC<Foo>;
190 * </code>
191 *
192 * which is not possible with AITHREADSAFE.
193 */
194template<typename T>
195class AIThreadSafeDC : public AIThreadSafe<T>
196{
197public:
198 // Construct a wrapper around a default constructed object.
199 AIThreadSafeDC(void) { new (AIThreadSafe<T>::ptr()) T; }
200};
201
202/**
203 * @brief Read lock object and provide read access.
204 */
205template<typename T>
206struct AIReadAccessConst
207{
208 //! Internal enum for the lock-type of the AI*Access object.
209 enum state_type
210 {
211 readlocked, //!< A AIReadAccessConst or AIReadAccess.
212 read2writelocked, //!< A AIWriteAccess constructed from a AIReadAccess.
213 writelocked, //!< A AIWriteAccess constructed from a AIThreadSafe.
214 write2writelocked //!< A AIWriteAccess constructed from (the AIReadAccess base class of) a AIWriteAccess.
215 };
216
217 //! Construct a AIReadAccessConst from a constant AIThreadSafe.
218 AIReadAccessConst(AIThreadSafe<T> const& wrapper)
219 : mWrapper(const_cast<AIThreadSafe<T>&>(wrapper)),
220 mState(readlocked)
221 {
222 mWrapper.mRWLock.rdlock();
223 }
224
225 //! Destruct the AI*Access object.
226 // These should never be dynamically allocated, so there is no need to make this virtual.
227 ~AIReadAccessConst()
228 {
229 if (mState == readlocked)
230 mWrapper.mRWLock.rdunlock();
231 else if (mState == writelocked)
232 mWrapper.mRWLock.wrunlock();
233 else if (mState == read2writelocked)
234 mWrapper.mRWLock.wr2rdlock();
235 }
236
237 //! Access the underlaying object for read access.
238 T const* operator->() const { return mWrapper.ptr(); }
239
240 //! Access the underlaying object for read access.
241 T const& operator*() const { return *mWrapper.ptr(); }
242
243protected:
244 //! Constructor used by AIReadAccess.
245 AIReadAccessConst(AIThreadSafe<T>& wrapper, state_type state)
246 : mWrapper(wrapper), mState(state) { }
247
248 AIThreadSafe<T>& mWrapper; //!< Reference to the object that we provide access to.
249 state_type const mState; //!< The lock state that mWrapper is in.
250
251private:
252 // Disallow copy constructing directly.
253 AIReadAccessConst(AIReadAccessConst const&);
254};
255
256/**
257 * @brief Read lock object and provide read access, with possible promotion to write access.
258 */
259template<typename T>
260struct AIReadAccess : public AIReadAccessConst<T>
261{
262 typedef typename AIReadAccessConst<T>::state_type state_type;
263 using AIReadAccessConst<T>::readlocked;
264
265 //! Construct a AIReadAccess from a non-constant AIThreadSafe.
266 AIReadAccess(AIThreadSafe<T>& wrapper) : AIReadAccessConst<T>(wrapper, readlocked) { this->mWrapper.mRWLock.rdlock(); }
267
268protected:
269 //! Constructor used by AIWriteAccess.
270 AIReadAccess(AIThreadSafe<T>& wrapper, state_type state) : AIReadAccessConst<T>(wrapper, state) { }
271
272 friend class AIWriteAccess<T>;
273};
274
275/**
276 * @brief Write lock object and provide read/write access.
277 */
278template<typename T>
279struct AIWriteAccess : public AIReadAccess<T>
280{
281 using AIReadAccessConst<T>::readlocked;
282 using AIReadAccessConst<T>::read2writelocked;
283 using AIReadAccessConst<T>::writelocked;
284 using AIReadAccessConst<T>::write2writelocked;
285
286 //! Construct a AIWriteAccess from a non-constant AIThreadSafe.
287 AIWriteAccess(AIThreadSafe<T>& wrapper) : AIReadAccess<T>(wrapper, writelocked) { this->mWrapper.mRWLock.wrlock();}
288
289 //! Promote read access to write access.
290 explicit AIWriteAccess(AIReadAccess<T>& access)
291 : AIReadAccess<T>(access.mWrapper, (access.mState == readlocked) ? read2writelocked : write2writelocked)
292 {
293 if (this->mState == read2writelocked)
294 {
295 this->mWrapper.mRWLock.rd2wrlock();
296 }
297 }
298
299 //! Access the underlaying object for (read and) write access.
300 T* operator->() const { return this->mWrapper.ptr(); }
301
302 //! Access the underlaying object for (read and) write access.
303 T& operator*() const { return *this->mWrapper.ptr(); }
304};
305
306/**
307 * @brief A wrapper class for objects that need to be accessed by more than one thread.
308 *
309 * Use AITHREADSAFESIMPLE to define instances of any type, and use AIAccess
310 * to get access to the instance.
311 *
312 * For example,
313 *
314 * <code>
315 * class Foo { public: Foo(int, int); };
316 *
317 * AITHREADSAFESIMPLE(Foo, foo, (2, 3));
318 *
319 * AIAccess<Foo> foo_w(foo);
320 * // Use foo_w-> for read and write access.
321 *
322 * See also AIThreadSafe
323 */
324template<typename T>
325class AIThreadSafeSimple : public AIThreadSafeBits<T>
326{
327protected:
328 // Only this one may access the object (through ptr()).
329 friend struct AIAccess<T>;
330
331 // Locking control.
332 LLMutex mMutex;
333
334 // For use by AIThreadSafeSimpleDC
335 AIThreadSafeSimple(void) { }
336 AIThreadSafeSimple(AIAPRPool& parent) : mMutex(parent) { }
337
338public:
339 // Only for use by AITHREADSAFESIMPLE, see below.
340 AIThreadSafeSimple(T* object) { llassert(object == AIThreadSafeBits<T>::ptr()); }
341};
342
343/**
344 * @brief Instantiate an static, global or local object of a given type wrapped in AIThreadSafeSimple, using an arbitrary constructor.
345 *
346 * For example, instead of doing
347 *
348 * <code>
349 * Foo foo(x, y);
350 * static Bar bar;
351 * </code>
352 *
353 * One can instantiate a thread-safe instance with
354 *
355 * <code>
356 * AITHREADSAFESIMPLE(Foo, foo, (x, y));
357 * static AITHREADSAFESIMPLE(Bar, bar, );
358 * </code>
359 *
360 * Note: This macro does not allow to allocate such object on the heap.
361 * If that is needed, have a look at AIThreadSafeSimpleDC.
362 */
363#define AITHREADSAFESIMPLE(type, var, paramlist) AIThreadSafeSimple<type> var(new (var.memory()) type paramlist)
364
365/**
366 * @brief A wrapper class for objects that need to be accessed by more than one thread.
367 *
368 * This class is the same as an AIThreadSafeSimple wrapper, except that it can only
369 * be used for default constructed objects.
370 *
371 * For example, instead of
372 *
373 * <code>
374 * Foo foo;
375 * </code>
376 *
377 * One would use
378 *
379 * <code>
380 * AIThreadSafeSimpleDC<Foo> foo;
381 * </code>
382 *
383 * The advantage over AITHREADSAFESIMPLE is that this object can be allocated with
384 * new on the heap. For example:
385 *
386 * <code>
387 * AIThreadSafeSimpleDC<Foo>* ptr = new AIThreadSafeSimpleDC<Foo>;
388 * </code>
389 *
390 * which is not possible with AITHREADSAFESIMPLE.
391 */
392template<typename T>
393class AIThreadSafeSimpleDC : public AIThreadSafeSimple<T>
394{
395public:
396 // Construct a wrapper around a default constructed object.
397 AIThreadSafeSimpleDC(void) { new (AIThreadSafeSimple<T>::ptr()) T; }
398
399protected:
400 // For use by AIThreadSafeSimpleDCRootPool
401 AIThreadSafeSimpleDC(AIAPRPool& parent) : AIThreadSafeSimple<T>(parent) { new (AIThreadSafeSimple<T>::ptr()) T; }
402};
403
404// Helper class for AIThreadSafeSimpleDCRootPool to assure initialization of
405// the root pool before constructing AIThreadSafeSimpleDC.
406class AIThreadSafeSimpleDCRootPool_pbase
407{
408protected:
409 AIAPRRootPool mRootPool;
410
411private:
412 template<typename T> friend class AIThreadSafeSimpleDCRootPool;
413 AIThreadSafeSimpleDCRootPool_pbase(void) { }
414};
415
416/**
417 * @brief A wrapper class for objects that need to be accessed by more than one thread.
418 *
419 * The same as AIThreadSafeSimpleDC except that this class creates its own AIAPRRootPool
420 * for the internally used mutexes and condition, instead of using the current threads
421 * root pool. The advantage of this is that it can be used for objects that need to
422 * be accessed from the destructors of global objects (after main). The disadvantage
423 * is that it's less efficient to use your own root pool, therefore it's use should be
424 * restricted to those cases where it is absolutely necessary.
425 */
426template<typename T>
427class AIThreadSafeSimpleDCRootPool : private AIThreadSafeSimpleDCRootPool_pbase, public AIThreadSafeSimpleDC<T>
428{
429public:
430 // Construct a wrapper around a default constructed object, using memory allocated
431 // from the operating system for the internal APR objects (mutexes and conditional),
432 // as opposed to allocated from the current threads root pool.
433 AIThreadSafeSimpleDCRootPool(void) :
434 AIThreadSafeSimpleDCRootPool_pbase(),
435 AIThreadSafeSimpleDC<T>(mRootPool) { }
436};
437
438/**
439 * @brief Write lock object and provide read/write access.
440 */
441template<typename T>
442struct AIAccess
443{
444 //! Construct a AIAccess from a non-constant AIThreadSafeSimple.
445 AIAccess(AIThreadSafeSimple<T>& wrapper) : mWrapper(wrapper) { this->mWrapper.mMutex.lock(); }
446
447 //! Access the underlaying object for (read and) write access.
448 T* operator->() const { return this->mWrapper.ptr(); }
449
450 //! Access the underlaying object for (read and) write access.
451 T& operator*() const { return *this->mWrapper.ptr(); }
452
453 ~AIAccess() { this->mWrapper.mMutex.unlock(); }
454
455protected:
456 AIThreadSafeSimple<T>& mWrapper; //!< Reference to the object that we provide access to.
457
458private:
459 // Disallow copy constructing directly.
460 AIAccess(AIAccess const&);
461};
462
463#endif
diff --git a/linden/indra/llcommon/imageids.cpp b/linden/indra/llcommon/imageids.cpp
new file mode 100644
index 0000000..e5343fe
--- /dev/null
+++ b/linden/indra/llcommon/imageids.cpp
@@ -0,0 +1,79 @@
1/**
2 * @file imageids.cpp
3 *
4 * $LicenseInfo:firstyear=2001&license=viewergpl$
5 *
6 * Copyright (c) 2001-2010, Linden Research, Inc.
7 *
8 * Second Life Viewer Source Code
9 * The source code in this file ("Source Code") is provided by Linden Lab
10 * to you under the terms of the GNU General Public License, version 2.0
11 * ("GPL"), unless you have obtained a separate licensing agreement
12 * ("Other License"), formally executed by you and Linden Lab. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlife.com/developers/opensource/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at
20 * http://secondlife.com/developers/opensource/flossexception
21 *
22 * By copying, modifying or distributing this software, you acknowledge
23 * that you have read and understood your obligations described above,
24 * and agree to abide by those obligations.
25 *
26 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
27 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
28 * COMPLETENESS OR PERFORMANCE.
29 * $/LicenseInfo$
30 *
31 */
32
33#include "linden_common.h"
34
35#include "imageids.h"
36
37#include "lluuid.h"
38
39//
40// USE OF THIS FILE IS DEPRECATED
41//
42// Please use viewerart.ini and the standard
43// art import path. // indicates if file is only
44 // on dataserver, or also
45 // pre-cached on viewer
46
47// Grass Images
48const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
49
50const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER
51
52const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver
53const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver
54const LLUUID IMG_CLOUD_POOF ("fc4b9f0b-d008-45c6-96a4-01dd947ac621"); // dataserver
55const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver
56const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver
57const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver
58const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector
59const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver
60const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver
61
62const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver
63const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver
64const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver
65const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver
66const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver
67
68const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver
69const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver
70
71const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER
72const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER
73const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER
74const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER
75const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER
76
77const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER
78
79const LLUUID DEFAULT_UNREZZED_AVATAR_PARTICLE ("c6e07fda-aea5-4149-acb6-6f09980e0db5"); // VIEWER only
diff --git a/linden/indra/llcommon/imageids.h b/linden/indra/llcommon/imageids.h
index 832708c..516fda1 100644
--- a/linden/indra/llcommon/imageids.h
+++ b/linden/indra/llcommon/imageids.h
@@ -33,46 +33,44 @@
33#ifndef LL_IMAGEIDS_H 33#ifndef LL_IMAGEIDS_H
34#define LL_IMAGEIDS_H 34#define LL_IMAGEIDS_H
35 35
36#include "lluuid.h"
37
38// 36//
39// USE OF THIS FILE IS DEPRECATED 37// USE OF THIS FILE IS DEPRECATED
40// 38//
41// Please use viewerart.ini and the standard 39// Please use viewerart.ini and the standard
42// art import path. // indicates if file is only 40// art import path.
43 // on dataserver, or also 41
44 // pre-cached on viewer 42class LLUUID;
45 43
46// Grass Images 44LL_COMMON_API extern const LLUUID IMG_SMOKE;
47const LLUUID IMG_SMOKE ("b4ba225c-373f-446d-9f7e-6cb7b5cf9b3d"); // VIEWER
48 45
49const LLUUID IMG_DEFAULT ("d2114404-dd59-4a4d-8e6c-49359e91bbf0"); // VIEWER 46LL_COMMON_API extern const LLUUID IMG_DEFAULT;
50 47
51const LLUUID IMG_SUN ("cce0f112-878f-4586-a2e2-a8f104bba271"); // dataserver 48LL_COMMON_API extern const LLUUID IMG_SUN;
52const LLUUID IMG_MOON ("d07f6eed-b96a-47cd-b51d-400ad4a1c428"); // dataserver 49LL_COMMON_API extern const LLUUID IMG_MOON;
53const LLUUID IMG_CLOUD_POOF ("fc4b9f0b-d008-45c6-96a4-01dd947ac621"); // dataserver 50LL_COMMON_API extern const LLUUID IMG_CLOUD_POOF;
54const LLUUID IMG_SHOT ("35f217a3-f618-49cf-bbca-c86d486551a9"); // dataserver 51LL_COMMON_API extern const LLUUID IMG_SHOT;
55const LLUUID IMG_SPARK ("d2e75ac1-d0fb-4532-820e-a20034ac814d"); // dataserver 52LL_COMMON_API extern const LLUUID IMG_SPARK;
56const LLUUID IMG_FIRE ("aca40aa8-44cf-44ca-a0fa-93e1a2986f82"); // dataserver 53LL_COMMON_API extern const LLUUID IMG_FIRE;
57const LLUUID IMG_FACE_SELECT ("a85ac674-cb75-4af6-9499-df7c5aaf7a28"); // face selector 54LL_COMMON_API extern const LLUUID IMG_FACE_SELECT;
58const LLUUID IMG_DEFAULT_AVATAR ("c228d1cf-4b5d-4ba8-84f4-899a0796aa97"); // dataserver 55LL_COMMON_API extern const LLUUID IMG_DEFAULT_AVATAR;
59const LLUUID IMG_INVISIBLE ("3a367d1c-bef1-6d43-7595-e88c1e3aadb3"); // dataserver 56LL_COMMON_API extern const LLUUID IMG_INVISIBLE;
60 57
61const LLUUID IMG_EXPLOSION ("68edcf47-ccd7-45b8-9f90-1649d7f12806"); // On dataserver 58LL_COMMON_API extern const LLUUID IMG_EXPLOSION;
62const LLUUID IMG_EXPLOSION_2 ("21ce046c-83fe-430a-b629-c7660ac78d7c"); // On dataserver 59LL_COMMON_API extern const LLUUID IMG_EXPLOSION_2;
63const LLUUID IMG_EXPLOSION_3 ("fedea30a-1be8-47a6-bc06-337a04a39c4b"); // On dataserver 60LL_COMMON_API extern const LLUUID IMG_EXPLOSION_3;
64const LLUUID IMG_EXPLOSION_4 ("abf0d56b-82e5-47a2-a8ad-74741bb2c29e"); // On dataserver 61LL_COMMON_API extern const LLUUID IMG_EXPLOSION_4;
65const LLUUID IMG_SMOKE_POOF ("1e63e323-5fe0-452e-92f8-b98bd0f764e3"); // On dataserver 62LL_COMMON_API extern const LLUUID IMG_SMOKE_POOF;
66 63
67const LLUUID IMG_BIG_EXPLOSION_1 ("5e47a0dc-97bf-44e0-8b40-de06718cee9d"); // On dataserver 64LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_1;
68const LLUUID IMG_BIG_EXPLOSION_2 ("9c8eca51-53d5-42a7-bb58-cef070395db8"); // On dataserver 65LL_COMMON_API extern const LLUUID IMG_BIG_EXPLOSION_2;
69 66
70const LLUUID IMG_BLOOM1 ("3c59f7fe-9dc8-47f9-8aaf-a9dd1fbc3bef"); // VIEWER 67LL_COMMON_API extern const LLUUID IMG_BLOOM1;
71const LLUUID TERRAIN_DIRT_DETAIL ("0bc58228-74a0-7e83-89bc-5c23464bcec5"); // VIEWER 68LL_COMMON_API extern const LLUUID TERRAIN_DIRT_DETAIL;
72const LLUUID TERRAIN_GRASS_DETAIL ("63338ede-0037-c4fd-855b-015d77112fc8"); // VIEWER 69LL_COMMON_API extern const LLUUID TERRAIN_GRASS_DETAIL;
73const LLUUID TERRAIN_MOUNTAIN_DETAIL ("303cd381-8560-7579-23f1-f0a880799740"); // VIEWER 70LL_COMMON_API extern const LLUUID TERRAIN_MOUNTAIN_DETAIL;
74const LLUUID TERRAIN_ROCK_DETAIL ("53a2f406-4895-1d13-d541-d2e3b86bc19c"); // VIEWER 71LL_COMMON_API extern const LLUUID TERRAIN_ROCK_DETAIL;
75 72
76const LLUUID DEFAULT_WATER_NORMAL ("822ded49-9a6c-f61c-cb89-6df54f42cdf4"); // VIEWER 73LL_COMMON_API extern const LLUUID DEFAULT_WATER_NORMAL;
77 74
75LL_COMMON_API extern const LLUUID DEFAULT_UNREZZED_AVATAR_PARTICLE;
78#endif 76#endif
diff --git a/linden/indra/llcommon/indra_constants.cpp b/linden/indra/llcommon/indra_constants.cpp
new file mode 100644
index 0000000..64cbb11
--- /dev/null
+++ b/linden/indra/llcommon/indra_constants.cpp
@@ -0,0 +1,47 @@
1/**
2 * @file indra_constants.cpp
3 * @brief some useful short term constants for Indra
4 *
5 * $LicenseInfo:firstyear=2001&license=viewergpl$
6 *
7 * Copyright (c) 2001-2010, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlife.com/developers/opensource/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlife.com/developers/opensource/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#include "linden_common.h"
34
35#include "indra_constants.h"
36
37#include "lluuid.h"
38
39// "agent id" for things that should be done to ALL agents
40const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb");
41
42// Governor Linden's agent id.
43const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f");
44const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
45const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
46// Maintenance's group id.
47const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd");
diff --git a/linden/indra/llcommon/indra_constants.h b/linden/indra/llcommon/indra_constants.h
index 96c0a1f..b765d4d 100644
--- a/linden/indra/llcommon/indra_constants.h
+++ b/linden/indra/llcommon/indra_constants.h
@@ -34,7 +34,9 @@
34#define LL_INDRA_CONSTANTS_H 34#define LL_INDRA_CONSTANTS_H
35 35
36#include "stdtypes.h" 36#include "stdtypes.h"
37#include "lluuid.h" 37#include "llpreprocessor.h"
38
39class LLUUID;
38 40
39// At 45 Hz collisions seem stable and objects seem 41// At 45 Hz collisions seem stable and objects seem
40// to settle down at a reasonable rate. 42// to settle down at a reasonable rate.
@@ -151,6 +153,11 @@ const char WATER_LAYER_CODE = 'W';
151const char WIND_LAYER_CODE = '7'; 153const char WIND_LAYER_CODE = '7';
152const char CLOUD_LAYER_CODE = '8'; 154const char CLOUD_LAYER_CODE = '8';
153 155
156// Extended land layer for Aurora Sim
157const char AURORA_LAND_LAYER_CODE = 'M';
158const char AURORA_WIND_LAYER_CODE = '9';
159const char AURORA_CLOUD_LAYER_CODE = ':';
160
154// keys 161// keys
155// Bit masks for various keyboard modifier keys. 162// Bit masks for various keyboard modifier keys.
156const MASK MASK_NONE = 0x0000; 163const MASK MASK_NONE = 0x0000;
@@ -261,14 +268,15 @@ const U8 GOD_LIKE = 1;
261const U8 GOD_NOT = 0; 268const U8 GOD_NOT = 0;
262 269
263// "agent id" for things that should be done to ALL agents 270// "agent id" for things that should be done to ALL agents
264const LLUUID LL_UUID_ALL_AGENTS("44e87126-e794-4ded-05b3-7c42da3d5cdb"); 271LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS;
272
273// inventory library owner
274LL_COMMON_API extern const LLUUID ALEXANDRIA_LINDEN_ID;
265 275
266// Governor Linden's agent id. 276LL_COMMON_API extern const LLUUID GOVERNOR_LINDEN_ID;
267const LLUUID ALEXANDRIA_LINDEN_ID("ba2a564a-f0f1-4b82-9c61-b7520bfcd09f"); 277LL_COMMON_API extern const LLUUID REALESTATE_LINDEN_ID;
268const LLUUID GOVERNOR_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
269const LLUUID REALESTATE_LINDEN_ID("3d6181b0-6a4b-97ef-18d8-722652995cf1");
270// Maintenance's group id. 278// Maintenance's group id.
271const LLUUID MAINTENANCE_GROUP_ID("dc7b21cd-3c89-fcaa-31c8-25f9ffd224cd"); 279LL_COMMON_API extern const LLUUID MAINTENANCE_GROUP_ID;
272 280
273// Flags for kick message 281// Flags for kick message
274const U32 KICK_FLAGS_DEFAULT = 0x0; 282const U32 KICK_FLAGS_DEFAULT = 0x0;
diff --git a/linden/indra/llcommon/linden_common.h b/linden/indra/llcommon/linden_common.h
index 25dd629..bf844b9 100644
--- a/linden/indra/llcommon/linden_common.h
+++ b/linden/indra/llcommon/linden_common.h
@@ -51,16 +51,16 @@
51#include <cstdio> 51#include <cstdio>
52#include <cstdlib> 52#include <cstdlib>
53#include <ctime> 53#include <ctime>
54#include <iostream> 54#include <iosfwd>
55#include <fstream>
56 55
57// Work Microsoft compiler warnings 56// Work around Microsoft compiler warnings in STL headers
58#ifdef LL_WINDOWS 57#ifdef LL_WINDOWS
59#pragma warning (disable : 4702) // unreachable code 58#pragma warning (disable : 4702) // unreachable code
60#pragma warning (disable : 4244) // conversion from time_t to S32 59#pragma warning (disable : 4244) // conversion from time_t to S32
61#endif // LL_WINDOWS 60#endif // LL_WINDOWS
62 61
63#include <algorithm> 62// *TODO: Eliminate these, most library .cpp files don't need them.
63// Add them to llviewerprecompiledheaders.h if necessary.
64#include <list> 64#include <list>
65#include <map> 65#include <map>
66#include <vector> 66#include <vector>
@@ -76,18 +76,21 @@
76#pragma warning (disable : 4512) // assignment operator could not be generated 76#pragma warning (disable : 4512) // assignment operator could not be generated
77#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) ) 77#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
78#pragma warning (disable : 4265) // boost 1.36.0, non-virtual destructor in boost::exception_detail::* 78#pragma warning (disable : 4265) // boost 1.36.0, non-virtual destructor in boost::exception_detail::*
79
80// Reenable warnings we disabled above
81#pragma warning (3 : 4702) // unreachable code, we like level 3, not 4
82// moved msvc warnings to llpreprocessor.h *TODO - delete this comment after merge conflicts are unlikely -brad
79#endif // LL_WINDOWS 83#endif // LL_WINDOWS
80 84
81// Linden only libs in alpha-order other than stdtypes.h 85// Linden only libs in alpha-order other than stdtypes.h
86// *NOTE: Please keep includes here to a minimum, see above.
82#include "stdtypes.h" 87#include "stdtypes.h"
83#include "lldefs.h" 88#include "lldefs.h"
84#include "llerror.h" 89#include "llerror.h"
85#include "llextendedstatus.h" 90#include "llextendedstatus.h"
86#include "llfasttimer.h" 91// Don't do this, adds 15K lines of header code to every library file.
92//#include "llfasttimer.h"
87#include "llfile.h" 93#include "llfile.h"
88#include "llformat.h" 94#include "llformat.h"
89#include "llstring.h"
90#include "llsys.h"
91#include "lltimer.h"
92 95
93#endif 96#endif
diff --git a/linden/indra/llcommon/llapp.cpp b/linden/indra/llcommon/llapp.cpp
index 199315f..eedc503 100644
--- a/linden/indra/llcommon/llapp.cpp
+++ b/linden/indra/llcommon/llapp.cpp
@@ -119,13 +119,8 @@ void LLApp::commonCtor()
119 mOptions.append(sd); 119 mOptions.append(sd);
120 } 120 }
121 121
122 // Make sure we clean up APR when we exit
123 // Don't need to do this if we're cleaning up APR in the destructor
124 //atexit(ll_cleanup_apr);
125
126 // Set the application to this instance. 122 // Set the application to this instance.
127 sApplication = this; 123 sApplication = this;
128
129} 124}
130 125
131LLApp::LLApp(LLErrorThread *error_thread) : 126LLApp::LLApp(LLErrorThread *error_thread) :
@@ -420,7 +415,7 @@ void LLApp::incSigChildCount()
420int LLApp::getPid() 415int LLApp::getPid()
421{ 416{
422#if LL_WINDOWS 417#if LL_WINDOWS
423 return 0; 418 return GetCurrentProcessId();
424#else 419#else
425 return getpid(); 420 return getpid();
426#endif 421#endif
diff --git a/linden/indra/llcommon/llapp.h b/linden/indra/llcommon/llapp.h
index f8a593c..96112c9 100644
--- a/linden/indra/llcommon/llapp.h
+++ b/linden/indra/llcommon/llapp.h
@@ -34,14 +34,17 @@
34#define LL_LLAPP_H 34#define LL_LLAPP_H
35 35
36#include <map> 36#include <map>
37#include "llapr.h"
38#include "llrun.h" 37#include "llrun.h"
39#include "llsd.h" 38#include "llsd.h"
40 39
41// Forward declarations 40// Forward declarations
41template <typename Type> class LLAtomic32;
42typedef LLAtomic32<U32> LLAtomicU32;
42class LLErrorThread; 43class LLErrorThread;
43class LLApp; 44class LLLiveFile;
44 45#if LL_LINUX
46typedef struct siginfo siginfo_t;
47#endif
45 48
46typedef void (*LLAppErrorHandler)(); 49typedef void (*LLAppErrorHandler)();
47typedef void (*LLAppChildCallback)(int pid, bool exited, int status); 50typedef void (*LLAppChildCallback)(int pid, bool exited, int status);
@@ -62,7 +65,7 @@ public:
62}; 65};
63#endif 66#endif
64 67
65class LLApp 68class LL_COMMON_API LLApp
66{ 69{
67 friend class LLErrorThread; 70 friend class LLErrorThread;
68public: 71public:
@@ -189,8 +192,6 @@ public:
189#if !LL_WINDOWS 192#if !LL_WINDOWS
190 static U32 getSigChildCount(); 193 static U32 getSigChildCount();
191 static void incSigChildCount(); 194 static void incSigChildCount();
192#else
193#define getpid GetCurrentProcessId
194#endif 195#endif
195 static int getPid(); 196 static int getPid();
196 197
diff --git a/linden/indra/llcommon/llapr.cpp b/linden/indra/llcommon/llapr.cpp
index 7e3a26c..a013d9c 100644
--- a/linden/indra/llcommon/llapr.cpp
+++ b/linden/indra/llcommon/llapr.cpp
@@ -34,220 +34,7 @@
34 34
35#include "linden_common.h" 35#include "linden_common.h"
36#include "llapr.h" 36#include "llapr.h"
37 37#include "llscopedvolatileaprpool.h"
38apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
39apr_thread_mutex_t *gLogMutexp = NULL;
40apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
41
42const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
43
44void ll_init_apr()
45{
46 if (!gAPRPoolp)
47 {
48 // Initialize APR and create the global pool
49 apr_initialize();
50 apr_pool_create(&gAPRPoolp, NULL);
51
52 // Initialize the logging mutex
53 apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
54 apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
55
56 // Initialize thread-local APR pool support.
57 LLVolatileAPRPool::initLocalAPRFilePool();
58 }
59}
60
61
62void ll_cleanup_apr()
63{
64 LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
65
66 if (gLogMutexp)
67 {
68 // Clean up the logging mutex
69
70 // All other threads NEED to be done before we clean up APR, so this is okay.
71 apr_thread_mutex_destroy(gLogMutexp);
72 gLogMutexp = NULL;
73 }
74 if (gCallStacksLogMutexp)
75 {
76 // Clean up the logging mutex
77
78 // All other threads NEED to be done before we clean up APR, so this is okay.
79 apr_thread_mutex_destroy(gCallStacksLogMutexp);
80 gCallStacksLogMutexp = NULL;
81 }
82 if (gAPRPoolp)
83 {
84 apr_pool_destroy(gAPRPoolp);
85 gAPRPoolp = NULL;
86 }
87 apr_terminate();
88}
89
90//
91//
92//LLAPRPool
93//
94LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
95{
96 mParent = parent ;
97 mReleasePoolFlag = releasePoolFlag ;
98 mMaxSize = size ;
99 mPool = NULL ;
100
101 createAPRPool() ;
102}
103
104LLAPRPool::~LLAPRPool()
105{
106 releaseAPRPool() ;
107}
108
109void LLAPRPool::createAPRPool()
110{
111 if(mPool)
112 {
113 return ;
114 }
115
116 mStatus = apr_pool_create(&mPool, mParent);
117 ll_apr_warn_status(mStatus) ;
118
119 if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
120 {
121 apr_allocator_t *allocator = apr_pool_allocator_get(mPool);
122 if (allocator)
123 {
124 apr_allocator_max_free_set(allocator, mMaxSize) ;
125 }
126 }
127}
128
129void LLAPRPool::releaseAPRPool()
130{
131 if(!mPool)
132 {
133 return ;
134 }
135
136 if(!mParent || mReleasePoolFlag)
137 {
138 apr_pool_destroy(mPool) ;
139 mPool = NULL ;
140 }
141}
142
143apr_pool_t* LLAPRPool::getAPRPool()
144{
145 if(!mPool)
146 {
147 createAPRPool() ;
148 }
149
150 return mPool ;
151}
152LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
153 : LLAPRPool(parent, size, releasePoolFlag)
154{
155 mNumActiveRef = 0 ;
156 mNumTotalRef = 0 ;
157}
158
159apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
160{
161 mNumTotalRef++ ;
162 mNumActiveRef++ ;
163 return getAPRPool() ;
164}
165
166void LLVolatileAPRPool::clearVolatileAPRPool()
167{
168 if(mNumActiveRef > 0)
169 {
170 mNumActiveRef--;
171 if(mNumActiveRef < 1)
172 {
173 if(isFull())
174 {
175 mNumTotalRef = 0 ;
176
177 //destroy the apr_pool.
178 releaseAPRPool() ;
179 }
180 else
181 {
182 //This does not actually free the memory,
183 //it just allows the pool to re-use this memory for the next allocation.
184 apr_pool_clear(mPool) ;
185 }
186 }
187 }
188 else
189 {
190 llassert_always(mNumActiveRef > 0) ;
191 }
192
193 //paranoia check if the pool is jammed.
194 //will remove the check before going to release.
195 llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
196}
197
198BOOL LLVolatileAPRPool::isFull()
199{
200 return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
201}
202
203#ifdef SHOW_ASSERT
204// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
205static void* gIsMainThread;
206bool is_main_thread() { return gIsMainThread == LLVolatileAPRPool::getLocalAPRFilePool(); }
207#endif
208
209// The thread private handle to access the LocalAPRFilePool.
210apr_threadkey_t* LLVolatileAPRPool::sLocalAPRFilePoolKey;
211
212// This should be called exactly once, before the first call to createLocalAPRFilePool.
213// static
214void LLVolatileAPRPool::initLocalAPRFilePool()
215{
216 apr_status_t status = apr_threadkey_private_create(&sLocalAPRFilePoolKey, &destroyLocalAPRFilePool, gAPRPoolp);
217 ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the
218 // total number of keys per process {PTHREAD_KEYS_MAX}
219 // has been exceeded.
220 // Create the thread-local pool for the main thread (this function is called by the main thread).
221 createLocalAPRFilePool();
222#ifdef SHOW_ASSERT
223 gIsMainThread = getLocalAPRFilePool();
224#endif
225}
226
227// This should be called once for every thread, before it uses getLocalAPRFilePool.
228// static
229void LLVolatileAPRPool::createLocalAPRFilePool()
230{
231 void* thread_local_data = new LLVolatileAPRPool;
232 apr_status_t status = apr_threadkey_private_set(thread_local_data, sLocalAPRFilePoolKey);
233 llassert_always(status == APR_SUCCESS);
234}
235
236// This is called once for every thread when the thread is destructed.
237// static
238void LLVolatileAPRPool::destroyLocalAPRFilePool(void* thread_local_data)
239{
240 delete reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
241}
242
243// static
244LLVolatileAPRPool* LLVolatileAPRPool::getLocalAPRFilePool()
245{
246 void* thread_local_data;
247 apr_status_t status = apr_threadkey_private_get(&thread_local_data, sLocalAPRFilePoolKey);
248 llassert_always(status == APR_SUCCESS);
249 return reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
250}
251 38
252//--------------------------------------------------------------------- 39//---------------------------------------------------------------------
253// 40//
@@ -310,13 +97,15 @@ void ll_apr_assert_status(apr_status_t status)
310// 97//
311LLAPRFile::LLAPRFile() 98LLAPRFile::LLAPRFile()
312 : mFile(NULL), 99 : mFile(NULL),
313 mCurrentFilePoolp(NULL) 100 mVolatileFilePoolp(NULL),
101 mRegularFilePoolp(NULL)
314{ 102{
315} 103}
316 104
317LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type) 105LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type)
318 : mFile(NULL), 106 : mFile(NULL),
319 mCurrentFilePoolp(NULL) 107 mVolatileFilePoolp(NULL),
108 mRegularFilePoolp(NULL)
320{ 109{
321 open(filename, flags, access_type); 110 open(filename, flags, access_type);
322} 111}
@@ -335,10 +124,16 @@ apr_status_t LLAPRFile::close()
335 mFile = NULL ; 124 mFile = NULL ;
336 } 125 }
337 126
338 if(mCurrentFilePoolp) 127 if (mVolatileFilePoolp)
339 { 128 {
340 mCurrentFilePoolp->clearVolatileAPRPool() ; 129 mVolatileFilePoolp->clearVolatileAPRPool() ;
341 mCurrentFilePoolp = NULL ; 130 mVolatileFilePoolp = NULL ;
131 }
132
133 if (mRegularFilePoolp)
134 {
135 delete mRegularFilePoolp;
136 mRegularFilePoolp = NULL;
342 } 137 }
343 138
344 return ret ; 139 return ret ;
@@ -347,25 +142,28 @@ apr_status_t LLAPRFile::close()
347apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep) 142apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep)
348{ 143{
349 llassert_always(!mFile); 144 llassert_always(!mFile);
350 llassert_always(!mCurrentFilePoolp); 145 llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp);
351 146
352 // Access the pool and increment it's reference count. 147 apr_status_t status;
353 // The reference count of LLVolatileAPRPool objects will be decremented
354 // again in LLAPRFile::close by calling mCurrentFilePoolp->clearVolatileAPRPool().
355 apr_pool_t* pool;
356 if (access_type == local)
357 {
358 // Use a "volatile" thread-local pool.
359 mCurrentFilePoolp = LLVolatileAPRPool::getLocalAPRFilePool();
360 pool = mCurrentFilePoolp->getVolatileAPRPool();
361 }
362 else
363 { 148 {
364 llassert(is_main_thread()); 149 apr_pool_t* apr_file_open_pool;
365 pool = gAPRPoolp; 150 if (access_type == local)
151 {
152 // Use a "volatile" thread-local pool.
153 mVolatileFilePoolp = &AIThreadLocalData::tldata().mVolatileAPRPool;
154 // Access the pool and increment it's reference count.
155 // The reference count of AIVolatileAPRPool objects will be decremented
156 // again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool().
157 apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool();
158 }
159 else
160 {
161 mRegularFilePoolp = new AIAPRPool(AIThreadLocalData::tldata().mRootPool);
162 apr_file_open_pool = (*mRegularFilePoolp)();
163 }
164 status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool);
366 } 165 }
367 apr_status_t s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, pool); 166 if (status != APR_SUCCESS || !mFile)
368 if (s != APR_SUCCESS || !mFile)
369 { 167 {
370 mFile = NULL ; 168 mFile = NULL ;
371 close() ; 169 close() ;
@@ -373,7 +171,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc
373 { 171 {
374 *sizep = 0; 172 *sizep = 0;
375 } 173 }
376 return s; 174 return status;
377 } 175 }
378 176
379 if (sizep) 177 if (sizep)
@@ -390,7 +188,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc
390 *sizep = file_size; 188 *sizep = file_size;
391 } 189 }
392 190
393 return s; 191 return status;
394} 192}
395 193
396// File I/O 194// File I/O
@@ -440,17 +238,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
440//static components of LLAPRFile 238//static components of LLAPRFile
441// 239//
442 240
443// Used in the static functions below.
444class LLScopedVolatileAPRFilePool {
445private:
446 LLVolatileAPRPool* mPool;
447 apr_pool_t* apr_pool;
448public:
449 LLScopedVolatileAPRFilePool() : mPool(LLVolatileAPRPool::getLocalAPRFilePool()), apr_pool(mPool->getVolatileAPRPool()) { }
450 ~LLScopedVolatileAPRFilePool() { mPool->clearVolatileAPRPool(); }
451 operator apr_pool_t*() const { return apr_pool; }
452};
453
454//static 241//static
455S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset) 242S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
456{ 243{
@@ -487,7 +274,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
487S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes) 274S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
488{ 275{
489 apr_file_t* file_handle; 276 apr_file_t* file_handle;
490 LLScopedVolatileAPRFilePool pool; 277 LLScopedVolatileAPRPool pool;
491 apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool); 278 apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool);
492 if (s != APR_SUCCESS || !file_handle) 279 if (s != APR_SUCCESS || !file_handle)
493 { 280 {
@@ -539,7 +326,7 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
539 } 326 }
540 327
541 apr_file_t* file_handle; 328 apr_file_t* file_handle;
542 LLScopedVolatileAPRFilePool pool; 329 LLScopedVolatileAPRPool pool;
543 apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); 330 apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
544 if (s != APR_SUCCESS || !file_handle) 331 if (s != APR_SUCCESS || !file_handle)
545 { 332 {
@@ -584,7 +371,7 @@ bool LLAPRFile::remove(const std::string& filename)
584{ 371{
585 apr_status_t s; 372 apr_status_t s;
586 373
587 LLScopedVolatileAPRFilePool pool; 374 LLScopedVolatileAPRPool pool;
588 s = apr_file_remove(filename.c_str(), pool); 375 s = apr_file_remove(filename.c_str(), pool);
589 376
590 if (s != APR_SUCCESS) 377 if (s != APR_SUCCESS)
@@ -601,7 +388,7 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname)
601{ 388{
602 apr_status_t s; 389 apr_status_t s;
603 390
604 LLScopedVolatileAPRFilePool pool; 391 LLScopedVolatileAPRPool pool;
605 s = apr_file_rename(filename.c_str(), newname.c_str(), pool); 392 s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
606 393
607 if (s != APR_SUCCESS) 394 if (s != APR_SUCCESS)
@@ -619,7 +406,7 @@ bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags)
619 apr_file_t* file_handle; 406 apr_file_t* file_handle;
620 apr_status_t s; 407 apr_status_t s;
621 408
622 LLScopedVolatileAPRFilePool pool; 409 LLScopedVolatileAPRPool pool;
623 s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool); 410 s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
624 411
625 if (s != APR_SUCCESS || !file_handle) 412 if (s != APR_SUCCESS || !file_handle)
@@ -640,7 +427,7 @@ S32 LLAPRFile::size(const std::string& filename)
640 apr_finfo_t info; 427 apr_finfo_t info;
641 apr_status_t s; 428 apr_status_t s;
642 429
643 LLScopedVolatileAPRFilePool pool; 430 LLScopedVolatileAPRPool pool;
644 s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool); 431 s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
645 432
646 if (s != APR_SUCCESS || !file_handle) 433 if (s != APR_SUCCESS || !file_handle)
@@ -669,7 +456,7 @@ bool LLAPRFile::makeDir(const std::string& dirname)
669{ 456{
670 apr_status_t s; 457 apr_status_t s;
671 458
672 LLScopedVolatileAPRFilePool pool; 459 LLScopedVolatileAPRPool pool;
673 s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool); 460 s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
674 461
675 if (s != APR_SUCCESS) 462 if (s != APR_SUCCESS)
@@ -686,7 +473,7 @@ bool LLAPRFile::removeDir(const std::string& dirname)
686{ 473{
687 apr_status_t s; 474 apr_status_t s;
688 475
689 LLScopedVolatileAPRFilePool pool; 476 LLScopedVolatileAPRPool pool;
690 s = apr_file_remove(dirname.c_str(), pool); 477 s = apr_file_remove(dirname.c_str(), pool);
691 478
692 if (s != APR_SUCCESS) 479 if (s != APR_SUCCESS)
diff --git a/linden/indra/llcommon/llapr.h b/linden/indra/llcommon/llapr.h
index 7f770b0..ded15f5 100644
--- a/linden/indra/llcommon/llapr.h
+++ b/linden/indra/llcommon/llapr.h
@@ -48,74 +48,8 @@
48#include "apr_atomic.h" 48#include "apr_atomic.h"
49#include "llstring.h" 49#include "llstring.h"
50 50
51extern apr_thread_mutex_t* gLogMutexp; 51class AIAPRPool;
52extern apr_thread_mutex_t* gCallStacksLogMutexp; 52class AIVolatileAPRPool;
53
54/**
55 * @brief initialize the common apr constructs -- apr itself, the
56 * global pool, and a mutex.
57 */
58void ll_init_apr();
59
60/**
61 * @brief Cleanup those common apr constructs.
62 */
63void ll_cleanup_apr();
64
65//
66//LL apr_pool
67//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
68//
69class LLAPRPool
70{
71public:
72 LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
73 ~LLAPRPool() ;
74
75 apr_pool_t* getAPRPool() ;
76 apr_status_t getStatus() {return mStatus ; }
77
78protected:
79 void releaseAPRPool() ;
80 void createAPRPool() ;
81
82protected:
83 apr_pool_t* mPool ; //pointing to an apr_pool
84 apr_pool_t* mParent ; //parent pool
85 apr_size_t mMaxSize ; //max size of mPool, mPool should return memory to system if allocated memory beyond this limit. However it seems not to work.
86 apr_status_t mStatus ; //status when creating the pool
87 BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
88};
89
90//
91//volatile LL apr_pool
92//which clears memory automatically.
93//so it can not hold static data or data after memory is cleared
94//
95class LLVolatileAPRPool : protected LLAPRPool
96{
97public:
98 LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
99 ~LLVolatileAPRPool(){}
100
101 apr_pool_t* getVolatileAPRPool() ;
102
103 void clearVolatileAPRPool() ;
104
105 BOOL isFull() ;
106 BOOL isEmpty() {return !mNumActiveRef ;}
107
108 static void initLocalAPRFilePool();
109 static void createLocalAPRFilePool();
110 static void destroyLocalAPRFilePool(void* thread_local_data);
111 static LLVolatileAPRPool* getLocalAPRFilePool();
112
113private:
114 S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
115 S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
116
117 static apr_threadkey_t* sLocalAPRFilePoolKey;
118} ;
119 53
120/** 54/**
121 * @class LLScopedLock 55 * @class LLScopedLock
@@ -126,7 +60,7 @@ private:
126 * destructor handles the unlock. Instances of this class are 60 * destructor handles the unlock. Instances of this class are
127 * <b>not</b> thread safe. 61 * <b>not</b> thread safe.
128 */ 62 */
129class LLScopedLock : private boost::noncopyable 63class LL_COMMON_API LLScopedLock : private boost::noncopyable
130{ 64{
131public: 65public:
132 /** 66 /**
@@ -201,12 +135,13 @@ typedef LLAtomic32<S32> LLAtomicS32;
201// 2, a global pool. 135// 2, a global pool.
202// 136//
203 137
204class LLAPRFile : boost::noncopyable 138class LL_COMMON_API LLAPRFile : boost::noncopyable
205{ 139{
206 // make this non copyable since a copy closes the file 140 // make this non copyable since a copy closes the file
207private: 141private:
208 apr_file_t* mFile ; 142 apr_file_t* mFile ;
209 LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool. 143 AIVolatileAPRPool* mVolatileFilePoolp; // (Thread local) APR pool currently in use.
144 AIAPRPool* mRegularFilePoolp; // ...or a regular pool.
210 145
211public: 146public:
212 enum access_t { 147 enum access_t {
@@ -257,10 +192,8 @@ public:
257 * APR_SUCCESS. 192 * APR_SUCCESS.
258 * @return Returns <code>true</code> if status is an error condition. 193 * @return Returns <code>true</code> if status is an error condition.
259 */ 194 */
260bool ll_apr_warn_status(apr_status_t status); 195bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
261
262void ll_apr_assert_status(apr_status_t status);
263 196
264extern "C" apr_pool_t* gAPRPoolp; // Global APR memory pool 197void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
265 198
266#endif // LL_LLAPR_H 199#endif // LL_LLAPR_H
diff --git a/linden/indra/llcommon/llassettype.h b/linden/indra/llcommon/llassettype.h
index 4077b8d..9f611ae 100644
--- a/linden/indra/llcommon/llassettype.h
+++ b/linden/indra/llcommon/llassettype.h
@@ -37,7 +37,7 @@
37 37
38#include "stdenums.h" // for EDragAndDropType 38#include "stdenums.h" // for EDragAndDropType
39 39
40class LLAssetType 40class LL_COMMON_API LLAssetType
41{ 41{
42public: 42public:
43 enum EType 43 enum EType
diff --git a/linden/indra/llcommon/llavatarname.cpp b/linden/indra/llcommon/llavatarname.cpp
new file mode 100644
index 0000000..ebe8c88
--- /dev/null
+++ b/linden/indra/llcommon/llavatarname.cpp
@@ -0,0 +1,150 @@
1/**
2 * @file llavatarname.cpp
3 * @brief Represents name-related data for an avatar, such as the
4 * username/SLID ("bobsmith123" or "james.linden") and the display
5 * name ("James Cook")
6 *
7 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
8 * Second Life Viewer Source Code
9 * Copyright (C) 2010, Linden Research, Inc.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation;
14 * version 2.1 of the License only.
15 *
16 * This library 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 GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
26 * $/LicenseInfo$
27 */
28#include "linden_common.h"
29
30#include "llavatarname.h"
31
32#include "lldate.h"
33#include "llsd.h"
34
35bool LLAvatarName::sOmitResidentAsLastName = false;
36
37// Store these in pre-built std::strings to avoid memory allocations in
38// LLSD map lookups
39static const std::string USERNAME("username");
40static const std::string DISPLAY_NAME("display_name");
41static const std::string LEGACY_FIRST_NAME("legacy_first_name");
42static const std::string LEGACY_LAST_NAME("legacy_last_name");
43static const std::string IS_DISPLAY_NAME_DEFAULT("is_display_name_default");
44static const std::string DISPLAY_NAME_EXPIRES("display_name_expires");
45static const std::string DISPLAY_NAME_NEXT_UPDATE("display_name_next_update");
46
47LLAvatarName::LLAvatarName()
48: mUsername(),
49 mDisplayName(),
50 mLegacyFirstName(),
51 mLegacyLastName(),
52 mIsDisplayNameDefault(false),
53 mIsDummy(false),
54 mExpires(F64_MAX),
55 mNextUpdate(0.0)
56{ }
57
58bool LLAvatarName::operator<(const LLAvatarName& rhs) const
59{
60 if (mUsername == rhs.mUsername)
61 return mDisplayName < rhs.mDisplayName;
62 else
63 return mUsername < rhs.mUsername;
64}
65
66LLSD LLAvatarName::asLLSD() const
67{
68 LLSD sd;
69 sd[USERNAME] = mUsername;
70 sd[DISPLAY_NAME] = mDisplayName;
71 sd[LEGACY_FIRST_NAME] = mLegacyFirstName;
72 sd[LEGACY_LAST_NAME] = mLegacyLastName;
73 sd[IS_DISPLAY_NAME_DEFAULT] = mIsDisplayNameDefault;
74 sd[DISPLAY_NAME_EXPIRES] = LLDate(mExpires);
75 sd[DISPLAY_NAME_NEXT_UPDATE] = LLDate(mNextUpdate);
76 return sd;
77}
78
79void LLAvatarName::fromLLSD(const LLSD& sd)
80{
81 mUsername = sd[USERNAME].asString();
82 mDisplayName = sd[DISPLAY_NAME].asString();
83 mLegacyFirstName = sd[LEGACY_FIRST_NAME].asString();
84 mLegacyLastName = sd[LEGACY_LAST_NAME].asString();
85 mIsDisplayNameDefault = sd[IS_DISPLAY_NAME_DEFAULT].asBoolean();
86 LLDate expires = sd[DISPLAY_NAME_EXPIRES];
87 mExpires = expires.secondsSinceEpoch();
88 LLDate next_update = sd[DISPLAY_NAME_NEXT_UPDATE];
89 mNextUpdate = next_update.secondsSinceEpoch();
90}
91
92std::string LLAvatarName::getCompleteName() const
93{
94 std::string name;
95 if (!mUsername.empty())
96 {
97 name = mDisplayName + " (" + mUsername + ")";
98 }
99 else
100 {
101 // ...display names are off, legacy name is in mDisplayName
102 name = mDisplayName;
103 }
104 return name;
105}
106
107std::string LLAvatarName::getLegacyName() const
108{
109 std::string name;
110 name.reserve(mLegacyFirstName.size() + 1 + mLegacyLastName.size());
111 name = mLegacyFirstName;
112 if (!sOmitResidentAsLastName || mLegacyLastName != "Resident")
113 {
114 name += " ";
115 name += mLegacyLastName;
116 }
117 return name;
118}
119
120std::string LLAvatarName::getNames(bool linefeed) const
121{
122 std::string name;
123
124 if (mUsername.empty())
125 {
126 // ...display names are off, legacy name is in mDisplayName
127 name = mDisplayName;
128 if (sOmitResidentAsLastName)
129 {
130 LLStringUtil::replaceString(name, " Resident", "");
131 }
132 }
133 else
134 {
135 name = getLegacyName();
136 if (name != mDisplayName)
137 {
138 if (linefeed)
139 {
140 name = mDisplayName + "\n[" + name + "]";
141 }
142 else
143 {
144 name = mDisplayName + " [" + name + "]";
145 }
146 }
147 }
148
149 return name;
150}
diff --git a/linden/indra/llcommon/llavatarname.h b/linden/indra/llcommon/llavatarname.h
new file mode 100644
index 0000000..3b6c6ea
--- /dev/null
+++ b/linden/indra/llcommon/llavatarname.h
@@ -0,0 +1,105 @@
1/**
2 * @file llavatarname.h
3 * @brief Represents name-related data for an avatar, such as the
4 * username/SLID ("bobsmith123" or "james.linden") and the display
5 * name ("James Cook")
6 *
7 * $LicenseInfo:firstyear=2010&license=viewerlgpl$
8 * Second Life Viewer Source Code
9 * Copyright (C) 2010, Linden Research, Inc.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation;
14 * version 2.1 of the License only.
15 *
16 * This library 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 GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 *
25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
26 * $/LicenseInfo$
27 */
28#ifndef LLAVATARNAME_H
29#define LLAVATARNAME_H
30
31#include <string>
32
33class LLSD;
34
35class LL_COMMON_API LLAvatarName
36{
37public:
38 LLAvatarName();
39
40 bool operator<(const LLAvatarName& rhs) const;
41
42 LLSD asLLSD() const;
43
44 void fromLLSD(const LLSD& sd);
45
46 // For normal names, returns "James Linden (james.linden)"
47 // When display names are disabled returns just "James Linden"
48 std::string getCompleteName() const;
49
50 // For normal names, returns "Whatever Display Name (John Doe)" when
51 // display name and legacy name are different, or just "John Doe"
52 // when they are equal or when display names are disabled.
53 // When linefeed == true, the space between the display name and
54 // the opening parenthesis for the legacy name is replaced with a
55 // line feed.
56 std::string getNames(bool linefeed = false) const;
57
58 // Returns "James Linden" or "bobsmith123 Resident" for backwards
59 // compatibility with systems like voice and muting
60 std::string getLegacyName() const;
61
62 // "bobsmith123" or "james.linden", US-ASCII only
63 std::string mUsername;
64
65 // "Jose' Sanchez" or "James Linden", UTF-8 encoded Unicode
66 // Contains data whether or not user has explicitly set
67 // a display name; may duplicate their username.
68 std::string mDisplayName;
69
70 // For "James Linden", "James"
71 // For "bobsmith123", "bobsmith123"
72 // Used to communicate with legacy systems like voice and muting which
73 // rely on old-style names.
74 std::string mLegacyFirstName;
75
76 // For "James Linden", "Linden"
77 // For "bobsmith123", "Resident"
78 // see above for rationale
79 std::string mLegacyLastName;
80
81 // If true, both display name and SLID were generated from
82 // a legacy first and last name, like "James Linden (james.linden)"
83 bool mIsDisplayNameDefault;
84
85 // Under error conditions, we may insert "dummy" records with
86 // names equal to legacy name into caches as placeholders.
87 // These can be shown in UI, but are not serialized.
88 bool mIsDummy;
89
90 // Names can change, so need to keep track of when name was
91 // last checked.
92 // Unix time-from-epoch seconds for efficiency
93 F64 mExpires;
94
95 // You can only change your name every N hours, so record
96 // when the next update is allowed
97 // Unix time-from-epoch seconds
98 F64 mNextUpdate;
99
100 // true to prevent the displaying of "Resident" as a last name
101 // in legacy names
102 static bool sOmitResidentAsLastName;
103};
104
105#endif
diff --git a/linden/indra/llcommon/llbase32.h b/linden/indra/llcommon/llbase32.h
index 63a93e1..47cd893 100644
--- a/linden/indra/llcommon/llbase32.h
+++ b/linden/indra/llcommon/llbase32.h
@@ -34,7 +34,7 @@
34#ifndef LLBASE32_H 34#ifndef LLBASE32_H
35#define LLBASE32_h 35#define LLBASE32_h
36 36
37class LLBase32 37class LL_COMMON_API LLBase32
38{ 38{
39public: 39public:
40 static std::string encode(const U8* input, size_t input_size); 40 static std::string encode(const U8* input, size_t input_size);
diff --git a/linden/indra/llcommon/llbase64.h b/linden/indra/llcommon/llbase64.h
index 58414bb..15b27a6 100644
--- a/linden/indra/llcommon/llbase64.h
+++ b/linden/indra/llcommon/llbase64.h
@@ -34,7 +34,7 @@
34#ifndef LLBASE64_H 34#ifndef LLBASE64_H
35#define LLBASE64_h 35#define LLBASE64_h
36 36
37class LLBase64 37class LL_COMMON_API LLBase64
38{ 38{
39public: 39public:
40 static std::string encode(const U8* input, size_t input_size); 40 static std::string encode(const U8* input, size_t input_size);
diff --git a/linden/indra/llcommon/llcommon.cpp b/linden/indra/llcommon/llcommon.cpp
index 2cbb718..298dd46 100644
--- a/linden/indra/llcommon/llcommon.cpp
+++ b/linden/indra/llcommon/llcommon.cpp
@@ -35,17 +35,9 @@
35#include "llthread.h" 35#include "llthread.h"
36 36
37//static 37//static
38BOOL LLCommon::sAprInitialized = FALSE;
39
40//static
41void LLCommon::initClass() 38void LLCommon::initClass()
42{ 39{
43 LLMemory::initClass(); 40 LLMemory::initClass();
44 if (!sAprInitialized)
45 {
46 ll_init_apr();
47 sAprInitialized = TRUE;
48 }
49 LLTimer::initClass(); 41 LLTimer::initClass();
50 LLThreadSafeRefCount::initThreadSafeRefCount(); 42 LLThreadSafeRefCount::initThreadSafeRefCount();
51// LLWorkerThread::initClass(); 43// LLWorkerThread::initClass();
@@ -59,10 +51,5 @@ void LLCommon::cleanupClass()
59// LLWorkerThread::cleanupClass(); 51// LLWorkerThread::cleanupClass();
60 LLThreadSafeRefCount::cleanupThreadSafeRefCount(); 52 LLThreadSafeRefCount::cleanupThreadSafeRefCount();
61 LLTimer::cleanupClass(); 53 LLTimer::cleanupClass();
62 if (sAprInitialized)
63 {
64 ll_cleanup_apr();
65 sAprInitialized = FALSE;
66 }
67 LLMemory::cleanupClass(); 54 LLMemory::cleanupClass();
68} 55}
diff --git a/linden/indra/llcommon/llcommon.h b/linden/indra/llcommon/llcommon.h
index 5f77988..300ebe2 100644
--- a/linden/indra/llcommon/llcommon.h
+++ b/linden/indra/llcommon/llcommon.h
@@ -38,13 +38,11 @@
38#include "lltimer.h" 38#include "lltimer.h"
39#include "llfile.h" 39#include "llfile.h"
40 40
41class LLCommon 41class LL_COMMON_API LLCommon
42{ 42{
43public: 43public:
44 static void initClass(); 44 static void initClass();
45 static void cleanupClass(); 45 static void cleanupClass();
46private:
47 static BOOL sAprInitialized;
48}; 46};
49 47
50#endif 48#endif
diff --git a/linden/indra/llcommon/llcrc.h b/linden/indra/llcommon/llcrc.h
index 27fae7d..7436906 100644
--- a/linden/indra/llcommon/llcrc.h
+++ b/linden/indra/llcommon/llcrc.h
@@ -50,7 +50,7 @@
50// llinfos << "File crc: " << crc.getCRC() << llendl; 50// llinfos << "File crc: " << crc.getCRC() << llendl;
51//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 51//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52 52
53class LLCRC 53class LL_COMMON_API LLCRC
54{ 54{
55protected: 55protected:
56 U32 mCurrent; 56 U32 mCurrent;
diff --git a/linden/indra/llcommon/llcriticaldamp.h b/linden/indra/llcommon/llcriticaldamp.h
index ad98284..13e37d8 100644
--- a/linden/indra/llcommon/llcriticaldamp.h
+++ b/linden/indra/llcommon/llcriticaldamp.h
@@ -38,7 +38,7 @@
38 38
39#include "llframetimer.h" 39#include "llframetimer.h"
40 40
41class LLCriticalDamp 41class LL_COMMON_API LLCriticalDamp
42{ 42{
43public: 43public:
44 LLCriticalDamp(); 44 LLCriticalDamp();
diff --git a/linden/indra/llcommon/llcursortypes.h b/linden/indra/llcommon/llcursortypes.h
index bea7035..836ecc3 100644
--- a/linden/indra/llcommon/llcursortypes.h
+++ b/linden/indra/llcommon/llcursortypes.h
@@ -77,6 +77,6 @@ enum ECursorType {
77 UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor) 77 UI_CURSOR_COUNT // Number of elements in this enum (NOT a cursor)
78}; 78};
79 79
80ECursorType getCursorFromString(const std::string& cursor_string); 80LL_COMMON_API ECursorType getCursorFromString(const std::string& cursor_string);
81 81
82#endif // LL_LLCURSORTYPES_H 82#endif // LL_LLCURSORTYPES_H
diff --git a/linden/indra/llcommon/lldate.cpp b/linden/indra/llcommon/lldate.cpp
index 41a3af3..be29448 100644
--- a/linden/indra/llcommon/lldate.cpp
+++ b/linden/indra/llcommon/lldate.cpp
@@ -113,6 +113,8 @@ void LLDate::toHTTPDateStream(std::ostream& s) const
113#else 113#else
114 s.setf(ios::right); 114 s.setf(ios::right);
115#endif 115#endif
116 static char const* const weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
117 static char const* const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
116 std::string day = weekdays[exp_time.tm_wday]; 118 std::string day = weekdays[exp_time.tm_wday];
117 std::string month = months[exp_time.tm_mon]; 119 std::string month = months[exp_time.tm_mon];
118 120
diff --git a/linden/indra/llcommon/lldate.h b/linden/indra/llcommon/lldate.h
index 7cc9c8a..d27da79 100644
--- a/linden/indra/llcommon/lldate.h
+++ b/linden/indra/llcommon/lldate.h
@@ -46,7 +46,7 @@
46 * 46 *
47 * The date class represents a point in time after epoch - 1970-01-01. 47 * The date class represents a point in time after epoch - 1970-01-01.
48 */ 48 */
49class LLDate 49class LL_COMMON_API LLDate
50{ 50{
51public: 51public:
52 /** 52 /**
@@ -153,14 +153,9 @@ private:
153}; 153};
154 154
155// Helper function to stream out a date 155// Helper function to stream out a date
156std::ostream& operator<<(std::ostream& s, const LLDate& date); 156LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLDate& date);
157 157
158// Helper function to stream in a date 158// Helper function to stream in a date
159std::istream& operator>>(std::istream& s, LLDate& date); 159LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
160
161
162const static std::string weekdays[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
163
164const static std::string months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
165 160
166#endif // LL_LLDATE_H 161#endif // LL_LLDATE_H
diff --git a/linden/indra/llcommon/llerror.cpp b/linden/indra/llcommon/llerror.cpp
index 30b61a9..aeba629 100644
--- a/linden/indra/llcommon/llerror.cpp
+++ b/linden/indra/llcommon/llerror.cpp
@@ -46,6 +46,8 @@
46# include <unistd.h> 46# include <unistd.h>
47#endif // !LL_WINDOWS 47#endif // !LL_WINDOWS
48#if LL_WINDOWS 48#if LL_WINDOWS
49# define WIN32_LEAN_AND_MEAN
50# include <winsock2.h>
49# include <windows.h> 51# include <windows.h>
50#endif // LL_WINDOWS 52#endif // LL_WINDOWS
51#include <vector> 53#include <vector>
@@ -58,7 +60,9 @@
58#include "llsd.h" 60#include "llsd.h"
59#include "llsdserialize.h" 61#include "llsdserialize.h"
60#include "llstl.h" 62#include "llstl.h"
63#include "lltimer.h"
61 64
65extern apr_thread_mutex_t* gCallStacksLogMutexp;
62 66
63namespace { 67namespace {
64#if !LL_WINDOWS 68#if !LL_WINDOWS
@@ -164,6 +168,9 @@ namespace {
164 } 168 }
165 } 169 }
166 fprintf(stderr, "%s\n", message.c_str()); 170 fprintf(stderr, "%s\n", message.c_str());
171#if LL_WINDOWS
172 fflush(stderr); //Now using a buffer. flush is required.
173#endif
167 if (ANSI_YES == mUseANSI) colorANSI("0"); // reset 174 if (ANSI_YES == mUseANSI) colorANSI("0"); // reset
168 } 175 }
169 176
@@ -559,7 +566,7 @@ namespace
559#if LL_WINDOWS 566#if LL_WINDOWS
560 LLError::addRecorder(new RecordToWinDebug); 567 LLError::addRecorder(new RecordToWinDebug);
561#endif 568#endif
562 569 llwarns << "Load LogControlFile from Directory:"<< dir << llendl;
563 LogControlFile& e = LogControlFile::fromDirectory(dir); 570 LogControlFile& e = LogControlFile::fromDirectory(dir);
564 571
565 // NOTE: We want to explicitly load the file before we add it to the event timer 572 // NOTE: We want to explicitly load the file before we add it to the event timer
@@ -869,6 +876,9 @@ You get:
869 876
870*/ 877*/
871 878
879apr_thread_mutex_t* gLogMutexp;
880apr_thread_mutex_t* gCallStacksLogMutexp;
881
872namespace { 882namespace {
873 bool checkLevelMap(const LevelMap& map, const std::string& key, 883 bool checkLevelMap(const LevelMap& map, const std::string& key,
874 LLError::ELevel& level) 884 LLError::ELevel& level)
diff --git a/linden/indra/llcommon/llerror.h b/linden/indra/llcommon/llerror.h
index 6794be4..5a4c644 100644
--- a/linden/indra/llcommon/llerror.h
+++ b/linden/indra/llcommon/llerror.h
@@ -131,7 +131,7 @@ namespace LLError
131 131
132 class CallSite; 132 class CallSite;
133 133
134 class Log 134 class LL_COMMON_API Log
135 { 135 {
136 public: 136 public:
137 static bool shouldLog(CallSite&); 137 static bool shouldLog(CallSite&);
@@ -140,7 +140,7 @@ namespace LLError
140 static void flush(std::ostringstream*, const CallSite&); 140 static void flush(std::ostringstream*, const CallSite&);
141 }; 141 };
142 142
143 class CallSite 143 class LL_COMMON_API CallSite
144 { 144 {
145 // Represents a specific place in the code where a message is logged 145 // Represents a specific place in the code where a message is logged
146 // This is public because it is used by the macros below. It is not 146 // This is public because it is used by the macros below. It is not
@@ -189,7 +189,7 @@ namespace LLError
189 //LLCallStacks is designed not to be thread-safe. 189 //LLCallStacks is designed not to be thread-safe.
190 //so try not to use it in multiple parallel threads at same time. 190 //so try not to use it in multiple parallel threads at same time.
191 //Used in a single thread at a time is fine. 191 //Used in a single thread at a time is fine.
192 class LLCallStacks 192 class LL_COMMON_API LLCallStacks
193 { 193 {
194 private: 194 private:
195 static char** sBuffer ; 195 static char** sBuffer ;
@@ -239,7 +239,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
239*/ 239*/
240 240
241#define lllog(level, broadTag, narrowTag, once) \ 241#define lllog(level, broadTag, narrowTag, once) \
242 { \ 242 do { \
243 static LLError::CallSite _site( \ 243 static LLError::CallSite _site( \
244 level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\ 244 level, __FILE__, __LINE__, typeid(_LL_CLASS_TO_LOG), __FUNCTION__, broadTag, narrowTag, once);\
245 if (_site.shouldLog()) \ 245 if (_site.shouldLog()) \
@@ -252,7 +252,7 @@ typedef LLError::NoClassInfo _LL_CLASS_TO_LOG;
252 LLError::End(); \ 252 LLError::End(); \
253 LLError::Log::flush(_out, _site); \ 253 LLError::Log::flush(_out, _site); \
254 } \ 254 } \
255 } 255 } while(0)
256 256
257// DEPRECATED: Use the new macros that allow tags and *look* like macros. 257// DEPRECATED: Use the new macros that allow tags and *look* like macros.
258#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false) 258#define lldebugs lllog(LLError::LEVEL_DEBUG, NULL, NULL, false)
diff --git a/linden/indra/llcommon/llerrorcontrol.h b/linden/indra/llcommon/llerrorcontrol.h
index a55d706..54138b2 100644
--- a/linden/indra/llcommon/llerrorcontrol.h
+++ b/linden/indra/llcommon/llerrorcontrol.h
@@ -52,12 +52,12 @@ class LLSD;
52 52
53namespace LLError 53namespace LLError
54{ 54{
55 void initForServer(const std::string& identity); 55 LL_COMMON_API void initForServer(const std::string& identity);
56 // resets all logging settings to defaults needed by server processes 56 // resets all logging settings to defaults needed by server processes
57 // logs to stderr, syslog, and windows debug log 57 // logs to stderr, syslog, and windows debug log
58 // the identity string is used for in the syslog 58 // the identity string is used for in the syslog
59 59
60 void initForApplication(const std::string& dir); 60 LL_COMMON_API void initForApplication(const std::string& dir);
61 // resets all logging settings to defaults needed by applicaitons 61 // resets all logging settings to defaults needed by applicaitons
62 // logs to stderr and windows debug log 62 // logs to stderr and windows debug log
63 // sets up log configuration from the file logcontrol.xml in dir 63 // sets up log configuration from the file logcontrol.xml in dir
@@ -68,13 +68,14 @@ namespace LLError
68 Setting a level means log messages at that level or above. 68 Setting a level means log messages at that level or above.
69 */ 69 */
70 70
71 void setPrintLocation(bool); 71 LL_COMMON_API void setPrintLocation(bool);
72 void setDefaultLevel(LLError::ELevel); 72 LL_COMMON_API void setDefaultLevel(LLError::ELevel);
73 void setFunctionLevel(const std::string& function_name, LLError::ELevel); 73 LL_COMMON_API void setFunctionLevel(const std::string& function_name, LLError::ELevel);
74 void setClassLevel(const std::string& class_name, LLError::ELevel); 74 LL_COMMON_API void setClassLevel(const std::string& class_name, LLError::ELevel);
75 void setFileLevel(const std::string& file_name, LLError::ELevel); 75 LL_COMMON_API void setFileLevel(const std::string& file_name, LLError::ELevel);
76 LL_COMMON_API void setTagLevel(const std::string& file_name, LLError::ELevel);
76 77
77 void configure(const LLSD&); 78 LL_COMMON_API void configure(const LLSD&);
78 // the LLSD can configure all of the settings 79 // the LLSD can configure all of the settings
79 // usually read automatically from the live errorlog.xml file 80 // usually read automatically from the live errorlog.xml file
80 81
@@ -84,25 +85,25 @@ namespace LLError
84 */ 85 */
85 86
86 typedef void(*FatalFunction)(const std::string& message); 87 typedef void(*FatalFunction)(const std::string& message);
87 void crashAndLoop(const std::string& message); 88 LL_COMMON_API void crashAndLoop(const std::string& message);
88 // Default fatal funtion: access null pointer and loops forever 89 // Default fatal funtion: access null pointer and loops forever
89 90
90 void setFatalFunction(FatalFunction); 91 LL_COMMON_API void setFatalFunction(FatalFunction);
91 // The fatal function will be called when an message of LEVEL_ERROR 92 // The fatal function will be called when an message of LEVEL_ERROR
92 // is logged. Note: supressing a LEVEL_ERROR message from being logged 93 // is logged. Note: supressing a LEVEL_ERROR message from being logged
93 // (by, for example, setting a class level to LEVEL_NONE), will keep 94 // (by, for example, setting a class level to LEVEL_NONE), will keep
94 // the that message from causing the fatal funciton to be invoked. 95 // the that message from causing the fatal funciton to be invoked.
95 96
96 typedef std::string (*TimeFunction)(); 97 typedef std::string (*TimeFunction)();
97 std::string utcTime(); 98 LL_COMMON_API std::string utcTime();
98 99
99 void setTimeFunction(TimeFunction); 100 LL_COMMON_API void setTimeFunction(TimeFunction);
100 // The function is use to return the current time, formatted for 101 // The function is use to return the current time, formatted for
101 // display by those error recorders that want the time included. 102 // display by those error recorders that want the time included.
102 103
103 104
104 105
105 class Recorder 106 class LL_COMMON_API Recorder
106 { 107 {
107 // An object that handles the actual output or error messages. 108 // An object that handles the actual output or error messages.
108 public: 109 public:
@@ -116,17 +117,17 @@ namespace LLError
116 // included in the text of the message 117 // included in the text of the message
117 }; 118 };
118 119
119 void addRecorder(Recorder*); 120 LL_COMMON_API void addRecorder(Recorder*);
120 void removeRecorder(Recorder*); 121 LL_COMMON_API void removeRecorder(Recorder*);
121 // each error message is passed to each recorder via recordMessage() 122 // each error message is passed to each recorder via recordMessage()
122 123
123 void logToFile(const std::string& filename); 124 LL_COMMON_API void logToFile(const std::string& filename);
124 void logToFixedBuffer(LLFixedBuffer*); 125 LL_COMMON_API void logToFixedBuffer(LLFixedBuffer*);
125 // Utilities to add recorders for logging to a file or a fixed buffer 126 // Utilities to add recorders for logging to a file or a fixed buffer
126 // A second call to the same function will remove the logger added 127 // A second call to the same function will remove the logger added
127 // with the first. 128 // with the first.
128 // Passing the empty string or NULL to just removes any prior. 129 // Passing the empty string or NULL to just removes any prior.
129 std::string logFileName(); 130 LL_COMMON_API std::string logFileName();
130 // returns name of current logging file, empty string if none 131 // returns name of current logging file, empty string if none
131 132
132 133
@@ -135,11 +136,11 @@ namespace LLError
135 */ 136 */
136 137
137 class Settings; 138 class Settings;
138 Settings* saveAndResetSettings(); 139 LL_COMMON_API Settings* saveAndResetSettings();
139 void restoreSettings(Settings *); 140 LL_COMMON_API void restoreSettings(Settings *);
140 141
141 std::string abbreviateFile(const std::string& filePath); 142 LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
142 int shouldLogCallCount(); 143 LL_COMMON_API int shouldLogCallCount();
143 144
144}; 145};
145 146
diff --git a/linden/indra/llcommon/llerrorthread.cpp b/linden/indra/llcommon/llerrorthread.cpp
index 4c779c5..e2b106a 100644
--- a/linden/indra/llcommon/llerrorthread.cpp
+++ b/linden/indra/llcommon/llerrorthread.cpp
@@ -32,6 +32,7 @@
32#include "linden_common.h" 32#include "linden_common.h"
33#include "llerrorthread.h" 33#include "llerrorthread.h"
34#include "llapp.h" 34#include "llapp.h"
35#include "lltimer.h"
35 36
36LLErrorThread::LLErrorThread() 37LLErrorThread::LLErrorThread()
37 : LLThread("Error"), 38 : LLThread("Error"),
diff --git a/linden/indra/llcommon/llerrorthread.h b/linden/indra/llcommon/llerrorthread.h
index f1d6ffc..3121d29 100644
--- a/linden/indra/llcommon/llerrorthread.h
+++ b/linden/indra/llcommon/llerrorthread.h
@@ -35,7 +35,7 @@
35 35
36#include "llthread.h" 36#include "llthread.h"
37 37
38class LLErrorThread : public LLThread 38class LL_COMMON_API LLErrorThread : public LLThread
39{ 39{
40public: 40public:
41 LLErrorThread(); 41 LLErrorThread();
diff --git a/linden/indra/llcommon/llevent.h b/linden/indra/llcommon/llevent.h
index 60887a0..6b223a8 100644
--- a/linden/indra/llcommon/llevent.h
+++ b/linden/indra/llcommon/llevent.h
@@ -44,7 +44,7 @@ class LLEventDispatcher;
44class LLObservable; 44class LLObservable;
45 45
46// Abstract event. All events derive from LLEvent 46// Abstract event. All events derive from LLEvent
47class LLEvent : public LLThreadSafeRefCount 47class LL_COMMON_API LLEvent : public LLThreadSafeRefCount
48{ 48{
49protected: 49protected:
50 virtual ~LLEvent(); 50 virtual ~LLEvent();
@@ -72,7 +72,7 @@ private:
72}; 72};
73 73
74// Abstract listener. All listeners derive from LLEventListener 74// Abstract listener. All listeners derive from LLEventListener
75class LLEventListener : public LLThreadSafeRefCount 75class LL_COMMON_API LLEventListener : public LLThreadSafeRefCount
76{ 76{
77protected: 77protected:
78 virtual ~LLEventListener(); 78 virtual ~LLEventListener();
@@ -89,7 +89,7 @@ public:
89}; 89};
90 90
91// A listener which tracks references to it and cleans up when it's deallocated 91// A listener which tracks references to it and cleans up when it's deallocated
92class LLSimpleListener : public LLEventListener 92class LL_COMMON_API LLSimpleListener : public LLEventListener
93{ 93{
94public: 94public:
95 void clearDispatchers(); 95 void clearDispatchers();
@@ -114,7 +114,7 @@ struct LLListenerEntry
114// Base class for a dispatcher - an object which listens 114// Base class for a dispatcher - an object which listens
115// to events being fired and relays them to their 115// to events being fired and relays them to their
116// appropriate destinations. 116// appropriate destinations.
117class LLEventDispatcher : public LLThreadSafeRefCount 117class LL_COMMON_API LLEventDispatcher : public LLThreadSafeRefCount
118{ 118{
119protected: 119protected:
120 virtual ~LLEventDispatcher(); 120 virtual ~LLEventDispatcher();
@@ -157,7 +157,7 @@ private:
157// In order for this class to work properly, it needs 157// In order for this class to work properly, it needs
158// an instance of an LLEventDispatcher to route events to their 158// an instance of an LLEventDispatcher to route events to their
159// listeners. 159// listeners.
160class LLObservable 160class LL_COMMON_API LLObservable
161{ 161{
162public: 162public:
163 // Initialize with the default Dispatcher 163 // Initialize with the default Dispatcher
diff --git a/linden/indra/llcommon/llfasttimer.cpp b/linden/indra/llcommon/llfasttimer.cpp
index 4aa23bb..5f091d5 100644
--- a/linden/indra/llcommon/llfasttimer.cpp
+++ b/linden/indra/llcommon/llfasttimer.cpp
@@ -42,6 +42,7 @@
42#include <sched.h> 42#include <sched.h>
43#elif LL_DARWIN 43#elif LL_DARWIN
44#include <sys/time.h> 44#include <sys/time.h>
45#include "lltimer.h" // get_clock_count()
45#else 46#else
46#error "architecture not supported" 47#error "architecture not supported"
47#endif 48#endif
diff --git a/linden/indra/llcommon/llfasttimer.h b/linden/indra/llcommon/llfasttimer.h
index 8c1cf47..602a2f7 100644
--- a/linden/indra/llcommon/llfasttimer.h
+++ b/linden/indra/llcommon/llfasttimer.h
@@ -35,9 +35,9 @@
35 35
36#define FAST_TIMER_ON 1 36#define FAST_TIMER_ON 1
37 37
38U64 get_cpu_clock_count(); 38LL_COMMON_API U64 get_cpu_clock_count();
39 39
40class LLFastTimer 40class LL_COMMON_API LLFastTimer
41{ 41{
42public: 42public:
43 enum EFastTimerType 43 enum EFastTimerType
diff --git a/linden/indra/llcommon/llfile.cpp b/linden/indra/llcommon/llfile.cpp
index 2a76f7f..6b68630 100644
--- a/linden/indra/llcommon/llfile.cpp
+++ b/linden/indra/llcommon/llfile.cpp
@@ -34,6 +34,8 @@
34 */ 34 */
35 35
36#if LL_WINDOWS 36#if LL_WINDOWS
37# define WIN32_LEAN_AND_MEAN
38# include <winsock2.h>
37#include <windows.h> 39#include <windows.h>
38#endif 40#endif
39 41
diff --git a/linden/indra/llcommon/llfile.h b/linden/indra/llcommon/llfile.h
index c6092f7..ee37605 100644
--- a/linden/indra/llcommon/llfile.h
+++ b/linden/indra/llcommon/llfile.h
@@ -70,7 +70,7 @@ typedef struct stat llstat;
70 70
71#include "llstring.h" // safe char* -> std::string conversion 71#include "llstring.h" // safe char* -> std::string conversion
72 72
73class LLFile 73class LL_COMMON_API LLFile
74{ 74{
75public: 75public:
76 // All these functions take UTF8 path/filenames. 76 // All these functions take UTF8 path/filenames.
@@ -95,7 +95,7 @@ public:
95 95
96#if USE_LLFILESTREAMS 96#if USE_LLFILESTREAMS
97 97
98class llifstream : public std::basic_istream < char , std::char_traits < char > > 98class LL_COMMON_API llifstream : public std::basic_istream < char , std::char_traits < char > >
99{ 99{
100 // input stream associated with a C stream 100 // input stream associated with a C stream
101public: 101public:
@@ -136,7 +136,7 @@ private:
136}; 136};
137 137
138 138
139class llofstream : public std::basic_ostream< char , std::char_traits < char > > 139class LL_COMMON_API llofstream : public std::basic_ostream< char , std::char_traits < char > >
140{ 140{
141public: 141public:
142 typedef std::basic_ostream< char , std::char_traits < char > > _Myt; 142 typedef std::basic_ostream< char , std::char_traits < char > > _Myt;
@@ -185,7 +185,7 @@ private:
185//#define llifstream std::ifstream 185//#define llifstream std::ifstream
186//#define llofstream std::ofstream 186//#define llofstream std::ofstream
187 187
188class llifstream : public std::ifstream 188class LL_COMMON_API llifstream : public std::ifstream
189{ 189{
190public: 190public:
191 llifstream() : std::ifstream() 191 llifstream() : std::ifstream()
@@ -203,7 +203,7 @@ public:
203}; 203};
204 204
205 205
206class llofstream : public std::ofstream 206class LL_COMMON_API llofstream : public std::ofstream
207{ 207{
208public: 208public:
209 llofstream() : std::ofstream() 209 llofstream() : std::ofstream()
diff --git a/linden/indra/llcommon/llfindlocale.cpp b/linden/indra/llcommon/llfindlocale.cpp
index 505f5c5..71675af 100644
--- a/linden/indra/llcommon/llfindlocale.cpp
+++ b/linden/indra/llcommon/llfindlocale.cpp
@@ -39,6 +39,8 @@
39#include <ctype.h> 39#include <ctype.h>
40 40
41#ifdef WIN32 41#ifdef WIN32
42# define WIN32_LEAN_AND_MEAN
43# include <winsock2.h>
42#include <windows.h> 44#include <windows.h>
43#include <winnt.h> 45#include <winnt.h>
44#endif 46#endif
diff --git a/linden/indra/llcommon/llfindlocale.h b/linden/indra/llcommon/llfindlocale.h
index f17c774..b812a06 100644
--- a/linden/indra/llcommon/llfindlocale.h
+++ b/linden/indra/llcommon/llfindlocale.h
@@ -59,8 +59,8 @@ typedef enum {
59/* This allocates/fills in a FL_Locale structure with pointers to 59/* This allocates/fills in a FL_Locale structure with pointers to
60 strings (which should be treated as static), or NULL for inappropriate / 60 strings (which should be treated as static), or NULL for inappropriate /
61 undetected fields. */ 61 undetected fields. */
62FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain); 62LL_COMMON_API FL_Success FL_FindLocale(FL_Locale **locale, FL_Domain domain);
63/* This should be used to free the struct written by FL_FindLocale */ 63/* This should be used to free the struct written by FL_FindLocale */
64void FL_FreeLocale(FL_Locale **locale); 64LL_COMMON_API void FL_FreeLocale(FL_Locale **locale);
65 65
66#endif /*__findlocale_h_*/ 66#endif /*__findlocale_h_*/
diff --git a/linden/indra/llcommon/llfixedbuffer.cpp b/linden/indra/llcommon/llfixedbuffer.cpp
index e9d6029..37a12ad 100644
--- a/linden/indra/llcommon/llfixedbuffer.cpp
+++ b/linden/indra/llcommon/llfixedbuffer.cpp
@@ -33,9 +33,8 @@
33#include "llfixedbuffer.h" 33#include "llfixedbuffer.h"
34 34
35LLFixedBuffer::LLFixedBuffer(const U32 max_lines) 35LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
36 : mMutex(NULL) 36 : mMaxLines(max_lines)
37{ 37{
38 mMaxLines = max_lines;
39 mTimer.reset(); 38 mTimer.reset();
40} 39}
41 40
diff --git a/linden/indra/llcommon/llfixedbuffer.h b/linden/indra/llcommon/llfixedbuffer.h
index 992a024..51d0701 100644
--- a/linden/indra/llcommon/llfixedbuffer.h
+++ b/linden/indra/llcommon/llfixedbuffer.h
@@ -41,7 +41,7 @@
41 41
42// Fixed size buffer for console output and other things. 42// Fixed size buffer for console output and other things.
43 43
44class LLFixedBuffer 44class LL_COMMON_API LLFixedBuffer
45{ 45{
46public: 46public:
47 LLFixedBuffer(const U32 max_lines = 20); 47 LLFixedBuffer(const U32 max_lines = 20);
diff --git a/linden/indra/llcommon/llformat.h b/linden/indra/llcommon/llformat.h
index 44c62d9..ad30d4f 100644
--- a/linden/indra/llcommon/llformat.h
+++ b/linden/indra/llcommon/llformat.h
@@ -40,6 +40,6 @@
40// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun) 40// *NOTE: buffer limited to 1024, (but vsnprintf prevents overrun)
41// should perhaps be replaced with boost::format. 41// should perhaps be replaced with boost::format.
42 42
43std::string llformat(const char *fmt, ...); 43LL_COMMON_API std::string llformat(const char *fmt, ...);
44 44
45#endif // LL_LLFORMAT_H 45#endif // LL_LLFORMAT_H
diff --git a/linden/indra/llcommon/llframetimer.h b/linden/indra/llcommon/llframetimer.h
index 8f51272..f4775a9 100644
--- a/linden/indra/llcommon/llframetimer.h
+++ b/linden/indra/llcommon/llframetimer.h
@@ -43,7 +43,7 @@
43#include "lltimer.h" 43#include "lltimer.h"
44#include "timing.h" 44#include "timing.h"
45 45
46class LLFrameTimer 46class LL_COMMON_API LLFrameTimer
47{ 47{
48public: 48public:
49 LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {} 49 LLFrameTimer() : mStartTime( sFrameTime ), mExpiry(0), mStarted(TRUE) {}
diff --git a/linden/indra/llcommon/llheartbeat.h b/linden/indra/llcommon/llheartbeat.h
index fecb5b1..6f70269 100644
--- a/linden/indra/llcommon/llheartbeat.h
+++ b/linden/indra/llcommon/llheartbeat.h
@@ -40,7 +40,7 @@
40// Note: Win32 does not support the heartbeat/smackdown system; 40// Note: Win32 does not support the heartbeat/smackdown system;
41// heartbeat-delivery turns into a no-op there. 41// heartbeat-delivery turns into a no-op there.
42 42
43class LLHeartbeat 43class LL_COMMON_API LLHeartbeat
44{ 44{
45public: 45public:
46 // secs_between_heartbeat: after a heartbeat is successfully delivered, 46 // secs_between_heartbeat: after a heartbeat is successfully delivered,
diff --git a/linden/indra/llcommon/llliveappconfig.h b/linden/indra/llcommon/llliveappconfig.h
index 55d84a4..3251a7c 100644
--- a/linden/indra/llcommon/llliveappconfig.h
+++ b/linden/indra/llcommon/llliveappconfig.h
@@ -37,7 +37,7 @@
37 37
38class LLApp; 38class LLApp;
39 39
40class LLLiveAppConfig : public LLLiveFile 40class LL_COMMON_API LLLiveAppConfig : public LLLiveFile
41{ 41{
42public: 42public:
43 // To use this, instantiate a LLLiveAppConfig object inside your main loop. 43 // To use this, instantiate a LLLiveAppConfig object inside your main loop.
diff --git a/linden/indra/llcommon/lllivefile.h b/linden/indra/llcommon/lllivefile.h
index fddf006..72f16fd 100644
--- a/linden/indra/llcommon/lllivefile.h
+++ b/linden/indra/llcommon/lllivefile.h
@@ -36,7 +36,7 @@
36const F32 configFileRefreshRate = 5.0; // seconds 36const F32 configFileRefreshRate = 5.0; // seconds
37 37
38 38
39class LLLiveFile 39class LL_COMMON_API LLLiveFile
40{ 40{
41public: 41public:
42 LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f); 42 LLLiveFile(const std::string &filename, const F32 refresh_period = 5.f);
diff --git a/linden/indra/llcommon/lllog.h b/linden/indra/llcommon/lllog.h
index 7ac6c8a..4b6777b 100644
--- a/linden/indra/llcommon/lllog.h
+++ b/linden/indra/llcommon/lllog.h
@@ -41,7 +41,7 @@ class LLLogImpl;
41class LLApp; 41class LLApp;
42class LLSD; 42class LLSD;
43 43
44class LLLog 44class LL_COMMON_API LLLog
45{ 45{
46public: 46public:
47 LLLog(LLApp* app); 47 LLLog(LLApp* app);
diff --git a/linden/indra/llcommon/lllslconstants.h b/linden/indra/llcommon/lllslconstants.h
index fc5363f..25a15e4 100644..100755
--- a/linden/indra/llcommon/lllslconstants.h
+++ b/linden/indra/llcommon/lllslconstants.h
@@ -5,7 +5,7 @@
5 * 5 *
6 * $LicenseInfo:firstyear=2006&license=viewergpl$ 6 * $LicenseInfo:firstyear=2006&license=viewergpl$
7 * 7 *
8 * Copyright (c) 2006-2009, Linden Research, Inc. 8 * Copyright (c) 2006-2010, Linden Research, Inc.
9 * 9 *
10 * Second Life Viewer Source Code 10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab 11 * The source code in this file ("Source Code") is provided by Linden Lab
@@ -189,9 +189,6 @@ const S32 OBJECT_OWNER = 6;
189const S32 OBJECT_GROUP = 7; 189const S32 OBJECT_GROUP = 7;
190const S32 OBJECT_CREATOR = 8; 190const S32 OBJECT_CREATOR = 8;
191 191
192// llTextBox() magic token string - yes this is a hack. sue me.
193const std::string TEXTBOX_MAGIC_TOKEN = "!!llTextBox!!";
194
195// changed() event flags 192// changed() event flags
196const U32 CHANGED_NONE = 0x0; 193const U32 CHANGED_NONE = 0x0;
197const U32 CHANGED_INVENTORY = 0x1; 194const U32 CHANGED_INVENTORY = 0x1;
diff --git a/linden/indra/llcommon/llmd5.cpp b/linden/indra/llcommon/llmd5.cpp
index 14b4f9f..887979b 100644
--- a/linden/indra/llcommon/llmd5.cpp
+++ b/linden/indra/llcommon/llmd5.cpp
@@ -83,6 +83,7 @@ documentation and/or software.
83#include "llmd5.h" 83#include "llmd5.h"
84 84
85#include <cassert> 85#include <cassert>
86#include <iostream>
86 87
87// how many bytes to grab at a time when checking files 88// how many bytes to grab at a time when checking files
88const int LLMD5::BLOCK_LEN = 4096; 89const int LLMD5::BLOCK_LEN = 4096;
diff --git a/linden/indra/llcommon/llmd5.h b/linden/indra/llcommon/llmd5.h
index d8bca03..df9d732 100644
--- a/linden/indra/llcommon/llmd5.h
+++ b/linden/indra/llcommon/llmd5.h
@@ -80,7 +80,7 @@ const int MD5RAW_BYTES = 16;
80const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null 80const int MD5HEX_STR_SIZE = 33; // char hex[MD5HEX_STR_SIZE]; with null
81const int MD5HEX_STR_BYTES = 32; // message system fixed size 81const int MD5HEX_STR_BYTES = 32; // message system fixed size
82 82
83class LLMD5 { 83class LL_COMMON_API LLMD5 {
84// first, some types: 84// first, some types:
85 typedef unsigned int uint4; // assumes integer is 4 words long 85 typedef unsigned int uint4; // assumes integer is 4 words long
86 typedef unsigned short int uint2; // assumes short integer is 2 words long 86 typedef unsigned short int uint2; // assumes short integer is 2 words long
diff --git a/linden/indra/llcommon/llmemory.cpp b/linden/indra/llcommon/llmemory.cpp
index a6de3d2..2b01442 100644
--- a/linden/indra/llcommon/llmemory.cpp
+++ b/linden/indra/llcommon/llmemory.cpp
@@ -33,6 +33,8 @@
33#include "linden_common.h" 33#include "linden_common.h"
34 34
35#if defined(LL_WINDOWS) 35#if defined(LL_WINDOWS)
36# define WIN32_LEAN_AND_MEAN
37# include <winsock2.h>
36# include <windows.h> 38# include <windows.h>
37# include <psapi.h> 39# include <psapi.h>
38#elif defined(LL_DARWIN) 40#elif defined(LL_DARWIN)
@@ -283,6 +285,11 @@ LLRefCount::LLRefCount() :
283{ 285{
284} 286}
285 287
288LLRefCount::LLRefCount(const LLRefCount& other)
289: mRef(0)
290{
291}
292
286LLRefCount::~LLRefCount() 293LLRefCount::~LLRefCount()
287{ 294{
288 if (mRef != 0) 295 if (mRef != 0)
@@ -290,7 +297,13 @@ LLRefCount::~LLRefCount()
290 llerrs << "deleting non-zero reference" << llendl; 297 llerrs << "deleting non-zero reference" << llendl;
291 } 298 }
292} 299}
293 300
301LLRefCount& LLRefCount::operator=(const LLRefCount&)
302{
303 // do nothing, since ref count is specific to *this* reference
304 return *this;
305}
306
294//---------------------------------------------------------------------------- 307//----------------------------------------------------------------------------
295 308
296#if defined(LL_WINDOWS) 309#if defined(LL_WINDOWS)
diff --git a/linden/indra/llcommon/llmemory.h b/linden/indra/llcommon/llmemory.h
index b5c0711..9aa4b85 100644
--- a/linden/indra/llcommon/llmemory.h
+++ b/linden/indra/llcommon/llmemory.h
@@ -45,7 +45,7 @@ const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA;
45 45
46//---------------------------------------------------------------------------- 46//----------------------------------------------------------------------------
47 47
48class LLMemory 48class LL_COMMON_API LLMemory
49{ 49{
50public: 50public:
51 static void initClass(); 51 static void initClass();
@@ -68,12 +68,12 @@ private:
68 68
69//---------------------------------------------------------------------------- 69//----------------------------------------------------------------------------
70 70
71class LLRefCount 71class LL_COMMON_API LLRefCount
72{ 72{
73protected: 73protected:
74 LLRefCount(const LLRefCount&); // not implemented 74 LLRefCount(const LLRefCount&);
75private: 75private:
76 LLRefCount&operator=(const LLRefCount&); // not implemented 76 LLRefCount&operator=(const LLRefCount&);
77 77
78protected: 78protected:
79 virtual ~LLRefCount(); // use unref() 79 virtual ~LLRefCount(); // use unref()
@@ -467,6 +467,6 @@ private:
467 467
468// Return the resident set size of the current process, in bytes. 468// Return the resident set size of the current process, in bytes.
469// Return value is zero if not known. 469// Return value is zero if not known.
470U64 getCurrentRSS(); 470LL_COMMON_API U64 getCurrentRSS();
471 471
472#endif 472#endif
diff --git a/linden/indra/llcommon/llmemorystream.h b/linden/indra/llcommon/llmemorystream.h
index f348632..fa0f5d2 100644
--- a/linden/indra/llcommon/llmemorystream.h
+++ b/linden/indra/llcommon/llmemorystream.h
@@ -52,7 +52,7 @@
52 * be careful to always pass in a valid memory location that exists 52 * be careful to always pass in a valid memory location that exists
53 * for at least as long as this streambuf. 53 * for at least as long as this streambuf.
54 */ 54 */
55class LLMemoryStreamBuf : public std::streambuf 55class LL_COMMON_API LLMemoryStreamBuf : public std::streambuf
56{ 56{
57public: 57public:
58 LLMemoryStreamBuf(const U8* start, S32 length); 58 LLMemoryStreamBuf(const U8* start, S32 length);
@@ -74,7 +74,7 @@ protected:
74 * be careful to always pass in a valid memory location that exists 74 * be careful to always pass in a valid memory location that exists
75 * for at least as long as this streambuf. 75 * for at least as long as this streambuf.
76 */ 76 */
77class LLMemoryStream : public std::istream 77class LL_COMMON_API LLMemoryStream : public std::istream
78{ 78{
79public: 79public:
80 LLMemoryStream(const U8* start, S32 length); 80 LLMemoryStream(const U8* start, S32 length);
diff --git a/linden/indra/llcommon/llmemtype.h b/linden/indra/llcommon/llmemtype.h
index a9ebc20..d4cc67e 100644
--- a/linden/indra/llcommon/llmemtype.h
+++ b/linden/indra/llcommon/llmemtype.h
@@ -57,7 +57,7 @@ static void operator delete(void* p) { ll_release(p); }
57 57
58//---------------------------------------------------------------------------- 58//----------------------------------------------------------------------------
59 59
60class LLMemType 60class LL_COMMON_API LLMemType
61{ 61{
62public: 62public:
63 // Also update sTypeDesc in llmemory.cpp 63 // Also update sTypeDesc in llmemory.cpp
diff --git a/linden/indra/llcommon/llmetrics.h b/linden/indra/llcommon/llmetrics.h
index 1d91e8c..f6f49eb 100644
--- a/linden/indra/llcommon/llmetrics.h
+++ b/linden/indra/llcommon/llmetrics.h
@@ -38,7 +38,7 @@
38class LLMetricsImpl; 38class LLMetricsImpl;
39class LLSD; 39class LLSD;
40 40
41class LLMetrics 41class LL_COMMON_API LLMetrics
42{ 42{
43public: 43public:
44 LLMetrics(); 44 LLMetrics();
diff --git a/linden/indra/llcommon/llmortician.h b/linden/indra/llcommon/llmortician.h
index 247632f..55a101a 100644
--- a/linden/indra/llcommon/llmortician.h
+++ b/linden/indra/llcommon/llmortician.h
@@ -35,7 +35,7 @@
35 35
36#include "stdtypes.h" 36#include "stdtypes.h"
37 37
38class LLMortician 38class LL_COMMON_API LLMortician
39{ 39{
40public: 40public:
41 LLMortician() { mIsDead = FALSE; } 41 LLMortician() { mIsDead = FALSE; }
diff --git a/linden/indra/llcommon/llpreprocessor.h b/linden/indra/llcommon/llpreprocessor.h
index 2e4fd47..6886e3a 100644
--- a/linden/indra/llcommon/llpreprocessor.h
+++ b/linden/indra/llcommon/llpreprocessor.h
@@ -92,47 +92,63 @@
92 92
93#endif 93#endif
94 94
95
96// Deal with the differeneces on Windows 95// Deal with the differeneces on Windows
97#if LL_MSVC
98namespace snprintf_hack
99{
100 int snprintf(char *str, size_t size, const char *format, ...);
101}
102
103// #define snprintf safe_snprintf /* Flawfinder: ignore */
104using snprintf_hack::snprintf;
105#endif // LL_MSVC
106
107// Static linking with apr on windows needs to be declared.
108#ifdef LL_WINDOWS
109#ifndef APR_DECLARE_STATIC
110#define APR_DECLARE_STATIC // For APR on Windows
111#endif
112#ifndef APU_DECLARE_STATIC
113#define APU_DECLARE_STATIC // For APR util on Windows
114#endif
115#endif
116
117#if defined(LL_WINDOWS) 96#if defined(LL_WINDOWS)
118#define BOOST_REGEX_NO_LIB 1 97#define BOOST_REGEX_NO_LIB 1
119#define CURL_STATICLIB 1 98#define CURL_STATICLIB 1
120#define XML_STATIC 99#define XML_STATIC
121#endif // LL_WINDOWS 100#endif // LL_WINDOWS
122 101
123
124// Deal with VC6 problems 102// Deal with VC6 problems
125#if LL_MSVC 103#if LL_MSVC
126#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4. 104#pragma warning( 3 : 4701 ) // "local variable used without being initialized" Treat this as level 3, not level 4.
127#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4. 105#pragma warning( 3 : 4702 ) // "unreachable code" Treat this as level 3, not level 4.
128#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4. 106#pragma warning( 3 : 4189 ) // "local variable initialized but not referenced" Treat this as level 3, not level 4.
129//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4. 107//#pragma warning( 3 : 4018 ) // "signed/unsigned mismatch" Treat this as level 3, not level 4.
108#pragma warning( 3 : 4263 ) // 'function' : member function does not override any base class virtual member function
109#pragma warning( 3 : 4264 ) // "'virtual_function' : no override available for virtual member function from base 'class'; function is hidden"
130#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual" 110#pragma warning( 3 : 4265 ) // "class has virtual functions, but destructor is not virtual"
131#pragma warning( disable : 4786 ) // silly MS warning deep inside their <map> include file 111//#pragma warning( disable : 4265 ) // boost 1.36.0, non-virtual destructor in boost::exception_detail::*
112#pragma warning( 3 : 4266 ) // 'function' : no override available for virtual member function from base 'type'; function is hidden
113#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
132#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file 114#pragma warning( disable : 4284 ) // silly MS warning deep inside their <map> include file
133#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation. 115#pragma warning( disable : 4503 ) // 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.
134#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning) 116#pragma warning( disable : 4800 ) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
135#pragma warning( disable : 4996 ) // warning: deprecated 117#pragma warning( disable : 4996 ) // warning: deprecated
118
119// Linker optimization with "extern template" generates these warnings
120#pragma warning( disable : 4231 ) // nonstandard extension used : 'extern' before template explicit instantiation
121#pragma warning( disable : 4506 ) // no definition for inline function
122
123// level 4 warnings that we need to disable:
124#pragma warning (disable : 4100) // unreferenced formal parameter
125#pragma warning (disable : 4127) // conditional expression is constant (e.g. while(1) )
126#pragma warning (disable : 4244) // possible loss of data on conversions
127#pragma warning (disable : 4396) // the inline specifier cannot be used when a friend declaration refers to a specialization of a function template
128#pragma warning (disable : 4512) // assignment operator could not be generated
129#pragma warning (disable : 4706) // assignment within conditional (even if((x = y)) )
130
131#pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class
132#pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class
136#endif // LL_MSVC 133#endif // LL_MSVC
137 134
135#if LL_WINDOWS
136#define LL_DLLEXPORT __declspec(dllexport)
137#define LL_DLLIMPORT __declspec(dllimport)
138#elif LL_LINUX
139#define LL_DLLEXPORT __attribute__ ((visibility("default")))
140#define LL_DLLIMPORT
141#else
142#define LL_DLLEXPORT
143#define LL_DLLIMPORT
144#endif // LL_WINDOWS
145
146#ifdef llcommon_EXPORTS
147// Compiling llcommon (shared)
148#define LL_COMMON_API LL_DLLEXPORT
149#else // llcommon_EXPORTS
150// Using llcommon (shared)
151#define LL_COMMON_API LL_DLLIMPORT
152#endif // llcommon_EXPORTS
153
138#endif // not LL_LINDEN_PREPROCESSOR_H 154#endif // not LL_LINDEN_PREPROCESSOR_H
diff --git a/linden/indra/llcommon/llprocesslauncher.cpp b/linden/indra/llcommon/llprocesslauncher.cpp
new file mode 100644
index 0000000..e27aaa3
--- /dev/null
+++ b/linden/indra/llcommon/llprocesslauncher.cpp
@@ -0,0 +1,346 @@
1/**
2 * @file llprocesslauncher.cpp
3 * @brief Utility class for launching, terminating, and tracking the state of processes.
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2008-2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#include "linden_common.h"
34
35#include "llprocesslauncher.h"
36
37#include <iostream>
38#if LL_DARWIN || LL_LINUX
39// not required or present on Win32
40#include <sys/wait.h>
41#endif
42
43LLProcessLauncher::LLProcessLauncher()
44{
45#if LL_WINDOWS
46 mProcessHandle = 0;
47#else
48 mProcessID = 0;
49#endif
50}
51
52LLProcessLauncher::~LLProcessLauncher()
53{
54 kill();
55}
56
57void LLProcessLauncher::setExecutable(const std::string &executable)
58{
59 mExecutable = executable;
60}
61
62void LLProcessLauncher::setWorkingDirectory(const std::string &dir)
63{
64 mWorkingDir = dir;
65}
66
67void LLProcessLauncher::clearArguments()
68{
69 mLaunchArguments.clear();
70}
71
72void LLProcessLauncher::addArgument(const std::string &arg)
73{
74 mLaunchArguments.push_back(arg);
75}
76
77void LLProcessLauncher::addArgument(const char *arg)
78{
79 mLaunchArguments.push_back(std::string(arg));
80}
81
82#if LL_WINDOWS
83
84int LLProcessLauncher::launch(void)
85{
86 // If there was already a process associated with this object, kill it.
87 kill();
88 orphan();
89
90 int result = 0;
91
92 PROCESS_INFORMATION pinfo;
93 STARTUPINFOA sinfo;
94 memset(&sinfo, 0, sizeof(sinfo));
95
96 std::string args = "\"" + mExecutable + "\"";
97 for(int i = 0; i < (int)mLaunchArguments.size(); i++)
98 {
99 args += " ";
100 args += mLaunchArguments[i];
101 }
102 LL_INFOS("Plugin") << "Executable: " << mExecutable << " arguments: " << args << LL_ENDL;
103
104 // So retarded. Windows requires that the second parameter to CreateProcessA be a writable (non-const) string...
105 char *args2 = new char[args.size() + 1];
106 strcpy(args2, args.c_str());
107
108 if( ! CreateProcessA( NULL, args2, NULL, NULL, FALSE, 0, NULL, NULL, &sinfo, &pinfo ) )
109 {
110 // TODO: do better than returning the OS-specific error code on failure...
111 result = GetLastError();
112 if(result == 0)
113 {
114 // Make absolutely certain we return a non-zero value on failure.
115 result = -1;
116 }
117 }
118 else
119 {
120 // foo = pinfo.dwProcessId; // get your pid here if you want to use it later on
121 // CloseHandle(pinfo.hProcess); // stops leaks - nothing else
122 mProcessHandle = pinfo.hProcess;
123 CloseHandle(pinfo.hThread); // stops leaks - nothing else
124 }
125
126 delete[] args2;
127
128 return result;
129}
130
131bool LLProcessLauncher::isRunning(void)
132{
133 if(mProcessHandle != 0)
134 {
135 DWORD waitresult = WaitForSingleObject(mProcessHandle, 0);
136 if(waitresult == WAIT_OBJECT_0)
137 {
138 // the process has completed.
139 mProcessHandle = 0;
140 }
141 }
142
143 return (mProcessHandle != 0);
144}
145bool LLProcessLauncher::kill(void)
146{
147 bool result = true;
148
149 if(mProcessHandle != 0)
150 {
151 TerminateProcess(mProcessHandle,0);
152
153 if(isRunning())
154 {
155 result = false;
156 }
157 }
158
159 return result;
160}
161
162void LLProcessLauncher::orphan(void)
163{
164 // Forget about the process
165 mProcessHandle = 0;
166}
167
168// static
169void LLProcessLauncher::reap(void)
170{
171 // No actions necessary on Windows.
172}
173
174#else // Mac and linux
175
176#include <signal.h>
177#include <fcntl.h>
178#include <errno.h>
179
180static std::list<pid_t> sZombies;
181
182// Attempt to reap a process ID -- returns true if the process has exited and been reaped, false otherwise.
183static bool reap_pid(pid_t pid)
184{
185 bool result = false;
186
187 pid_t wait_result = ::waitpid(pid, NULL, WNOHANG);
188 if(wait_result == pid)
189 {
190 result = true;
191 }
192 else if(wait_result == -1)
193 {
194 if(errno == ECHILD)
195 {
196 // No such process -- this may mean we're ignoring SIGCHILD.
197 result = true;
198 }
199 }
200
201 return result;
202}
203
204int LLProcessLauncher::launch(void)
205{
206 // If there was already a process associated with this object, kill it.
207 kill();
208 orphan();
209
210 int result = 0;
211 int current_wd = -1;
212
213 // create an argv vector for the child process
214 const char ** fake_argv = new const char *[mLaunchArguments.size() + 2]; // 1 for the executable path, 1 for the NULL terminator
215
216 int i = 0;
217
218 // add the executable path
219 fake_argv[i++] = mExecutable.c_str();
220
221 // and any arguments
222 for(int j=0; j < mLaunchArguments.size(); j++)
223 fake_argv[i++] = mLaunchArguments[j].c_str();
224
225 // terminate with a null pointer
226 fake_argv[i] = NULL;
227
228 if(!mWorkingDir.empty())
229 {
230 // save the current working directory
231 current_wd = ::open(".", O_RDONLY);
232
233 // and change to the one the child will be executed in
234 if (::chdir(mWorkingDir.c_str()))
235 {
236 // chdir failed
237 }
238 }
239
240 // flush all buffers before the child inherits them
241 ::fflush(NULL);
242
243 pid_t id = vfork();
244 if(id == 0)
245 {
246 // child process
247
248 ::execv(mExecutable.c_str(), (char * const *)fake_argv);
249
250 // If we reach this point, the exec failed.
251 // Use _exit() instead of exit() per the vfork man page.
252 _exit(0);
253 }
254
255 // parent process
256
257 if(current_wd >= 0)
258 {
259 // restore the previous working directory
260 if (::fchdir(current_wd))
261 {
262 // chdir failed
263 }
264 ::close(current_wd);
265 }
266
267 delete[] fake_argv;
268
269 mProcessID = id;
270
271 // At this point, the child process will have been created (since that's how vfork works -- the child borrowed our execution context until it forked)
272 // If the process doesn't exist at this point, the exec failed.
273 if(!isRunning())
274 {
275 result = -1;
276 }
277
278 return result;
279}
280
281bool LLProcessLauncher::isRunning(void)
282{
283 if(mProcessID != 0)
284 {
285 // Check whether the process has exited, and reap it if it has.
286 if(reap_pid(mProcessID))
287 {
288 // the process has exited.
289 mProcessID = 0;
290 }
291 }
292
293 return (mProcessID != 0);
294}
295
296bool LLProcessLauncher::kill(void)
297{
298 bool result = true;
299
300 if(mProcessID != 0)
301 {
302 // Try to kill the process. We'll do approximately the same thing whether the kill returns an error or not, so we ignore the result.
303 (void)::kill(mProcessID, SIGTERM);
304
305 // This will have the side-effect of reaping the zombie if the process has exited.
306 if(isRunning())
307 {
308 result = false;
309 }
310 }
311
312 return result;
313}
314
315void LLProcessLauncher::orphan(void)
316{
317 // Disassociate the process from this object
318 if(mProcessID != 0)
319 {
320 // We may still need to reap the process's zombie eventually
321 sZombies.push_back(mProcessID);
322
323 mProcessID = 0;
324 }
325}
326
327// static
328void LLProcessLauncher::reap(void)
329{
330 // Attempt to real all saved process ID's.
331
332 std::list<pid_t>::iterator iter = sZombies.begin();
333 while(iter != sZombies.end())
334 {
335 if(reap_pid(*iter))
336 {
337 iter = sZombies.erase(iter);
338 }
339 else
340 {
341 iter++;
342 }
343 }
344}
345
346#endif
diff --git a/linden/indra/llcommon/llprocesslauncher.h b/linden/indra/llcommon/llprocesslauncher.h
new file mode 100644
index 0000000..9833a13
--- /dev/null
+++ b/linden/indra/llcommon/llprocesslauncher.h
@@ -0,0 +1,91 @@
1/**
2 * @file llprocesslauncher.h
3 * @brief Utility class for launching, terminating, and tracking the state of processes.
4 *
5 * $LicenseInfo:firstyear=2008&license=viewergpl$
6 *
7 * Copyright (c) 2008-2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#ifndef LL_LLPROCESSLAUNCHER_H
34#define LL_LLPROCESSLAUNCHER_H
35
36#if LL_WINDOWS
37# define WIN32_LEAN_AND_MEAN
38# include <winsock2.h>
39#include <windows.h>
40#endif
41
42
43/*
44 LLProcessLauncher handles launching external processes with specified command line arguments.
45 It also keeps track of whether the process is still running, and can kill it if required.
46*/
47
48class LL_COMMON_API LLProcessLauncher
49{
50 LOG_CLASS(LLProcessLauncher);
51public:
52 LLProcessLauncher();
53 virtual ~LLProcessLauncher();
54
55 void setExecutable(const std::string &executable);
56 void setWorkingDirectory(const std::string &dir);
57
58 void clearArguments();
59 void addArgument(const std::string &arg);
60 void addArgument(const char *arg);
61
62 int launch(void);
63 bool isRunning(void);
64
65 // Attempt to kill the process -- returns true if the process is no longer running when it returns.
66 // Note that even if this returns false, the process may exit some time after it's called.
67 bool kill(void);
68
69 // Use this if you want the external process to continue execution after the LLProcessLauncher instance controlling it is deleted.
70 // Normally, the destructor will attempt to kill the process and wait for termination.
71 // This should only be used if the viewer is about to exit -- otherwise, the child process will become a zombie after it exits.
72 void orphan(void);
73
74 // This needs to be called periodically on Mac/Linux to clean up zombie processes.
75 static void reap(void);
76private:
77 std::string mExecutable;
78 std::string mWorkingDir;
79 std::vector<std::string> mLaunchArguments;
80
81#if LL_WINDOWS
82 HANDLE mProcessHandle;
83#else
84 pid_t mProcessID;
85
86public:
87 pid_t getProcessID() const { return mProcessID; }
88#endif
89};
90
91#endif // LL_LLPROCESSLAUNCHER_H
diff --git a/linden/indra/llcommon/llqueuedthread.cpp b/linden/indra/llcommon/llqueuedthread.cpp
index caf4c2a..bee95be 100644
--- a/linden/indra/llcommon/llqueuedthread.cpp
+++ b/linden/indra/llcommon/llqueuedthread.cpp
@@ -32,6 +32,7 @@
32#include "linden_common.h" 32#include "linden_common.h"
33#include "llqueuedthread.h" 33#include "llqueuedthread.h"
34#include "llstl.h" 34#include "llstl.h"
35#include "lltimer.h"
35 36
36//============================================================================ 37//============================================================================
37 38
diff --git a/linden/indra/llcommon/llqueuedthread.h b/linden/indra/llcommon/llqueuedthread.h
index aa7c6e4..e0e0f1b 100644
--- a/linden/indra/llcommon/llqueuedthread.h
+++ b/linden/indra/llcommon/llqueuedthread.h
@@ -47,7 +47,7 @@
47// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small 47// Note: ~LLQueuedThread is O(N) N=# of queued threads, assumed to be small
48// It is assumed that LLQueuedThreads are rarely created/destroyed. 48// It is assumed that LLQueuedThreads are rarely created/destroyed.
49 49
50class LLQueuedThread : public LLThread 50class LL_COMMON_API LLQueuedThread : public LLThread
51{ 51{
52 //------------------------------------------------------------------------ 52 //------------------------------------------------------------------------
53public: 53public:
@@ -80,7 +80,7 @@ public:
80 //------------------------------------------------------------------------ 80 //------------------------------------------------------------------------
81public: 81public:
82 82
83 class QueuedRequest : public LLSimpleHashEntry<handle_t> 83 class LL_COMMON_API QueuedRequest : public LLSimpleHashEntry<handle_t>
84 { 84 {
85 friend class LLQueuedThread; 85 friend class LLQueuedThread;
86 86
diff --git a/linden/indra/llcommon/llrand.h b/linden/indra/llcommon/llrand.h
index d12597b..73ea179 100644
--- a/linden/indra/llcommon/llrand.h
+++ b/linden/indra/llcommon/llrand.h
@@ -65,32 +65,32 @@
65/** 65/**
66 *@brief Generate a float from [0, RAND_MAX). 66 *@brief Generate a float from [0, RAND_MAX).
67 */ 67 */
68S32 ll_rand(); 68LL_COMMON_API S32 ll_rand();
69 69
70/** 70/**
71 *@brief Generate a float from [0, val) or (val, 0]. 71 *@brief Generate a float from [0, val) or (val, 0].
72 */ 72 */
73S32 ll_rand(S32 val); 73LL_COMMON_API S32 ll_rand(S32 val);
74 74
75/** 75/**
76 *@brief Generate a float from [0, 1.0). 76 *@brief Generate a float from [0, 1.0).
77 */ 77 */
78F32 ll_frand(); 78LL_COMMON_API F32 ll_frand();
79 79
80/** 80/**
81 *@brief Generate a float from [0, val) or (val, 0]. 81 *@brief Generate a float from [0, val) or (val, 0].
82 */ 82 */
83F32 ll_frand(F32 val); 83LL_COMMON_API F32 ll_frand(F32 val);
84 84
85/** 85/**
86 *@brief Generate a double from [0, 1.0). 86 *@brief Generate a double from [0, 1.0).
87 */ 87 */
88F64 ll_drand(); 88LL_COMMON_API F64 ll_drand();
89 89
90/** 90/**
91 *@brief Generate a double from [0, val) or (val, 0]. 91 *@brief Generate a double from [0, val) or (val, 0].
92 */ 92 */
93F64 ll_drand(F64 val); 93LL_COMMON_API F64 ll_drand(F64 val);
94 94
95/** 95/**
96 * @brief typedefs for good boost lagged fibonacci. 96 * @brief typedefs for good boost lagged fibonacci.
diff --git a/linden/indra/llcommon/llrun.h b/linden/indra/llcommon/llrun.h
index 77b23d9..0f8d51d 100644
--- a/linden/indra/llcommon/llrun.h
+++ b/linden/indra/llcommon/llrun.h
@@ -38,6 +38,8 @@
38#include <vector> 38#include <vector>
39#include <boost/shared_ptr.hpp> 39#include <boost/shared_ptr.hpp>
40 40
41#include "llpreprocessor.h"
42
41class LLRunnable; 43class LLRunnable;
42 44
43/** 45/**
@@ -48,7 +50,7 @@ class LLRunnable;
48 * which are scheduled to run on a repeating or one time basis. 50 * which are scheduled to run on a repeating or one time basis.
49 * @see LLRunnable 51 * @see LLRunnable
50 */ 52 */
51class LLRunner 53class LL_COMMON_API LLRunner
52{ 54{
53public: 55public:
54 /** 56 /**
@@ -149,7 +151,7 @@ protected:
149 * something useful. 151 * something useful.
150 * @see LLRunner 152 * @see LLRunner
151 */ 153 */
152class LLRunnable 154class LL_COMMON_API LLRunnable
153{ 155{
154public: 156public:
155 LLRunnable(); 157 LLRunnable();
diff --git a/linden/indra/llcommon/llscopedvolatileaprpool.h b/linden/indra/llcommon/llscopedvolatileaprpool.h
new file mode 100644
index 0000000..724dc7f
--- /dev/null
+++ b/linden/indra/llcommon/llscopedvolatileaprpool.h
@@ -0,0 +1,58 @@
1/**
2 * @file llscopedvolatileaprpool.h
3 * @brief Implementation of LLScopedVolatileAPRPool
4 *
5 * $LicenseInfo:firstyear=2010&license=viewergpl$
6 *
7 * Copyright (c) 2010, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#ifndef LL_LLSCOPEDVOLATILEAPRPOOL_H
34#define LL_LLSCOPEDVOLATILEAPRPOOL_H
35
36#include "llthread.h"
37
38//! Scoped volatile memory pool.
39//
40// As the AIVolatileAPRPool should never keep allocations very
41// long, it's most common use is for allocations with a lifetime
42// equal to it's scope.
43//
44// This is a convenience class that makes just a little easier to type.
45//
46class LLScopedVolatileAPRPool
47{
48private:
49 AIVolatileAPRPool& mPool;
50 apr_pool_t* mScopedAPRpool;
51public:
52 LLScopedVolatileAPRPool() : mPool(AIThreadLocalData::tldata().mVolatileAPRPool), mScopedAPRpool(mPool.getVolatileAPRPool()) { }
53 ~LLScopedVolatileAPRPool() { mPool.clearVolatileAPRPool(); }
54 // Only use this to pass the pointer to a libapr-1 function that requires it.
55 operator apr_pool_t*() const { return mScopedAPRpool; }
56};
57
58#endif
diff --git a/linden/indra/llcommon/llsd.cpp b/linden/indra/llcommon/llsd.cpp
index 2cc94c2..be40bb6 100644
--- a/linden/indra/llcommon/llsd.cpp
+++ b/linden/indra/llcommon/llsd.cpp
@@ -75,7 +75,7 @@ protected:
75 ///< This constructor is used for static objects and causes the 75 ///< This constructor is used for static objects and causes the
76 // suppresses adjusting the debugging counters when they are 76 // suppresses adjusting the debugging counters when they are
77 // finally initialized. 77 // finally initialized.
78 78
79 virtual ~Impl(); 79 virtual ~Impl();
80 80
81 bool shared() const { return mUseCount > 1; } 81 bool shared() const { return mUseCount > 1; }
@@ -162,6 +162,7 @@ namespace
162 162
163 virtual LLSD::Type type() const { return T; } 163 virtual LLSD::Type type() const { return T; }
164 164
165 using LLSD::Impl::assign;
165 virtual void assign(LLSD::Impl*& var, DataRef value) { 166 virtual void assign(LLSD::Impl*& var, DataRef value) {
166 if (shared()) 167 if (shared())
167 { 168 {
@@ -348,6 +349,10 @@ namespace
348 349
349 virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } 350 virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
350 351
352 using LLSD::Impl::get; // Unhiding get(LLSD::Integer)
353 using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
354 using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
355
351 virtual bool has(const LLSD::String&) const; 356 virtual bool has(const LLSD::String&) const;
352 virtual LLSD get(const LLSD::String&) const; 357 virtual LLSD get(const LLSD::String&) const;
353 LLSD& insert(const LLSD::String& k, const LLSD& v); 358 LLSD& insert(const LLSD::String& k, const LLSD& v);
@@ -440,6 +445,11 @@ namespace
440 virtual LLSD::Boolean asBoolean() const { return !mData.empty(); } 445 virtual LLSD::Boolean asBoolean() const { return !mData.empty(); }
441 446
442 virtual int size() const; 447 virtual int size() const;
448
449 using LLSD::Impl::get; // Unhiding get(LLSD::Integer)
450 using LLSD::Impl::erase; // Unhiding erase(LLSD::Integer)
451 using LLSD::Impl::ref; // Unhiding ref(LLSD::Integer)
452
443 virtual LLSD get(LLSD::Integer) const; 453 virtual LLSD get(LLSD::Integer) const;
444 void set(LLSD::Integer, const LLSD&); 454 void set(LLSD::Integer, const LLSD&);
445 LLSD& insert(LLSD::Integer, const LLSD&); 455 LLSD& insert(LLSD::Integer, const LLSD&);
diff --git a/linden/indra/llcommon/llsd.h b/linden/indra/llcommon/llsd.h
index d2845a3..552bb57 100644
--- a/linden/indra/llcommon/llsd.h
+++ b/linden/indra/llcommon/llsd.h
@@ -89,7 +89,7 @@
89 @nosubgrouping 89 @nosubgrouping
90*/ 90*/
91 91
92class LLSD 92class LL_COMMON_API LLSD
93{ 93{
94public: 94public:
95 LLSD(); ///< initially Undefined 95 LLSD(); ///< initially Undefined
@@ -387,7 +387,7 @@ struct llsd_select_string : public std::unary_function<LLSD, LLSD::String>
387 } 387 }
388}; 388};
389 389
390std::ostream& operator<<(std::ostream& s, const LLSD& llsd); 390LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLSD& llsd);
391 391
392/** QUESTIONS & TO DOS 392/** QUESTIONS & TO DOS
393 - Would Binary be more convenient as usigned char* buffer semantics? 393 - Would Binary be more convenient as usigned char* buffer semantics?
diff --git a/linden/indra/llcommon/llsdserialize.h b/linden/indra/llcommon/llsdserialize.h
index f7cd91b..a01b6dc 100644
--- a/linden/indra/llcommon/llsdserialize.h
+++ b/linden/indra/llcommon/llsdserialize.h
@@ -43,7 +43,7 @@
43 * @class LLSDParser 43 * @class LLSDParser
44 * @brief Abstract base class for LLSD parsers. 44 * @brief Abstract base class for LLSD parsers.
45 */ 45 */
46class LLSDParser : public LLRefCount 46class LL_COMMON_API LLSDParser : public LLRefCount
47{ 47{
48protected: 48protected:
49 /** 49 /**
@@ -220,7 +220,7 @@ protected:
220 * @class LLSDNotationParser 220 * @class LLSDNotationParser
221 * @brief Parser which handles the original notation format for LLSD. 221 * @brief Parser which handles the original notation format for LLSD.
222 */ 222 */
223class LLSDNotationParser : public LLSDParser 223class LL_COMMON_API LLSDNotationParser : public LLSDParser
224{ 224{
225protected: 225protected:
226 /** 226 /**
@@ -293,7 +293,7 @@ private:
293 * @class LLSDXMLParser 293 * @class LLSDXMLParser
294 * @brief Parser which handles XML format LLSD. 294 * @brief Parser which handles XML format LLSD.
295 */ 295 */
296class LLSDXMLParser : public LLSDParser 296class LL_COMMON_API LLSDXMLParser : public LLSDParser
297{ 297{
298protected: 298protected:
299 /** 299 /**
@@ -341,7 +341,7 @@ private:
341 * @class LLSDBinaryParser 341 * @class LLSDBinaryParser
342 * @brief Parser which handles binary formatted LLSD. 342 * @brief Parser which handles binary formatted LLSD.
343 */ 343 */
344class LLSDBinaryParser : public LLSDParser 344class LL_COMMON_API LLSDBinaryParser : public LLSDParser
345{ 345{
346protected: 346protected:
347 /** 347 /**
@@ -406,7 +406,7 @@ private:
406 * @class LLSDFormatter 406 * @class LLSDFormatter
407 * @brief Abstract base class for formatting LLSD. 407 * @brief Abstract base class for formatting LLSD.
408 */ 408 */
409class LLSDFormatter : public LLRefCount 409class LL_COMMON_API LLSDFormatter : public LLRefCount
410{ 410{
411protected: 411protected:
412 /** 412 /**
@@ -478,7 +478,7 @@ protected:
478 * @class LLSDNotationFormatter 478 * @class LLSDNotationFormatter
479 * @brief Formatter which outputs the original notation format for LLSD. 479 * @brief Formatter which outputs the original notation format for LLSD.
480 */ 480 */
481class LLSDNotationFormatter : public LLSDFormatter 481class LL_COMMON_API LLSDNotationFormatter : public LLSDFormatter
482{ 482{
483protected: 483protected:
484 /** 484 /**
@@ -519,7 +519,7 @@ public:
519 * @class LLSDXMLFormatter 519 * @class LLSDXMLFormatter
520 * @brief Formatter which outputs the LLSD as XML. 520 * @brief Formatter which outputs the LLSD as XML.
521 */ 521 */
522class LLSDXMLFormatter : public LLSDFormatter 522class LL_COMMON_API LLSDXMLFormatter : public LLSDFormatter
523{ 523{
524protected: 524protected:
525 /** 525 /**
@@ -587,7 +587,7 @@ protected:
587 * Map: '{' + 4 byte integer size every(key + value) + '}'<br> 587 * Map: '{' + 4 byte integer size every(key + value) + '}'<br>
588 * map keys are serialized as 'k' + 4 byte integer size + string 588 * map keys are serialized as 'k' + 4 byte integer size + string
589 */ 589 */
590class LLSDBinaryFormatter : public LLSDFormatter 590class LL_COMMON_API LLSDBinaryFormatter : public LLSDFormatter
591{ 591{
592protected: 592protected:
593 /** 593 /**
@@ -676,7 +676,7 @@ typedef LLSDOStreamer<LLSDXMLFormatter> LLSDXMLStreamer;
676 * @class LLSDSerialize 676 * @class LLSDSerialize
677 * @brief Serializer / deserializer for the various LLSD formats 677 * @brief Serializer / deserializer for the various LLSD formats
678 */ 678 */
679class LLSDSerialize 679class LL_COMMON_API LLSDSerialize
680{ 680{
681public: 681public:
682 enum ELLSD_Serialize 682 enum ELLSD_Serialize
diff --git a/linden/indra/llcommon/llsdserialize_xml.cpp b/linden/indra/llcommon/llsdserialize_xml.cpp
index c12ca35..33206b4 100644
--- a/linden/indra/llcommon/llsdserialize_xml.cpp
+++ b/linden/indra/llcommon/llsdserialize_xml.cpp
@@ -562,7 +562,7 @@ void LLSDXMLParser::Impl::parsePart(const char* buf, int len)
562 562
563#ifdef XML_PARSER_PERFORMANCE_TESTS 563#ifdef XML_PARSER_PERFORMANCE_TESTS
564 564
565extern U64 totalTime(); 565extern LL_COMMON_API U64 totalTime();
566U64 readElementTime = 0; 566U64 readElementTime = 0;
567U64 startElementTime = 0; 567U64 startElementTime = 0;
568U64 endElementTime = 0; 568U64 endElementTime = 0;
diff --git a/linden/indra/llcommon/llsdutil.h b/linden/indra/llcommon/llsdutil.h
index b67ad52..4740a30 100644
--- a/linden/indra/llcommon/llsdutil.h
+++ b/linden/indra/llcommon/llsdutil.h
@@ -68,28 +68,28 @@ LLSD ll_sd_from_color4(const LLColor4& c);
68LLColor4 ll_color4_from_sd(const LLSD& sd); 68LLColor4 ll_color4_from_sd(const LLSD& sd);
69 69
70// U32 70// U32
71LLSD ll_sd_from_U32(const U32); 71LL_COMMON_API LLSD ll_sd_from_U32(const U32);
72U32 ll_U32_from_sd(const LLSD& sd); 72LL_COMMON_API U32 ll_U32_from_sd(const LLSD& sd);
73 73
74// U64 74// U64
75LLSD ll_sd_from_U64(const U64); 75LL_COMMON_API LLSD ll_sd_from_U64(const U64);
76U64 ll_U64_from_sd(const LLSD& sd); 76LL_COMMON_API U64 ll_U64_from_sd(const LLSD& sd);
77 77
78// IP Address 78// IP Address
79LLSD ll_sd_from_ipaddr(const U32); 79LL_COMMON_API LLSD ll_sd_from_ipaddr(const U32);
80U32 ll_ipaddr_from_sd(const LLSD& sd); 80LL_COMMON_API U32 ll_ipaddr_from_sd(const LLSD& sd);
81 81
82// Binary to string 82// Binary to string
83LLSD ll_string_from_binary(const LLSD& sd); 83LL_COMMON_API LLSD ll_string_from_binary(const LLSD& sd);
84 84
85//String to binary 85//String to binary
86LLSD ll_binary_from_string(const LLSD& sd); 86LL_COMMON_API LLSD ll_binary_from_string(const LLSD& sd);
87 87
88// Serializes sd to static buffer and returns pointer, useful for gdb debugging. 88// Serializes sd to static buffer and returns pointer, useful for gdb debugging.
89char* ll_print_sd(const LLSD& sd); 89LL_COMMON_API char* ll_print_sd(const LLSD& sd);
90 90
91// Serializes sd to static buffer and returns pointer, using "pretty printing" mode. 91// Serializes sd to static buffer and returns pointer, using "pretty printing" mode.
92char* ll_pretty_print_sd(const LLSD& sd); 92LL_COMMON_API char* ll_pretty_print_sd(const LLSD& sd);
93 93
94//compares the structure of an LLSD to a template LLSD and stores the 94//compares the structure of an LLSD to a template LLSD and stores the
95//"valid" values in a 3rd LLSD. Default values 95//"valid" values in a 3rd LLSD. Default values
@@ -98,7 +98,7 @@ char* ll_pretty_print_sd(const LLSD& sd);
98//Returns false if the test is of same type but values differ in type 98//Returns false if the test is of same type but values differ in type
99//Otherwise, returns true 99//Otherwise, returns true
100 100
101BOOL compare_llsd_with_template( 101LL_COMMON_API BOOL compare_llsd_with_template(
102 const LLSD& llsd_to_test, 102 const LLSD& llsd_to_test,
103 const LLSD& template_llsd, 103 const LLSD& template_llsd,
104 LLSD& resultant_llsd); 104 LLSD& resultant_llsd);
diff --git a/linden/indra/llcommon/llsecondlifeurls.h b/linden/indra/llcommon/llsecondlifeurls.h
index 9c64b57..e3932d0 100644
--- a/linden/indra/llcommon/llsecondlifeurls.h
+++ b/linden/indra/llcommon/llsecondlifeurls.h
@@ -34,14 +34,14 @@
34#define LL_LLSECONDLIFEURLS_H 34#define LL_LLSECONDLIFEURLS_H
35 35
36 36
37extern const std::string AUCTION_URL; 37LL_COMMON_API extern const std::string AUCTION_URL;
38 38
39extern const std::string EVENTS_URL; 39LL_COMMON_API extern const std::string EVENTS_URL;
40 40
41// Currency page 41// Currency page
42extern const std::string BUY_CURRENCY_URL; 42LL_COMMON_API extern const std::string BUY_CURRENCY_URL;
43 43
44// Release Notes Redirect URL for Server and Viewer 44// Release Notes Redirect URL for Server and Viewer
45extern const std::string RELEASE_NOTES_BASE_URL; 45LL_COMMON_API extern const std::string RELEASE_NOTES_BASE_URL;
46 46
47#endif 47#endif
diff --git a/linden/indra/llcommon/llsimplehash.h b/linden/indra/llcommon/llsimplehash.h
index 0ba2a30..5df93b6 100644
--- a/linden/indra/llcommon/llsimplehash.h
+++ b/linden/indra/llcommon/llsimplehash.h
@@ -64,7 +64,7 @@ public:
64}; 64};
65 65
66template <typename HASH_KEY_TYPE, int TABLE_SIZE> 66template <typename HASH_KEY_TYPE, int TABLE_SIZE>
67class LLSimpleHash 67class LL_COMMON_API LLSimpleHash
68{ 68{
69public: 69public:
70 LLSimpleHash() 70 LLSimpleHash()
diff --git a/linden/indra/llcommon/llstat.h b/linden/indra/llcommon/llstat.h
index 66521a3..951091b 100644
--- a/linden/indra/llcommon/llstat.h
+++ b/linden/indra/llcommon/llstat.h
@@ -52,7 +52,7 @@ class LLSD;
52// amounts of time with very low memory cost. 52// amounts of time with very low memory cost.
53// 53//
54 54
55class LLStatAccum 55class LL_COMMON_API LLStatAccum
56{ 56{
57protected: 57protected:
58 LLStatAccum(bool use_frame_timer); 58 LLStatAccum(bool use_frame_timer);
@@ -109,7 +109,7 @@ public:
109 F64 mLastSampleValue; 109 F64 mLastSampleValue;
110}; 110};
111 111
112class LLStatMeasure : public LLStatAccum 112class LL_COMMON_API LLStatMeasure : public LLStatAccum
113 // gathers statistics about things that are measured 113 // gathers statistics about things that are measured
114 // ex.: tempature, time dilation 114 // ex.: tempature, time dilation
115{ 115{
@@ -124,7 +124,7 @@ public:
124}; 124};
125 125
126 126
127class LLStatRate : public LLStatAccum 127class LL_COMMON_API LLStatRate : public LLStatAccum
128 // gathers statistics about things that can be counted over time 128 // gathers statistics about things that can be counted over time
129 // ex.: LSL instructions executed, messages sent, simulator frames completed 129 // ex.: LSL instructions executed, messages sent, simulator frames completed
130 // renders it in terms of rate of thing per second 130 // renders it in terms of rate of thing per second
@@ -140,7 +140,7 @@ public:
140}; 140};
141 141
142 142
143class LLStatTime : public LLStatAccum 143class LL_COMMON_API LLStatTime : public LLStatAccum
144 // gathers statistics about time spent in a block of code 144 // gathers statistics about time spent in a block of code
145 // measure average duration per second in the block 145 // measure average duration per second in the block
146{ 146{
@@ -171,7 +171,7 @@ private:
171 171
172 172
173// Use this class on the stack to record statistics about an area of code 173// Use this class on the stack to record statistics about an area of code
174class LLPerfBlock 174class LL_COMMON_API LLPerfBlock
175{ 175{
176public: 176public:
177 struct StatEntry 177 struct StatEntry
@@ -213,7 +213,7 @@ private:
213 213
214// ---------------------------------------------------------------------------- 214// ----------------------------------------------------------------------------
215 215
216class LLPerfStats 216class LL_COMMON_API LLPerfStats
217{ 217{
218public: 218public:
219 LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0); 219 LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0);
@@ -249,7 +249,7 @@ private:
249}; 249};
250 250
251// ---------------------------------------------------------------------------- 251// ----------------------------------------------------------------------------
252class LLStat 252class LL_COMMON_API LLStat
253{ 253{
254public: 254public:
255 LLStat(const U32 num_bins = 32, BOOL use_frame_timer = FALSE); 255 LLStat(const U32 num_bins = 32, BOOL use_frame_timer = FALSE);
diff --git a/linden/indra/llcommon/llstreamtools.h b/linden/indra/llcommon/llstreamtools.h
index a6dc4d5..371fac5 100644
--- a/linden/indra/llcommon/llstreamtools.h
+++ b/linden/indra/llcommon/llstreamtools.h
@@ -39,23 +39,23 @@
39// unless specifed otherwise these all return input_stream.good() 39// unless specifed otherwise these all return input_stream.good()
40 40
41// skips spaces and tabs 41// skips spaces and tabs
42bool skip_whitespace(std::istream& input_stream); 42LL_COMMON_API bool skip_whitespace(std::istream& input_stream);
43 43
44// skips whitespace and newlines 44// skips whitespace and newlines
45bool skip_emptyspace(std::istream& input_stream); 45LL_COMMON_API bool skip_emptyspace(std::istream& input_stream);
46 46
47// skips emptyspace and lines that start with a # 47// skips emptyspace and lines that start with a #
48bool skip_comments_and_emptyspace(std::istream& input_stream); 48LL_COMMON_API bool skip_comments_and_emptyspace(std::istream& input_stream);
49 49
50// skips to character after next newline 50// skips to character after next newline
51bool skip_line(std::istream& input_stream); 51LL_COMMON_API bool skip_line(std::istream& input_stream);
52 52
53// skips to beginning of next non-emptyspace 53// skips to beginning of next non-emptyspace
54bool skip_to_next_word(std::istream& input_stream); 54LL_COMMON_API bool skip_to_next_word(std::istream& input_stream);
55 55
56// skips to character after the end of next keyword 56// skips to character after the end of next keyword
57// a 'keyword' is defined as the first word on a line 57// a 'keyword' is defined as the first word on a line
58bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream); 58LL_COMMON_API bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream);
59 59
60// skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug 60// skip_to_start_of_next_keyword() is disabled -- might tickle corruption bug
61// in windows iostream 61// in windows iostream
@@ -65,14 +65,14 @@ bool skip_to_end_of_next_keyword(const char* keyword, std::istream& input_stream
65 65
66// characters are pulled out of input_stream and appended to output_string 66// characters are pulled out of input_stream and appended to output_string
67// returns result of input_stream.good() after characters are pulled 67// returns result of input_stream.good() after characters are pulled
68bool get_word(std::string& output_string, std::istream& input_stream); 68LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream);
69bool get_line(std::string& output_string, std::istream& input_stream); 69LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream);
70 70
71// characters are pulled out of input_stream (up to a max of 'n') 71// characters are pulled out of input_stream (up to a max of 'n')
72// and appended to output_string 72// and appended to output_string
73// returns result of input_stream.good() after characters are pulled 73// returns result of input_stream.good() after characters are pulled
74bool get_word(std::string& output_string, std::istream& input_stream, int n); 74LL_COMMON_API bool get_word(std::string& output_string, std::istream& input_stream, int n);
75bool get_line(std::string& output_string, std::istream& input_stream, int n); 75LL_COMMON_API bool get_line(std::string& output_string, std::istream& input_stream, int n);
76 76
77// unget_line() is disabled -- might tickle corruption bug in windows iostream 77// unget_line() is disabled -- might tickle corruption bug in windows iostream
78//// backs up the input_stream by line_size + 1 characters 78//// backs up the input_stream by line_size + 1 characters
@@ -82,28 +82,28 @@ bool get_line(std::string& output_string, std::istream& input_stream, int n);
82 82
83// removes the last char in 'line' if it matches 'c' 83// removes the last char in 'line' if it matches 'c'
84// returns true if removed last char 84// returns true if removed last char
85bool remove_last_char(char c, std::string& line); 85LL_COMMON_API bool remove_last_char(char c, std::string& line);
86 86
87// replaces escaped characters with the correct characters from left to right 87// replaces escaped characters with the correct characters from left to right
88// "\\" ---> '\\' 88// "\\" ---> '\\'
89// "\n" ---> '\n' 89// "\n" ---> '\n'
90void unescape_string(std::string& line); 90LL_COMMON_API void unescape_string(std::string& line);
91 91
92// replaces unescaped characters with expanded equivalents from left to right 92// replaces unescaped characters with expanded equivalents from left to right
93// '\\' ---> "\\" 93// '\\' ---> "\\"
94// '\n' ---> "\n" 94// '\n' ---> "\n"
95void escape_string(std::string& line); 95LL_COMMON_API void escape_string(std::string& line);
96 96
97// replaces each '\n' character with ' ' 97// replaces each '\n' character with ' '
98void replace_newlines_with_whitespace(std::string& line); 98LL_COMMON_API void replace_newlines_with_whitespace(std::string& line);
99 99
100// erases any double-quote characters in line 100// erases any double-quote characters in line
101void remove_double_quotes(std::string& line); 101LL_COMMON_API void remove_double_quotes(std::string& line);
102 102
103// the 'keyword' is defined as the first word on a line 103// the 'keyword' is defined as the first word on a line
104// the 'value' is everything after the keyword on the same line 104// the 'value' is everything after the keyword on the same line
105// starting at the first non-whitespace and ending right before the newline 105// starting at the first non-whitespace and ending right before the newline
106void get_keyword_and_value(std::string& keyword, 106LL_COMMON_API void get_keyword_and_value(std::string& keyword,
107 std::string& value, 107 std::string& value,
108 const std::string& line); 108 const std::string& line);
109 109
@@ -111,13 +111,13 @@ void get_keyword_and_value(std::string& keyword,
111// read anymore or until we hit the count. Some istream 111// read anymore or until we hit the count. Some istream
112// implimentations have a max that they will read. 112// implimentations have a max that they will read.
113// Returns the number of bytes read. 113// Returns the number of bytes read.
114std::streamsize fullread( 114LL_COMMON_API std::streamsize fullread(
115 std::istream& istr, 115 std::istream& istr,
116 char* buf, 116 char* buf,
117 std::streamsize requested); 117 std::streamsize requested);
118 118
119 119
120std::istream& operator>>(std::istream& str, const char *tocheck); 120LL_COMMON_API std::istream& operator>>(std::istream& str, const char *tocheck);
121 121
122#endif 122#endif
123 123
diff --git a/linden/indra/llcommon/llstring.cpp b/linden/indra/llcommon/llstring.cpp
index 1f653c1..cd5a9f2 100644
--- a/linden/indra/llcommon/llstring.cpp
+++ b/linden/indra/llcommon/llstring.cpp
@@ -50,7 +50,8 @@ std::string ll_safe_string(const char* in)
50 50
51std::string ll_safe_string(const char* in, S32 maxlen) 51std::string ll_safe_string(const char* in, S32 maxlen)
52{ 52{
53 if(in) return std::string(in, maxlen); 53//KOKUA FIXME: Which wormhole all the antistrings (strings with negative length) come from ?
54 if(in && maxlen > 0) return std::string(in, maxlen);
54 return std::string(); 55 return std::string();
55} 56}
56 57
@@ -595,6 +596,40 @@ std::string utf8str_removeCRLF(const std::string& utf8str)
595 return out; 596 return out;
596} 597}
597 598
599bool is_hex_string(U8* str, S32 len)
600{
601 bool rv = true;
602 U8* c = str;
603 while(rv && len--)
604 {
605 switch(*c)
606 {
607 case '0':
608 case '1':
609 case '2':
610 case '3':
611 case '4':
612 case '5':
613 case '6':
614 case '7':
615 case '8':
616 case '9':
617 case 'a':
618 case 'b':
619 case 'c':
620 case 'd':
621 case 'e':
622 case 'f':
623 ++c;
624 break;
625 default:
626 rv = false;
627 break;
628 }
629 }
630 return rv;
631}
632
598#if LL_WINDOWS 633#if LL_WINDOWS
599// documentation moved to header. Phoenix 2007-11-27 634// documentation moved to header. Phoenix 2007-11-27
600namespace snprintf_hack 635namespace snprintf_hack
diff --git a/linden/indra/llcommon/llstring.h b/linden/indra/llcommon/llstring.h
index 7db62bc..a592e2c 100644
--- a/linden/indra/llcommon/llstring.h
+++ b/linden/indra/llcommon/llstring.h
@@ -34,12 +34,14 @@
34#define LL_LLSTRING_H 34#define LL_LLSTRING_H
35 35
36#include <string> 36#include <string>
37#include <cstdio>
38#include <algorithm>
39#include <map>
37 40
38#if LL_LINUX || LL_SOLARIS 41#if LL_LINUX || LL_SOLARIS
39#include <wctype.h> 42#include <wctype.h>
40#include <wchar.h> 43#include <wchar.h>
41#endif 44#endif
42#include "linden_common.h"
43 45
44#include <string.h> 46#include <string.h>
45 47
@@ -144,7 +146,7 @@ struct char_traits<U16>
144}; 146};
145#endif 147#endif
146 148
147class LLStringOps 149class LL_COMMON_API LLStringOps
148{ 150{
149public: 151public:
150 static char toUpper(char elem) { return toupper((unsigned char)elem); } 152 static char toUpper(char elem) { return toupper((unsigned char)elem); }
@@ -179,8 +181,8 @@ public:
179 * @brief Return a string constructed from in without crashing if the 181 * @brief Return a string constructed from in without crashing if the
180 * pointer is NULL. 182 * pointer is NULL.
181 */ 183 */
182std::string ll_safe_string(const char* in); 184std::string LL_COMMON_API ll_safe_string(const char* in);
183std::string ll_safe_string(const char* in, S32 maxlen); 185std::string LL_COMMON_API ll_safe_string(const char* in, S32 maxlen);
184 186
185 187
186// Allowing assignments from non-strings into format_map_t is apparently 188// Allowing assignments from non-strings into format_map_t is apparently
@@ -209,7 +211,7 @@ public:
209 ///////////////////////////////////////////////////////////////////////////////////////// 211 /////////////////////////////////////////////////////////////////////////////////////////
210 // Static Utility functions that operate on std::strings 212 // Static Utility functions that operate on std::strings
211 213
212 static std::basic_string<T> null; 214 static std::basic_string<T> const null;
213 215
214 typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t; 216 typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
215 static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map); 217 static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
@@ -236,7 +238,8 @@ public:
236 static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab ); 238 static void replaceTabsWithSpaces( std::basic_string<T>& string, size_type spaces_per_tab );
237 static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement ); 239 static void replaceNonstandardASCII( std::basic_string<T>& string, T replacement );
238 static void replaceChar( std::basic_string<T>& string, T target, T replacement ); 240 static void replaceChar( std::basic_string<T>& string, T target, T replacement );
239 241 static void replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement );
242
240 static BOOL containsNonprintable(const std::basic_string<T>& string); 243 static BOOL containsNonprintable(const std::basic_string<T>& string);
241 static void stripNonprintable(std::basic_string<T>& string); 244 static void stripNonprintable(std::basic_string<T>& string);
242 245
@@ -299,7 +302,7 @@ public:
299 302
300}; 303};
301 304
302template<class T> std::basic_string<T> LLStringUtilBase<T>::null; 305template<class T> std::basic_string<T> const LLStringUtilBase<T>::null;
303 306
304typedef LLStringUtilBase<char> LLStringUtil; 307typedef LLStringUtilBase<char> LLStringUtil;
305typedef LLStringUtilBase<llwchar> LLWStringUtil; 308typedef LLStringUtilBase<llwchar> LLWStringUtil;
@@ -349,7 +352,7 @@ inline std::string chop_tail_copy(
349 * @brief This translates a nybble stored as a hex value from 0-f back 352 * @brief This translates a nybble stored as a hex value from 0-f back
350 * to a nybble in the low order bits of the return byte. 353 * to a nybble in the low order bits of the return byte.
351 */ 354 */
352U8 hex_as_nybble(char hex); 355LL_COMMON_API U8 hex_as_nybble(char hex);
353 356
354/** 357/**
355 * @brief read the contents of a file into a string. 358 * @brief read the contents of a file into a string.
@@ -360,7 +363,7 @@ U8 hex_as_nybble(char hex);
360 * @param filename The full name of the file to read. 363 * @param filename The full name of the file to read.
361 * @return Returns true on success. If false, str is unmodified. 364 * @return Returns true on success. If false, str is unmodified.
362 */ 365 */
363bool _read_file_into_string(std::string& str, const std::string& filename); 366LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename);
364 367
365/** 368/**
366 * Unicode support 369 * Unicode support
@@ -369,52 +372,52 @@ bool _read_file_into_string(std::string& str, const std::string& filename);
369// Make the incoming string a utf8 string. Replaces any unknown glyph 372// Make the incoming string a utf8 string. Replaces any unknown glyph
370// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest 373// with the UNKOWN_CHARACTER. Once any unknown glph is found, the rest
371// of the data may not be recovered. 374// of the data may not be recovered.
372std::string rawstr_to_utf8(const std::string& raw); 375LL_COMMON_API std::string rawstr_to_utf8(const std::string& raw);
373 376
374// 377//
375// We should never use UTF16 except when communicating with Win32! 378// We should never use UTF16 except when communicating with Win32!
376// 379//
377typedef std::basic_string<U16> llutf16string; 380typedef std::basic_string<U16> llutf16string;
378 381
379LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len); 382LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str, S32 len);
380LLWString utf16str_to_wstring(const llutf16string &utf16str); 383LL_COMMON_API LLWString utf16str_to_wstring(const llutf16string &utf16str);
381 384
382llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len); 385LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str, S32 len);
383llutf16string wstring_to_utf16str(const LLWString &utf32str); 386LL_COMMON_API llutf16string wstring_to_utf16str(const LLWString &utf32str);
384 387
385llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len); 388LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str, S32 len);
386llutf16string utf8str_to_utf16str ( const std::string& utf8str ); 389LL_COMMON_API llutf16string utf8str_to_utf16str ( const std::string& utf8str );
387 390
388LLWString utf8str_to_wstring(const std::string &utf8str, S32 len); 391LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str, S32 len);
389LLWString utf8str_to_wstring(const std::string &utf8str); 392LL_COMMON_API LLWString utf8str_to_wstring(const std::string &utf8str);
390// Same function, better name. JC 393// Same function, better name. JC
391inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); } 394inline LLWString utf8string_to_wstring(const std::string& utf8_string) { return utf8str_to_wstring(utf8_string); }
392 395
393// 396//
394S32 wchar_to_utf8chars(llwchar inchar, char* outchars); 397LL_COMMON_API S32 wchar_to_utf8chars(llwchar inchar, char* outchars);
395 398
396std::string wstring_to_utf8str(const LLWString &utf32str, S32 len); 399LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str, S32 len);
397std::string wstring_to_utf8str(const LLWString &utf32str); 400LL_COMMON_API std::string wstring_to_utf8str(const LLWString &utf32str);
398 401
399std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len); 402LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str, S32 len);
400std::string utf16str_to_utf8str(const llutf16string &utf16str); 403LL_COMMON_API std::string utf16str_to_utf8str(const llutf16string &utf16str);
401 404
402// Length of this UTF32 string in bytes when transformed to UTF8 405// Length of this UTF32 string in bytes when transformed to UTF8
403S32 wstring_utf8_length(const LLWString& wstr); 406LL_COMMON_API S32 wstring_utf8_length(const LLWString& wstr);
404 407
405// Length in bytes of this wide char in a UTF8 string 408// Length in bytes of this wide char in a UTF8 string
406S32 wchar_utf8_length(const llwchar wc); 409LL_COMMON_API S32 wchar_utf8_length(const llwchar wc);
407 410
408std::string utf8str_tolower(const std::string& utf8str); 411LL_COMMON_API std::string utf8str_tolower(const std::string& utf8str);
409 412
410// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string. 413// Length in llwchar (UTF-32) of the first len units (16 bits) of the given UTF-16 string.
411S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len); 414LL_COMMON_API S32 utf16str_wstring_length(const llutf16string &utf16str, S32 len);
412 415
413// Length in utf16string (UTF-16) of wlen wchars beginning at woffset. 416// Length in utf16string (UTF-16) of wlen wchars beginning at woffset.
414S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen); 417LL_COMMON_API S32 wstring_utf16_length(const LLWString & wstr, S32 woffset, S32 wlen);
415 418
416// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.) 419// Length in wstring (i.e., llwchar count) of a part of a wstring specified by utf16 length (i.e., utf16 units.)
417S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL); 420LL_COMMON_API S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset, S32 utf16_length, BOOL *unaligned = NULL);
418 421
419/** 422/**
420 * @brief Properly truncate a utf8 string to a maximum byte count. 423 * @brief Properly truncate a utf8 string to a maximum byte count.
@@ -426,11 +429,11 @@ S32 wstring_wstring_length_from_utf16_length(const LLWString & wstr, S32 woffset
426 * @param max_len The maximum number of bytes in the return value. 429 * @param max_len The maximum number of bytes in the return value.
427 * @return Returns a valid utf8 string with byte count <= max_len. 430 * @return Returns a valid utf8 string with byte count <= max_len.
428 */ 431 */
429std::string utf8str_truncate(const std::string& utf8str, const S32 max_len); 432LL_COMMON_API std::string utf8str_truncate(const std::string& utf8str, const S32 max_len);
430 433
431std::string utf8str_trim(const std::string& utf8str); 434LL_COMMON_API std::string utf8str_trim(const std::string& utf8str);
432 435
433S32 utf8str_compare_insensitive( 436LL_COMMON_API S32 utf8str_compare_insensitive(
434 const std::string& lhs, 437 const std::string& lhs,
435 const std::string& rhs); 438 const std::string& rhs);
436 439
@@ -441,17 +444,19 @@ S32 utf8str_compare_insensitive(
441 * @param target_char The wchar to be replaced 444 * @param target_char The wchar to be replaced
442 * @param replace_char The wchar which is written on replace 445 * @param replace_char The wchar which is written on replace
443 */ 446 */
444std::string utf8str_substChar( 447LL_COMMON_API std::string utf8str_substChar(
445 const std::string& utf8str, 448 const std::string& utf8str,
446 const llwchar target_char, 449 const llwchar target_char,
447 const llwchar replace_char); 450 const llwchar replace_char);
448 451
449std::string utf8str_makeASCII(const std::string& utf8str); 452LL_COMMON_API std::string utf8str_makeASCII(const std::string& utf8str);
450 453
451// Hack - used for evil notecards. 454// Hack - used for evil notecards.
452std::string mbcsstring_makeASCII(const std::string& str); 455LL_COMMON_API std::string mbcsstring_makeASCII(const std::string& str);
453 456
454std::string utf8str_removeCRLF(const std::string& utf8str); 457LL_COMMON_API std::string utf8str_removeCRLF(const std::string& utf8str);
458
459LL_COMMON_API bool is_hex_string(U8* str, S32 len);
455 460
456 461
457#if LL_WINDOWS 462#if LL_WINDOWS
@@ -476,14 +481,21 @@ std::string utf8str_removeCRLF(const std::string& utf8str);
476 * formatted string. 481 * formatted string.
477 * 482 *
478 */ 483 */
479int safe_snprintf(char* str, size_t size, const char* format, ...); 484
485// Deal with the differeneces on Windows
486namespace snprintf_hack
487{
488 LL_COMMON_API int snprintf(char *str, size_t size, const char *format, ...);
489}
490
491using snprintf_hack::snprintf;
480 492
481/** 493/**
482 * @brief Convert a wide string to std::string 494 * @brief Convert a wide string to std::string
483 * 495 *
484 * This replaces the unsafe W2A macro from ATL. 496 * This replaces the unsafe W2A macro from ATL.
485 */ 497 */
486std::string ll_convert_wide_to_string(const wchar_t* in); 498LL_COMMON_API std::string ll_convert_wide_to_string(const wchar_t* in);
487 499
488//@} 500//@}
489#endif // LL_WINDOWS 501#endif // LL_WINDOWS
@@ -506,7 +518,7 @@ namespace LLStringFn
506 * with zero non-printable characters. 518 * with zero non-printable characters.
507 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. 519 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
508 */ 520 */
509 void replace_nonprintable_in_ascii( 521 LL_COMMON_API void replace_nonprintable_in_ascii(
510 std::basic_string<char>& string, 522 std::basic_string<char>& string,
511 char replacement); 523 char replacement);
512 524
@@ -520,7 +532,7 @@ namespace LLStringFn
520 * with zero non-printable characters and zero pipe characters. 532 * with zero non-printable characters and zero pipe characters.
521 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. 533 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
522 */ 534 */
523 void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str, 535 LL_COMMON_API void replace_nonprintable_and_pipe_in_ascii(std::basic_string<char>& str,
524 char replacement); 536 char replacement);
525 537
526 538
@@ -529,7 +541,7 @@ namespace LLStringFn
529 * Returns a copy of the string with those characters removed. 541 * Returns a copy of the string with those characters removed.
530 * Works with US ASCII and UTF-8 encoded strings. JC 542 * Works with US ASCII and UTF-8 encoded strings. JC
531 */ 543 */
532 std::string strip_invalid_xml(const std::string& input); 544 LL_COMMON_API std::string strip_invalid_xml(const std::string& input);
533 545
534 546
535 /** 547 /**
@@ -540,7 +552,7 @@ namespace LLStringFn
540 * with zero non-printable characters. 552 * with zero non-printable characters.
541 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure. 553 * @param The replacement character. use LL_UNKNOWN_CHAR if unsure.
542 */ 554 */
543 void replace_ascii_controlchars( 555 LL_COMMON_API void replace_ascii_controlchars(
544 std::basic_string<char>& string, 556 std::basic_string<char>& string,
545 char replacement); 557 char replacement);
546} 558}
@@ -870,6 +882,7 @@ void LLStringUtilBase<T>::addCRLF(std::basic_string<T>& string)
870 } 882 }
871 883
872 string.assign(t, size); 884 string.assign(t, size);
885 delete[] t;
873 } 886 }
874} 887}
875 888
@@ -900,11 +913,22 @@ template<class T>
900void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement ) 913void LLStringUtilBase<T>::replaceChar( std::basic_string<T>& string, T target, T replacement )
901{ 914{
902 size_type found_pos = 0; 915 size_type found_pos = 0;
903 for (found_pos = string.find(target, found_pos); 916 while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
904 found_pos != std::basic_string<T>::npos;
905 found_pos = string.find(target, found_pos))
906 { 917 {
907 string[found_pos] = replacement; 918 string[found_pos] = replacement;
919 found_pos++; // avoid infinite defeat if target == replacement
920 }
921}
922
923//static
924template<class T>
925void LLStringUtilBase<T>::replaceString( std::basic_string<T>& string, std::basic_string<T> target, std::basic_string<T> replacement )
926{
927 size_type found_pos = 0;
928 while( (found_pos = string.find(target, found_pos)) != std::basic_string<T>::npos )
929 {
930 string.replace( found_pos, target.length(), replacement );
931 found_pos += replacement.length(); // avoid infinite defeat if replacement contains target
908 } 932 }
909} 933}
910 934
diff --git a/linden/indra/llcommon/llstringtable.h b/linden/indra/llcommon/llstringtable.h
index 4492063..b13b016 100644
--- a/linden/indra/llcommon/llstringtable.h
+++ b/linden/indra/llcommon/llstringtable.h
@@ -56,7 +56,7 @@
56 56
57const U32 MAX_STRINGS_LENGTH = 256; 57const U32 MAX_STRINGS_LENGTH = 256;
58 58
59class LLStringTableEntry 59class LL_COMMON_API LLStringTableEntry
60{ 60{
61public: 61public:
62 LLStringTableEntry(const char *str) 62 LLStringTableEntry(const char *str)
@@ -81,7 +81,7 @@ public:
81 S32 mCount; 81 S32 mCount;
82}; 82};
83 83
84class LLStringTable 84class LL_COMMON_API LLStringTable
85{ 85{
86public: 86public:
87 LLStringTable(int tablesize); 87 LLStringTable(int tablesize);
@@ -115,7 +115,7 @@ public:
115#endif 115#endif
116}; 116};
117 117
118extern LLStringTable gStringTable; 118extern LL_COMMON_API LLStringTable gStringTable;
119 119
120//============================================================================ 120//============================================================================
121 121
@@ -125,7 +125,7 @@ extern LLStringTable gStringTable;
125 125
126typedef const std::string* LLStdStringHandle; 126typedef const std::string* LLStdStringHandle;
127 127
128class LLStdStringTable 128class LL_COMMON_API LLStdStringTable
129{ 129{
130public: 130public:
131 LLStdStringTable(S32 tablesize = 0) 131 LLStdStringTable(S32 tablesize = 0)
diff --git a/linden/indra/llcommon/llsys.cpp b/linden/indra/llcommon/llsys.cpp
index a56ac47..95dd2e5 100644
--- a/linden/indra/llcommon/llsys.cpp
+++ b/linden/indra/llcommon/llsys.cpp
@@ -76,6 +76,75 @@ extern int errno;
76static const S32 CPUINFO_BUFFER_SIZE = 16383; 76static const S32 CPUINFO_BUFFER_SIZE = 16383;
77LLCPUInfo gSysCPU; 77LLCPUInfo gSysCPU;
78 78
79#if LL_WINDOWS
80#ifndef DLLVERSIONINFO
81typedef struct _DllVersionInfo
82{
83 DWORD cbSize;
84 DWORD dwMajorVersion;
85 DWORD dwMinorVersion;
86 DWORD dwBuildNumber;
87 DWORD dwPlatformID;
88}DLLVERSIONINFO;
89#endif
90
91#ifndef DLLGETVERSIONPROC
92typedef int (FAR WINAPI *DLLGETVERSIONPROC) (DLLVERSIONINFO *);
93#endif
94
95bool get_shell32_dll_version(DWORD& major, DWORD& minor, DWORD& build_number)
96{
97 bool result = false;
98 const U32 BUFF_SIZE = 32767;
99 WCHAR tempBuf[BUFF_SIZE];
100 if(GetSystemDirectory((LPWSTR)&tempBuf, BUFF_SIZE))
101 {
102
103 std::basic_string<WCHAR> shell32_path(tempBuf);
104
105 // Shell32.dll contains the DLLGetVersion function.
106 // according to msdn its not part of the API
107 // so you have to go in and get it.
108 // http://msdn.microsoft.com/en-us/library/bb776404(VS.85).aspx
109 shell32_path += TEXT("\\shell32.dll");
110
111 HMODULE hDllInst = LoadLibrary(shell32_path.c_str()); //load the DLL
112 if(hDllInst)
113 { // Could successfully load the DLL
114 DLLGETVERSIONPROC pDllGetVersion;
115 /*
116 You must get this function explicitly because earlier versions of the DLL
117 don't implement this function. That makes the lack of implementation of the
118 function a version marker in itself.
119 */
120 pDllGetVersion = (DLLGETVERSIONPROC) GetProcAddress(hDllInst,
121 "DllGetVersion");
122
123 if(pDllGetVersion)
124 {
125 // DLL supports version retrieval function
126 DLLVERSIONINFO dvi;
127
128 ZeroMemory(&dvi, sizeof(dvi));
129 dvi.cbSize = sizeof(dvi);
130 HRESULT hr = (*pDllGetVersion)(&dvi);
131
132 if(SUCCEEDED(hr))
133 { // Finally, the version is at our hands
134 major = dvi.dwMajorVersion;
135 minor = dvi.dwMinorVersion;
136 build_number = dvi.dwBuildNumber;
137 result = true;
138 }
139 }
140
141 FreeLibrary(hDllInst); // Release DLL
142 }
143 }
144 return result;
145}
146#endif // LL_WINDOWS
147
79LLOSInfo::LLOSInfo() : 148LLOSInfo::LLOSInfo() :
80 mMajorVer(0), mMinorVer(0), mBuild(0) 149 mMajorVer(0), mMinorVer(0), mBuild(0)
81{ 150{
@@ -98,44 +167,74 @@ LLOSInfo::LLOSInfo() :
98 mMinorVer = osvi.dwMinorVersion; 167 mMinorVer = osvi.dwMinorVersion;
99 mBuild = osvi.dwBuildNumber; 168 mBuild = osvi.dwBuildNumber;
100 169
170 DWORD shell32_major, shell32_minor, shell32_build;
171 bool got_shell32_version = get_shell32_dll_version(shell32_major,
172 shell32_minor,
173 shell32_build);
174
101 switch(osvi.dwPlatformId) 175 switch(osvi.dwPlatformId)
102 { 176 {
103 case VER_PLATFORM_WIN32_NT: 177 case VER_PLATFORM_WIN32_NT:
104 { 178 {
105 // Test for the product. 179 // Test for the product.
106 if(osvi.dwMajorVersion <= 4) 180 if (osvi.dwMajorVersion <= 4)
107 { 181 {
108 mOSStringSimple = "Microsoft Windows NT "; 182 mOSStringSimple = "Microsoft Windows NT ";
109 } 183 }
110 else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) 184 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
111 { 185 {
112 mOSStringSimple = "Microsoft Windows 2000 "; 186 mOSStringSimple = "Microsoft Windows 2000 ";
113 } 187 }
114 else if(osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1) 188 else if (osvi.dwMajorVersion ==5 && osvi.dwMinorVersion == 1)
115 { 189 {
116 mOSStringSimple = "Microsoft Windows XP "; 190 mOSStringSimple = "Microsoft Windows XP ";
117 } 191 }
118 else if(osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) 192 else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
119 { 193 {
120 if(osvi.wProductType == VER_NT_WORKSTATION) 194 if (osvi.wProductType == VER_NT_WORKSTATION)
195 {
121 mOSStringSimple = "Microsoft Windows XP x64 Edition "; 196 mOSStringSimple = "Microsoft Windows XP x64 Edition ";
122 else 197 }
123 mOSStringSimple = "Microsoft Windows Server 2003 "; 198 else
199 {
200 mOSStringSimple = "Microsoft Windows Server 2003 ";
201 }
124 } 202 }
125 else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 1) 203 else if (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion <= 2)
126 { 204 {
127 if(osvi.dwMinorVersion == 0) 205 if (osvi.dwMinorVersion == 0)
128 { 206 {
129 mOSStringSimple = "Microsoft Windows Vista "; 207 if (osvi.wProductType == VER_NT_WORKSTATION)
208 {
209 mOSStringSimple = "Microsoft Windows Vista ";
210 }
211 else
212 {
213 mOSStringSimple = "Windows Server 2008 ";
214 }
215
130 } 216 }
131 else if(osvi.dwMinorVersion == 1) 217 else if (osvi.dwMinorVersion == 1)
132 { 218 {
133 mOSStringSimple = "Microsoft Windows 7 "; 219 if (osvi.wProductType == VER_NT_WORKSTATION)
220 {
221 mOSStringSimple = "Microsoft Windows 7 ";
222 }
223 else
224 {
225 mOSStringSimple = "Windows Server 2008 R2 ";
226 }
134 } 227 }
135 228 else if (osvi.dwMinorVersion == 2)
136 if(osvi.wProductType != VER_NT_WORKSTATION)
137 { 229 {
138 mOSStringSimple += "Server "; 230 if (osvi.wProductType == VER_NT_WORKSTATION)
231 {
232 mOSStringSimple = "Microsoft Windows 8 ";
233 }
234 else
235 {
236 mOSStringSimple = "Windows Server 2012 ";
237 }
139 } 238 }
140 239
141 ///get native system info if available.. 240 ///get native system info if available..
@@ -146,8 +245,8 @@ LLOSInfo::LLOSInfo() :
146 pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function 245 pGNSI = (PGNSI) GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetNativeSystemInfo"); //load kernel32 get function
147 if(NULL != pGNSI) //check if it has failed 246 if(NULL != pGNSI) //check if it has failed
148 pGNSI(&si); //success 247 pGNSI(&si); //success
149 else 248 else
150 GetSystemInfo(&si); //if it fails get regular system info 249 GetSystemInfo(&si); //if it fails get regular system info
151 //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load) 250 //(Warning: If GetSystemInfo it may result in incorrect information in a WOW64 machine, if the kernel fails to load)
152 251
153 //msdn microsoft finds 32 bit and 64 bit flavors this way.. 252 //msdn microsoft finds 32 bit and 64 bit flavors this way..
@@ -206,6 +305,7 @@ LLOSInfo::LLOSInfo() :
206 csdversion.c_str(), 305 csdversion.c_str(),
207 (osvi.dwBuildNumber & 0xffff)); 306 (osvi.dwBuildNumber & 0xffff));
208 } 307 }
308
209 mOSString = mOSStringSimple + tmpstr; 309 mOSString = mOSStringSimple + tmpstr;
210 } 310 }
211 break; 311 break;
@@ -235,6 +335,20 @@ LLOSInfo::LLOSInfo() :
235 mOSString = mOSStringSimple; 335 mOSString = mOSStringSimple;
236 break; 336 break;
237 } 337 }
338
339 std::string compatibility_mode;
340 if(got_shell32_version)
341 {
342 if(osvi.dwMajorVersion != shell32_major || osvi.dwMinorVersion != shell32_minor)
343 {
344 compatibility_mode = llformat(" compatibility mode. real ver: %d.%d (Build %d)",
345 shell32_major,
346 shell32_minor,
347 shell32_build);
348 }
349 }
350 mOSString += compatibility_mode;
351
238#else 352#else
239 struct utsname un; 353 struct utsname un;
240 if(uname(&un) != -1) 354 if(uname(&un) != -1)
@@ -262,8 +376,8 @@ LLOSInfo::LLOSInfo() :
262 else if (ostype == "Linux") 376 else if (ostype == "Linux")
263 { 377 {
264 // Only care about major and minor Linux versions, truncate at second '.' 378 // Only care about major and minor Linux versions, truncate at second '.'
265 S32 idx1 = mOSStringSimple.find_first_of(".", 0); 379 std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
266 S32 idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos; 380 std::string::size_type idx2 = (idx1 != std::string::npos) ? mOSStringSimple.find_first_of(".", idx1+1) : std::string::npos;
267 std::string simple = mOSStringSimple.substr(0, idx2); 381 std::string simple = mOSStringSimple.substr(0, idx2);
268 if (simple.length() > 0) 382 if (simple.length() > 0)
269 mOSStringSimple = simple; 383 mOSStringSimple = simple;
@@ -429,15 +543,15 @@ LLCPUInfo::LLCPUInfo()
429 mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions; 543 mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions;
430 mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions; 544 mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions;
431 mHasAltivec = info->_Ext.Altivec_Extensions; 545 mHasAltivec = info->_Ext.Altivec_Extensions;
432 mCPUMhz = (S32)(proc.GetCPUFrequency(50)/1000000.0); 546 mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0);
433 mFamily.assign( info->strFamily ); 547 mFamily.assign( info->strFamily );
434 mCPUString = "Unknown"; 548 mCPUString = "Unknown";
435 549
436#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS 550#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
437 out << proc.strCPUName; 551 out << proc.strCPUName;
438 if (200 < mCPUMhz && mCPUMhz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check 552 if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check
439 { 553 {
440 out << " (" << mCPUMhz << " MHz)"; 554 out << " (" << mCPUMHz << " MHz)";
441 } 555 }
442 mCPUString = out.str(); 556 mCPUString = out.str();
443 557
@@ -482,7 +596,7 @@ LLCPUInfo::LLCPUInfo()
482 if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) 596 if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
483 && 200.0 < mhz && mhz < 10000.0) 597 && 200.0 < mhz && mhz < 10000.0)
484 { 598 {
485 mCPUMhz = (S32)llrint(mhz); 599 mCPUMHz = (F64)llrint(mhz);
486 } 600 }
487 if (!cpuinfo["model name"].empty()) 601 if (!cpuinfo["model name"].empty())
488 mCPUString = cpuinfo["model name"]; 602 mCPUString = cpuinfo["model name"];
@@ -505,9 +619,9 @@ bool LLCPUInfo::hasSSE2() const
505 return mHasSSE2; 619 return mHasSSE2;
506} 620}
507 621
508S32 LLCPUInfo::getMhz() const 622F64 LLCPUInfo::getMHz() const
509{ 623{
510 return mCPUMhz; 624 return mCPUMHz;
511} 625}
512 626
513std::string LLCPUInfo::getCPUString() const 627std::string LLCPUInfo::getCPUString() const
@@ -554,7 +668,7 @@ void LLCPUInfo::stream(std::ostream& s) const
554 s << "->mHasSSE: " << (U32)mHasSSE << std::endl; 668 s << "->mHasSSE: " << (U32)mHasSSE << std::endl;
555 s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl; 669 s << "->mHasSSE2: " << (U32)mHasSSE2 << std::endl;
556 s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl; 670 s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl;
557 s << "->mCPUMhz: " << mCPUMhz << std::endl; 671 s << "->mCPUMHz: " << mCPUMHz << std::endl;
558 s << "->mCPUString: " << mCPUString << std::endl; 672 s << "->mCPUString: " << mCPUString << std::endl;
559} 673}
560 674
@@ -631,6 +745,26 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const
631 } 745 }
632} 746}
633 747
748//static
749void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
750{
751#if LL_WINDOWS
752 MEMORYSTATUSEX state;
753 state.dwLength = sizeof(state);
754 GlobalMemoryStatusEx(&state);
755
756 avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ;
757 avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ;
758
759#else
760 //do not know how to collect available memory info for other systems.
761 //leave it blank here for now.
762
763 avail_physical_mem_kb = -1 ;
764 avail_virtual_mem_kb = -1 ;
765#endif
766}
767
634void LLMemoryInfo::stream(std::ostream& s) const 768void LLMemoryInfo::stream(std::ostream& s) const
635{ 769{
636#if LL_WINDOWS 770#if LL_WINDOWS
diff --git a/linden/indra/llcommon/llsys.h b/linden/indra/llcommon/llsys.h
index 03f48ca..e481c88 100644
--- a/linden/indra/llcommon/llsys.h
+++ b/linden/indra/llcommon/llsys.h
@@ -45,7 +45,7 @@
45#include <iosfwd> 45#include <iosfwd>
46#include <string> 46#include <string>
47 47
48class LLOSInfo 48class LL_COMMON_API LLOSInfo
49{ 49{
50public: 50public:
51 LLOSInfo(); 51 LLOSInfo();
@@ -70,7 +70,7 @@ private:
70}; 70};
71 71
72 72
73class LLCPUInfo 73class LL_COMMON_API LLCPUInfo
74{ 74{
75public: 75public:
76 LLCPUInfo(); 76 LLCPUInfo();
@@ -81,7 +81,7 @@ public:
81 bool hasAltivec() const; 81 bool hasAltivec() const;
82 bool hasSSE() const; 82 bool hasSSE() const;
83 bool hasSSE2() const; 83 bool hasSSE2() const;
84 S32 getMhz() const; 84 F64 getMHz() const;
85 85
86 // Family is "AMD Duron" or "Intel Pentium Pro" 86 // Family is "AMD Duron" or "Intel Pentium Pro"
87 const std::string& getFamily() const { return mFamily; } 87 const std::string& getFamily() const { return mFamily; }
@@ -90,7 +90,7 @@ private:
90 bool mHasSSE; 90 bool mHasSSE;
91 bool mHasSSE2; 91 bool mHasSSE2;
92 bool mHasAltivec; 92 bool mHasAltivec;
93 S32 mCPUMhz; 93 F64 mCPUMHz;
94 std::string mFamily; 94 std::string mFamily;
95 std::string mCPUString; 95 std::string mCPUString;
96}; 96};
@@ -99,7 +99,7 @@ private:
99// 99//
100// CLASS LLMemoryInfo 100// CLASS LLMemoryInfo
101 101
102class LLMemoryInfo 102class LL_COMMON_API LLMemoryInfo
103 103
104/*! @brief Class to query the memory subsystem 104/*! @brief Class to query the memory subsystem
105 105
@@ -120,18 +120,21 @@ public:
120 ** be returned. 120 ** be returned.
121 */ 121 */
122 U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes 122 U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
123
124 //get the available memory infomation in KiloBytes.
125 static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
123}; 126};
124 127
125 128
126std::ostream& operator<<(std::ostream& s, const LLOSInfo& info); 129LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLOSInfo& info);
127std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info); 130LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLCPUInfo& info);
128std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info); 131LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info);
129 132
130// gunzip srcfile into dstfile. Returns FALSE on error. 133// gunzip srcfile into dstfile. Returns FALSE on error.
131BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile); 134LL_COMMON_API BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile);
132// gzip srcfile into dstfile. Returns FALSE on error. 135// gzip srcfile into dstfile. Returns FALSE on error.
133BOOL gzip_file(const std::string& srcfile, const std::string& dstfile); 136LL_COMMON_API BOOL gzip_file(const std::string& srcfile, const std::string& dstfile);
134 137
135extern LLCPUInfo gSysCPU; 138LL_COMMON_API extern LLCPUInfo gSysCPU;
136 139
137#endif // LL_LLSYS_H 140#endif // LL_LLSYS_H
diff --git a/linden/indra/llcommon/llthread.cpp b/linden/indra/llcommon/llthread.cpp
index 692d6c4..f7732cb 100644
--- a/linden/indra/llcommon/llthread.cpp
+++ b/linden/indra/llcommon/llthread.cpp
@@ -72,8 +72,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
72 // Set thread state to running 72 // Set thread state to running
73 threadp->mStatus = RUNNING; 73 threadp->mStatus = RUNNING;
74 74
75 // Create a thread local APRFile pool. 75 // Create a thread local data.
76 LLVolatileAPRPool::createLocalAPRFilePool(); 76 AIThreadLocalData::create(threadp);
77 77
78 // Run the user supplied function 78 // Run the user supplied function
79 threadp->run(); 79 threadp->run();
@@ -87,24 +87,14 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
87} 87}
88 88
89 89
90LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : 90LLThread::LLThread(std::string const& name) :
91 mPaused(false), 91 mPaused(false),
92 mName(name), 92 mName(name),
93 mAPRThreadp(NULL), 93 mAPRThreadp(NULL),
94 mStatus(STOPPED) 94 mStatus(STOPPED),
95 mThreadLocalData(NULL)
95{ 96{
96 // Thread creation probably CAN be paranoid about APR being initialized, if necessary 97 mRunCondition = new LLCondition;
97 if (poolp)
98 {
99 mIsLocalPool = false;
100 mAPRPoolp = poolp;
101 }
102 else
103 {
104 mIsLocalPool = true;
105 apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
106 }
107 mRunCondition = new LLCondition(mAPRPoolp);
108} 98}
109 99
110 100
@@ -147,24 +137,18 @@ void LLThread::shutdown()
147 if (!isStopped()) 137 if (!isStopped())
148 { 138 {
149 // This thread just wouldn't stop, even though we gave it time 139 // This thread just wouldn't stop, even though we gave it time
150 llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl; 140 llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
151 return; 141 return;
152 } 142 }
153 mAPRThreadp = NULL; 143 mAPRThreadp = NULL;
154 } 144 }
155 145
156 delete mRunCondition; 146 delete mRunCondition;
157
158 if (mIsLocalPool)
159 {
160 apr_pool_destroy(mAPRPoolp);
161 }
162} 147}
163 148
164
165void LLThread::start() 149void LLThread::start()
166{ 150{
167 apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp); 151 apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
168 152
169 // We won't bother joining 153 // We won't bother joining
170 apr_thread_detach(mAPRThreadp); 154 apr_thread_detach(mAPRThreadp);
@@ -265,38 +249,72 @@ void LLThread::wakeLocked()
265 } 249 }
266} 250}
267 251
268//============================================================================ 252#ifdef SHOW_ASSERT
253// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
254static apr_os_thread_t main_thread_id;
255bool is_main_thread() { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); }
256#endif
269 257
270LLMutex::LLMutex(apr_pool_t *poolp) : 258// The thread private handle to access the AIThreadLocalData instance.
271 mAPRMutexp(NULL) 259apr_threadkey_t* AIThreadLocalData::sThreadLocalDataKey;
260
261//static
262void AIThreadLocalData::init(void)
272{ 263{
273 //if (poolp) 264 // Only do this once.
274 //{ 265 if (sThreadLocalDataKey)
275 // mIsLocalPool = false;
276 // mAPRPoolp = poolp;
277 //}
278 //else
279 { 266 {
280 mIsLocalPool = true; 267 return;
281 apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
282 } 268 }
283 apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp); 269
270 apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &AIThreadLocalData::destroy, AIAPRRootPool::get()());
271 ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the
272 // total number of keys per process {PTHREAD_KEYS_MAX}
273 // has been exceeded.
274
275 // Create the thread-local data for the main thread (this function is called by the main thread).
276 AIThreadLocalData::create(NULL);
277
278#ifdef SHOW_ASSERT
279 // This function is called by the main thread.
280 main_thread_id = apr_os_thread_current();
281#endif
284} 282}
285 283
286LLMutex::~LLMutex() 284// This is called once for every thread when the thread is destructed.
285//static
286void AIThreadLocalData::destroy(void* thread_local_data)
287{ 287{
288#if _DEBUG 288 delete reinterpret_cast<AIThreadLocalData*>(thread_local_data);
289 llassert(!isLocked()); // better not be locked! 289}
290#endif 290
291 apr_thread_mutex_destroy(mAPRMutexp); 291//static
292 mAPRMutexp = NULL; 292void AIThreadLocalData::create(LLThread* threadp)
293 if (mIsLocalPool) 293{
294 AIThreadLocalData* new_tld = new AIThreadLocalData;
295 if (threadp)
294 { 296 {
295 apr_pool_destroy(mAPRPoolp); 297 threadp->mThreadLocalData = new_tld;
296 } 298 }
299 apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey);
300 llassert_always(status == APR_SUCCESS);
297} 301}
298 302
299bool LLMutex::isLocked() 303//static
304AIThreadLocalData& AIThreadLocalData::tldata(void)
305{
306 if (!sThreadLocalDataKey)
307 AIThreadLocalData::init();
308
309 void* data;
310 apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey);
311 llassert_always(status == APR_SUCCESS);
312 return *static_cast<AIThreadLocalData*>(data);
313}
314
315//============================================================================
316
317bool LLMutexBase::isLocked()
300{ 318{
301 if (!tryLock()) 319 if (!tryLock())
302 { 320 {
@@ -308,12 +326,9 @@ bool LLMutex::isLocked()
308 326
309//============================================================================ 327//============================================================================
310 328
311LLCondition::LLCondition(apr_pool_t *poolp) : 329LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent)
312 LLMutex(poolp)
313{ 330{
314 // base class (LLMutex) has already ensured that mAPRPoolp is set up. 331 apr_thread_cond_create(&mAPRCondp, mPool());
315
316 apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
317} 332}
318 333
319LLCondition::~LLCondition() 334LLCondition::~LLCondition()
@@ -349,7 +364,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
349{ 364{
350 if (!sMutex) 365 if (!sMutex)
351 { 366 {
352 sMutex = new LLMutex(0); 367 sMutex = new LLMutex;
353 } 368 }
354} 369}
355 370
diff --git a/linden/indra/llcommon/llthread.h b/linden/indra/llcommon/llthread.h
index ed76a3b..1e982cc 100644
--- a/linden/indra/llcommon/llthread.h
+++ b/linden/indra/llcommon/llthread.h
@@ -38,12 +38,29 @@
38#include "llmemory.h" 38#include "llmemory.h"
39 39
40#include "apr_thread_cond.h" 40#include "apr_thread_cond.h"
41#include "aiaprpool.h"
41 42
42class LLThread; 43class LLThread;
43class LLMutex; 44class LLMutex;
44class LLCondition; 45class LLCondition;
45 46
46class LLThread 47class LL_COMMON_API AIThreadLocalData
48{
49private:
50 static apr_threadkey_t* sThreadLocalDataKey;
51
52public:
53 // Thread-local memory pool.
54 AIAPRRootPool mRootPool;
55 AIVolatileAPRPool mVolatileAPRPool;
56
57 static void init(void);
58 static void destroy(void* thread_local_data);
59 static void create(LLThread* pthread);
60 static AIThreadLocalData& tldata(void);
61};
62
63class LL_COMMON_API LLThread
47{ 64{
48public: 65public:
49 typedef enum e_thread_status 66 typedef enum e_thread_status
@@ -53,7 +70,7 @@ public:
53 QUITTING= 2 // Someone wants this thread to quit 70 QUITTING= 2 // Someone wants this thread to quit
54 } EThreadStatus; 71 } EThreadStatus;
55 72
56 LLThread(const std::string& name, apr_pool_t *poolp = NULL); 73 LLThread(std::string const& name);
57 virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state. 74 virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
58 virtual void shutdown(); // stops the thread 75 virtual void shutdown(); // stops the thread
59 76
@@ -82,7 +99,8 @@ public:
82 // this kicks off the apr thread 99 // this kicks off the apr thread
83 void start(void); 100 void start(void);
84 101
85 apr_pool_t *getAPRPool() { return mAPRPoolp; } 102 // Return thread-local data for the current thread.
103 static AIThreadLocalData& tldata(void) { return AIThreadLocalData::tldata(); }
86 104
87private: 105private:
88 bool mPaused; 106 bool mPaused;
@@ -95,10 +113,11 @@ protected:
95 LLCondition* mRunCondition; 113 LLCondition* mRunCondition;
96 114
97 apr_thread_t *mAPRThreadp; 115 apr_thread_t *mAPRThreadp;
98 apr_pool_t *mAPRPoolp;
99 bool mIsLocalPool;
100 EThreadStatus mStatus; 116 EThreadStatus mStatus;
101 117
118 friend void AIThreadLocalData::create(LLThread* threadp);
119 AIThreadLocalData* mThreadLocalData;
120
102 void setQuitting(); 121 void setQuitting();
103 122
104 // virtual function overridden by subclass -- this will be called when the thread runs 123 // virtual function overridden by subclass -- this will be called when the thread runs
@@ -125,12 +144,9 @@ protected:
125 144
126//============================================================================ 145//============================================================================
127 146
128class LLMutex 147class LL_COMMON_API LLMutexBase
129{ 148{
130public: 149public:
131 LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
132 ~LLMutex();
133
134 void lock() { apr_thread_mutex_lock(mAPRMutexp); } 150 void lock() { apr_thread_mutex_lock(mAPRMutexp); }
135 void unlock() { apr_thread_mutex_unlock(mAPRMutexp); } 151 void unlock() { apr_thread_mutex_unlock(mAPRMutexp); }
136 // Returns true if lock was obtained successfully. 152 // Returns true if lock was obtained successfully.
@@ -139,16 +155,60 @@ public:
139 bool isLocked(); // non-blocking, but does do a lock/unlock so not free 155 bool isLocked(); // non-blocking, but does do a lock/unlock so not free
140 156
141protected: 157protected:
142 apr_thread_mutex_t *mAPRMutexp; 158 // mAPRMutexp is initialized and uninitialized in the derived class.
143 apr_pool_t *mAPRPoolp; 159 apr_thread_mutex_t* mAPRMutexp;
144 bool mIsLocalPool; 160};
161
162class LL_COMMON_API LLMutex : public LLMutexBase
163{
164public:
165 LLMutex(AIAPRPool& parent = LLThread::tldata().mRootPool) : mPool(parent)
166 {
167 apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mPool());
168 }
169 ~LLMutex()
170 {
171 llassert(!isLocked()); // better not be locked!
172 apr_thread_mutex_destroy(mAPRMutexp);
173 mAPRMutexp = NULL;
174 }
175
176protected:
177 AIAPRPool mPool;
145}; 178};
146 179
180#if APR_HAS_THREADS
181// No need to use a root pool in this case.
182typedef LLMutex LLMutexRootPool;
183#else // APR_HAS_THREADS
184class LL_COMMON_API LLMutexRootPool : public LLMutexBase
185{
186public:
187 LLMutexRootPool(void)
188 {
189 apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mRootPool());
190 }
191 ~LLMutexRootPool()
192 {
193#if APR_POOL_DEBUG
194 // It is allowed to destruct root pools from a different thread.
195 mRootPool.grab_ownership();
196#endif
197 llassert(!isLocked()); // better not be locked!
198 apr_thread_mutex_destroy(mAPRMutexp);
199 mAPRMutexp = NULL;
200 }
201
202protected:
203 AIAPRRootPool mRootPool;
204};
205#endif // APR_HAS_THREADS
206
147// Actually a condition/mutex pair (since each condition needs to be associated with a mutex). 207// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
148class LLCondition : public LLMutex 208class LL_COMMON_API LLCondition : public LLMutex
149{ 209{
150public: 210public:
151 LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well. 211 LLCondition(AIAPRPool& parent = LLThread::tldata().mRootPool);
152 ~LLCondition(); 212 ~LLCondition();
153 213
154 void wait(); // blocks 214 void wait(); // blocks
@@ -159,10 +219,10 @@ protected:
159 apr_thread_cond_t *mAPRCondp; 219 apr_thread_cond_t *mAPRCondp;
160}; 220};
161 221
162class LLMutexLock 222class LL_COMMON_API LLMutexLock
163{ 223{
164public: 224public:
165 LLMutexLock(LLMutex* mutex) 225 LLMutexLock(LLMutexBase* mutex)
166 { 226 {
167 mMutex = mutex; 227 mMutex = mutex;
168 mMutex->lock(); 228 mMutex->lock();
@@ -172,7 +232,102 @@ public:
172 mMutex->unlock(); 232 mMutex->unlock();
173 } 233 }
174private: 234private:
175 LLMutex* mMutex; 235 LLMutexBase* mMutex;
236};
237
238class AIRWLock
239{
240public:
241 AIRWLock(AIAPRPool& parent = LLThread::tldata().mRootPool) :
242 mWriterWaitingMutex(parent), mNoHoldersCondition(parent), mHoldersCount(0), mWriterIsWaiting(false) { }
243
244private:
245 LLMutex mWriterWaitingMutex; //!< This mutex is locked while some writer is waiting for access.
246 LLCondition mNoHoldersCondition; //!< Access control for mHoldersCount. Condition true when there are no more holders.
247 int mHoldersCount; //!< Number of readers or -1 if a writer locked this object.
248 // This is volatile because we read it outside the critical area of mWriterWaitingMutex, at [1].
249 // That means that other threads can change it while we are already in the (inlined) function rdlock.
250 // Without volatile, the following assembly would fail:
251 // register x = mWriterIsWaiting;
252 // /* some thread changes mWriterIsWaiting */
253 // if (x ...
254 // However, because the function is fuzzy to begin with (we don't mind that this race
255 // condition exists) it would work fine without volatile. So, basically it's just here
256 // out of principle ;). -- Aleric
257 bool volatile mWriterIsWaiting; //!< True when there is a writer waiting for write access.
258
259public:
260 void rdlock(bool high_priority = false)
261 {
262 // Give a writer a higher priority (kinda fuzzy).
263 if (mWriterIsWaiting && !high_priority) // [1] If there is a writer interested,
264 {
265 mWriterWaitingMutex.lock(); // [2] then give it precedence and wait here.
266 // If we get here then the writer got it's access; mHoldersCount == -1.
267 mWriterWaitingMutex.unlock();
268 }
269 mNoHoldersCondition.lock(); // [3] Get exclusive access to mHoldersCount.
270 while (mHoldersCount == -1) // [4]
271 {
272 mNoHoldersCondition.wait(); // [5] Wait till mHoldersCount is (or just was) 0.
273 }
274 ++mHoldersCount; // One more reader.
275 mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
276 }
277 void rdunlock(void)
278 {
279 mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
280 if (--mHoldersCount == 0) // Was this the last reader?
281 {
282 mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7].
283 }
284 mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
285 }
286 void wrlock(void)
287 {
288 mWriterWaitingMutex.lock(); // Block new readers, see [2],
289 mWriterIsWaiting = true; // from this moment on, see [1].
290 mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
291 while (mHoldersCount != 0) // Other readers or writers have this lock?
292 {
293 mNoHoldersCondition.wait(); // [6] Wait till mHoldersCount is (or just was) 0.
294 }
295 mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1].
296 mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3].
297 mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]).
298 mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]).
299 }
300 void wrunlock(void)
301 {
302 mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
303 mHoldersCount = 0; // We have no writer anymore.
304 mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7].
305 mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
306 }
307 void rd2wrlock(void)
308 {
309 mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. Blocks new readers at [3].
310 if (--mHoldersCount > 0) // Any other reads left?
311 {
312 mWriterWaitingMutex.lock(); // Block new readers, see [2],
313 mWriterIsWaiting = true; // from this moment on, see [1].
314 while (mHoldersCount != 0) // Other readers (still) have this lock?
315 {
316 mNoHoldersCondition.wait(); // [7] Wait till mHoldersCount is (or just was) 0.
317 }
318 mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1].
319 mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3].
320 }
321 mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]).
322 mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]).
323 }
324 void wr2rdlock(void)
325 {
326 mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
327 mHoldersCount = 1; // Turn writer into a reader.
328 mNoHoldersCondition.signal(); // Tell waiting readers, see [5].
329 mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
330 }
176}; 331};
177 332
178//============================================================================ 333//============================================================================
@@ -187,12 +342,11 @@ void LLThread::unlockData()
187 mRunCondition->unlock(); 342 mRunCondition->unlock();
188} 343}
189 344
190
191//============================================================================ 345//============================================================================
192 346
193// see llmemory.h for LLPointer<> definition 347// see llmemory.h for LLPointer<> definition
194 348
195class LLThreadSafeRefCount 349class LL_COMMON_API LLThreadSafeRefCount
196{ 350{
197public: 351public:
198 static void initThreadSafeRefCount(); // creates sMutex 352 static void initThreadSafeRefCount(); // creates sMutex
@@ -244,7 +398,7 @@ private:
244 398
245// Simple responder for self destructing callbacks 399// Simple responder for self destructing callbacks
246// Pure virtual class 400// Pure virtual class
247class LLResponder : public LLThreadSafeRefCount 401class LL_COMMON_API LLResponder : public LLThreadSafeRefCount
248{ 402{
249protected: 403protected:
250 virtual ~LLResponder(); 404 virtual ~LLResponder();
diff --git a/linden/indra/llcommon/lltimer.cpp b/linden/indra/llcommon/lltimer.cpp
index fa6efaf..b825c1e 100644
--- a/linden/indra/llcommon/lltimer.cpp
+++ b/linden/indra/llcommon/lltimer.cpp
@@ -33,6 +33,7 @@
33#include "linden_common.h" 33#include "linden_common.h"
34 34
35#include "lltimer.h" 35#include "lltimer.h"
36#include "timing.h" // totalTime prototype.
36 37
37#include "u64.h" 38#include "u64.h"
38 39
@@ -51,9 +52,6 @@
51// 52//
52// Locally used constants 53// Locally used constants
53// 54//
54const U32 SEC_PER_DAY = 86400;
55const F64 SEC_TO_MICROSEC = 1000000.f;
56const U64 SEC_TO_MICROSEC_U64 = 1000000;
57const F64 USEC_TO_SEC_F64 = 0.000001; 55const F64 USEC_TO_SEC_F64 = 0.000001;
58 56
59 57
@@ -527,6 +525,34 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
527} 525}
528 526
529 527
528struct tm* utc_to_offset_time(time_t utc_time, S32 offset, BOOL DST)
529{
530 if (DST)
531 {
532 //Add one then
533 offset++;
534 }
535
536 // We subtract off the PST/PDT offset _before_ getting
537 // "UTC" time, because this will handle wrapping around
538 // for 5 AM UTC -> 10 PM PDT of the previous day.
539 utc_time -= (-1 * offset) * MIN_PER_HOUR * SEC_PER_MIN;
540
541 // Internal buffer to PST/PDT (see above)
542 struct tm* internal_time = gmtime(&utc_time);
543
544 /*
545 // Don't do this, this won't correctly tell you if daylight savings is active in CA or not.
546 if (pacific_daylight_time)
547 {
548 internal_time->tm_isdst = 1;
549 }
550 */
551
552 return internal_time;
553}
554
555
530void microsecondsToTimecodeString(U64 current_time, std::string& tcstring) 556void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
531{ 557{
532 U64 hours; 558 U64 hours;
diff --git a/linden/indra/llcommon/lltimer.h b/linden/indra/llcommon/lltimer.h
index e2cf1c7..8590328 100644
--- a/linden/indra/llcommon/lltimer.h
+++ b/linden/indra/llcommon/lltimer.h
@@ -39,6 +39,7 @@
39#include <limits.h> 39#include <limits.h>
40 40
41#include "stdtypes.h" 41#include "stdtypes.h"
42#include "llpreprocessor.h"
42#include "lldate.h" 43#include "lldate.h"
43 44
44#include <string> 45#include <string>
@@ -54,7 +55,7 @@ const U32 USEC_PER_HOUR = USEC_PER_MIN * MIN_PER_HOUR;
54const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR; 55const U32 SEC_PER_HOUR = SEC_PER_MIN * MIN_PER_HOUR;
55const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC; 56const F64 SEC_PER_USEC = 1.0 / (F64) USEC_PER_SEC;
56 57
57class LLTimer 58class LL_COMMON_API LLTimer
58{ 59{
59public: 60public:
60 static LLTimer *sTimer; // global timer 61 static LLTimer *sTimer; // global timer
@@ -113,17 +114,17 @@ public:
113// 114//
114// Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work. 115// Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work.
115// 116//
116U64 get_clock_count(); 117LL_COMMON_API U64 get_clock_count();
117F64 calc_clock_frequency(U32 msecs); 118LL_COMMON_API F64 calc_clock_frequency(U32 msecs);
118void update_clock_frequencies(); 119LL_COMMON_API void update_clock_frequencies();
119 120
120// Sleep for milliseconds 121// Sleep for milliseconds
121void ms_sleep(U32 ms); 122LL_COMMON_API void ms_sleep(U32 ms);
122U32 micro_sleep(U64 us, U32 max_yields = 0xFFFFFFFF); 123LL_COMMON_API U32 micro_sleep(U64 us, U32 max_yields = 0xFFFFFFFF);
123 124
124// Returns the correct UTC time in seconds, like time(NULL). 125// Returns the correct UTC time in seconds, like time(NULL).
125// Useful on the viewer, which may have its local clock set wrong. 126// Useful on the viewer, which may have its local clock set wrong.
126time_t time_corrected(); 127LL_COMMON_API time_t time_corrected();
127 128
128static inline time_t time_min() 129static inline time_t time_min()
129{ 130{
@@ -154,24 +155,25 @@ static inline time_t time_max()
154} 155}
155 156
156// Correction factor used by time_corrected() above. 157// Correction factor used by time_corrected() above.
157extern S32 gUTCOffset; 158LL_COMMON_API extern S32 gUTCOffset;
158 159
159// Is the current computer (in its current time zone) 160// Is the current computer (in its current time zone)
160// observing daylight savings time? 161// observing daylight savings time?
161BOOL is_daylight_savings(); 162LL_COMMON_API BOOL is_daylight_savings();
162 163
163// Converts internal "struct tm" time buffer to Pacific Standard/Daylight Time 164// Converts internal "struct tm" time buffer to Pacific Standard/Daylight Time
164// Usage: 165// Usage:
165// S32 utc_time; 166// S32 utc_time;
166// utc_time = time_corrected(); 167// utc_time = time_corrected();
167// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight); 168// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
168struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time); 169LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
170LL_COMMON_API struct tm* utc_to_offset_time(time_t utc_time, S32 offset, BOOL DST);
169 171
170void microsecondsToTimecodeString(U64 current_time, std::string& tcstring); 172LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
171void secondsToTimecodeString(F32 current_time, std::string& tcstring); 173LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
172 174
173// class for scheduling a function to be called at a given frequency (approximate, inprecise) 175// class for scheduling a function to be called at a given frequency (approximate, inprecise)
174class LLEventTimer 176class LL_COMMON_API LLEventTimer
175{ 177{
176public: 178public:
177 LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds 179 LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds
diff --git a/linden/indra/llcommon/lluri.h b/linden/indra/llcommon/lluri.h
index 156d80b..57bbedf 100644
--- a/linden/indra/llcommon/lluri.h
+++ b/linden/indra/llcommon/lluri.h
@@ -47,7 +47,7 @@ class LLApp;
47 * See: http://www.ietf.org/rfc/rfc3986.txt 47 * See: http://www.ietf.org/rfc/rfc3986.txt
48 * 48 *
49 */ 49 */
50class LLURI 50class LL_COMMON_API LLURI
51{ 51{
52public: 52public:
53 LLURI(); 53 LLURI();
@@ -189,6 +189,6 @@ private:
189}; 189};
190 190
191// this operator required for tut 191// this operator required for tut
192bool operator!=(const LLURI& first, const LLURI& second); 192LL_COMMON_API bool operator!=(const LLURI& first, const LLURI& second);
193 193
194#endif // LL_LLURI_H 194#endif // LL_LLURI_H
diff --git a/linden/indra/llcommon/lluuid.h b/linden/indra/llcommon/lluuid.h
index 4b32138..c78fb12 100644
--- a/linden/indra/llcommon/lluuid.h
+++ b/linden/indra/llcommon/lluuid.h
@@ -35,6 +35,7 @@
35#include <iostream> 35#include <iostream>
36#include <set> 36#include <set>
37#include "stdtypes.h" 37#include "stdtypes.h"
38#include "llpreprocessor.h"
38 39
39const S32 UUID_BYTES = 16; 40const S32 UUID_BYTES = 16;
40const S32 UUID_WORDS = 4; 41const S32 UUID_WORDS = 4;
@@ -47,7 +48,7 @@ struct uuid_time_t {
47 U32 low; 48 U32 low;
48 }; 49 };
49 50
50class LLUUID 51class LL_COMMON_API LLUUID
51{ 52{
52public: 53public:
53 // 54 //
@@ -106,8 +107,8 @@ public:
106 LLUUID combine(const LLUUID& other) const; 107 LLUUID combine(const LLUUID& other) const;
107 void combine(const LLUUID& other, LLUUID& result) const; 108 void combine(const LLUUID& other, LLUUID& result) const;
108 109
109 friend std::ostream& operator<<(std::ostream& s, const LLUUID &uuid); 110 friend LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLUUID &uuid);
110 friend std::istream& operator>>(std::istream& s, LLUUID &uuid); 111 friend LL_COMMON_API std::istream& operator>>(std::istream& s, LLUUID &uuid);
111 112
112 void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0) 113 void toString(char *out) const; // Does not allocate memory, needs 36 characters (including \0)
113 void toString(std::string& out) const; 114 void toString(std::string& out) const;
@@ -323,7 +324,7 @@ typedef std::set<LLUUID, lluuid_less> uuid_list_t;
323 */ 324 */
324typedef LLUUID LLAssetID; 325typedef LLUUID LLAssetID;
325 326
326class LLTransactionID : public LLUUID 327class LL_COMMON_API LLTransactionID : public LLUUID
327{ 328{
328public: 329public:
329 LLTransactionID() : LLUUID() { } 330 LLTransactionID() : LLUUID() { }
diff --git a/linden/indra/llcommon/llworkerthread.cpp b/linden/indra/llcommon/llworkerthread.cpp
index 8195e1c..e238a89 100644
--- a/linden/indra/llcommon/llworkerthread.cpp
+++ b/linden/indra/llcommon/llworkerthread.cpp
@@ -43,7 +43,7 @@
43LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) : 43LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) :
44 LLQueuedThread(name, threaded) 44 LLQueuedThread(name, threaded)
45{ 45{
46 mDeleteMutex = new LLMutex(NULL); 46 mDeleteMutex = new LLMutex;
47} 47}
48 48
49LLWorkerThread::~LLWorkerThread() 49LLWorkerThread::~LLWorkerThread()
@@ -183,7 +183,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
183 : mWorkerThread(workerthread), 183 : mWorkerThread(workerthread),
184 mWorkerClassName(name), 184 mWorkerClassName(name),
185 mRequestHandle(LLWorkerThread::nullHandle()), 185 mRequestHandle(LLWorkerThread::nullHandle()),
186 mMutex(NULL),
187 mWorkFlags(0) 186 mWorkFlags(0)
188{ 187{
189 if (!mWorkerThread) 188 if (!mWorkerThread)
diff --git a/linden/indra/llcommon/llworkerthread.h b/linden/indra/llcommon/llworkerthread.h
index 708d812..8e0dd8a 100644
--- a/linden/indra/llcommon/llworkerthread.h
+++ b/linden/indra/llcommon/llworkerthread.h
@@ -50,7 +50,7 @@ class LLWorkerClass;
50// Note: ~LLWorkerThread is O(N) N=# of worker threads, assumed to be small 50// Note: ~LLWorkerThread is O(N) N=# of worker threads, assumed to be small
51// It is assumed that LLWorkerThreads are rarely created/destroyed. 51// It is assumed that LLWorkerThreads are rarely created/destroyed.
52 52
53class LLWorkerThread : public LLQueuedThread 53class LL_COMMON_API LLWorkerThread : public LLQueuedThread
54{ 54{
55 friend class LLWorkerClass; 55 friend class LLWorkerClass;
56public: 56public:
@@ -114,7 +114,7 @@ public:
114// Only one background task can be active at a time (per instance). 114// Only one background task can be active at a time (per instance).
115// i.e. don't call addWork() if haveWork() returns true 115// i.e. don't call addWork() if haveWork() returns true
116 116
117class LLWorkerClass 117class LL_COMMON_API LLWorkerClass
118{ 118{
119 friend class LLWorkerThread; 119 friend class LLWorkerThread;
120 friend class LLWorkerThread::WorkRequest; 120 friend class LLWorkerThread::WorkRequest;
@@ -194,7 +194,7 @@ protected:
194 U32 mRequestPriority; // last priority set 194 U32 mRequestPriority; // last priority set
195 195
196private: 196private:
197 LLMutex mMutex; 197 LLMutexRootPool mMutex; // Use LLMutexRootPool since this object is created and destructed by multiple threads.
198 LLAtomicU32 mWorkFlags; 198 LLAtomicU32 mWorkFlags;
199}; 199};
200 200
diff --git a/linden/indra/llcommon/metaclass.h b/linden/indra/llcommon/metaclass.h
index cc10f16..f38bcd2 100644
--- a/linden/indra/llcommon/metaclass.h
+++ b/linden/indra/llcommon/metaclass.h
@@ -43,7 +43,7 @@
43class LLReflective; 43class LLReflective;
44class LLMetaProperty; 44class LLMetaProperty;
45class LLMetaMethod; 45class LLMetaMethod;
46class LLMetaClass 46class LL_COMMON_API LLMetaClass
47{ 47{
48public: 48public:
49 49
diff --git a/linden/indra/llcommon/metaproperty.h b/linden/indra/llcommon/metaproperty.h
index e5ac359..6c016c5 100644
--- a/linden/indra/llcommon/metaproperty.h
+++ b/linden/indra/llcommon/metaproperty.h
@@ -41,7 +41,7 @@
41 41
42class LLMetaClass; 42class LLMetaClass;
43class LLReflective; 43class LLReflective;
44class LLMetaProperty 44class LL_COMMON_API LLMetaProperty
45{ 45{
46public: 46public:
47 LLMetaProperty(const std::string& name, const LLMetaClass& object_class); 47 LLMetaProperty(const std::string& name, const LLMetaClass& object_class);
diff --git a/linden/indra/llcommon/reflective.h b/linden/indra/llcommon/reflective.h
index e2c18eb..a135376 100644
--- a/linden/indra/llcommon/reflective.h
+++ b/linden/indra/llcommon/reflective.h
@@ -36,7 +36,7 @@
36#define LL_REFLECTIVE_H 36#define LL_REFLECTIVE_H
37 37
38class LLMetaClass; 38class LLMetaClass;
39class LLReflective 39class LL_COMMON_API LLReflective
40{ 40{
41public: 41public:
42 LLReflective(); 42 LLReflective();
diff --git a/linden/indra/llcommon/stdtypes.h b/linden/indra/llcommon/stdtypes.h
index af0b4dd..aed1e46 100644
--- a/linden/indra/llcommon/stdtypes.h
+++ b/linden/indra/llcommon/stdtypes.h
@@ -64,10 +64,17 @@ typedef long long unsigned int U64;
64#endif 64#endif
65#endif 65#endif
66 66
67#ifdef LL_DARWIN
68 #ifndef BOOL
69 #define BOOL S32
70 #endif
71#else
72 typedef S32 BOOL;
73#endif
74
67typedef float F32; 75typedef float F32;
68typedef double F64; 76typedef double F64;
69 77
70typedef S32 BOOL;
71typedef U8 KEY; 78typedef U8 KEY;
72typedef U32 MASK; 79typedef U32 MASK;
73typedef U32 TPACKETID; 80typedef U32 TPACKETID;
diff --git a/linden/indra/llcommon/timing.h b/linden/indra/llcommon/timing.h
index 2b9f60a..cfc637e 100644
--- a/linden/indra/llcommon/timing.h
+++ b/linden/indra/llcommon/timing.h
@@ -44,6 +44,6 @@ const U64 SEC_TO_MICROSEC_U64 = 1000000;
44const U32 SEC_PER_DAY = 86400; 44const U32 SEC_PER_DAY = 86400;
45 45
46// This is just a stub, implementation in lltimer.cpp. This file will be deprecated in the future. 46// This is just a stub, implementation in lltimer.cpp. This file will be deprecated in the future.
47U64 totalTime(); // Returns current system time in microseconds 47LL_COMMON_API U64 totalTime(); // Returns current system time in microseconds
48 48
49#endif 49#endif
diff --git a/linden/indra/llcommon/u64.h b/linden/indra/llcommon/u64.h
index 09a6b3e..eb51131 100644
--- a/linden/indra/llcommon/u64.h
+++ b/linden/indra/llcommon/u64.h
@@ -39,14 +39,14 @@
39 * @param str The string to parse. 39 * @param str The string to parse.
40 * @return Returns the first U64 value found in the string or 0 on failure. 40 * @return Returns the first U64 value found in the string or 0 on failure.
41 */ 41 */
42U64 str_to_U64(const std::string& str); 42LL_COMMON_API U64 str_to_U64(const std::string& str);
43 43
44/** 44/**
45 * @brief Given a U64 value, return a printable representation. 45 * @brief Given a U64 value, return a printable representation.
46 * @param value The U64 to turn into a printable character array. 46 * @param value The U64 to turn into a printable character array.
47 * @return Returns the result string. 47 * @return Returns the result string.
48 */ 48 */
49std::string U64_to_str(U64 value); 49LL_COMMON_API std::string U64_to_str(U64 value);
50 50
51/** 51/**
52 * @brief Given a U64 value, return a printable representation. 52 * @brief Given a U64 value, return a printable representation.
@@ -65,16 +65,16 @@ std::string U64_to_str(U64 value);
65 * @param result_size The size of the buffer allocated. Use U64_BUF. 65 * @param result_size The size of the buffer allocated. Use U64_BUF.
66 * @return Returns the result pointer. 66 * @return Returns the result pointer.
67 */ 67 */
68char* U64_to_str(U64 value, char* result, S32 result_size); 68LL_COMMON_API char* U64_to_str(U64 value, char* result, S32 result_size);
69 69
70/** 70/**
71 * @brief Convert a U64 to the closest F64 value. 71 * @brief Convert a U64 to the closest F64 value.
72 */ 72 */
73F64 U64_to_F64(const U64 value); 73LL_COMMON_API F64 U64_to_F64(const U64 value);
74 74
75/** 75/**
76 * @brief Helper function to wrap strtoull() which is not available on windows. 76 * @brief Helper function to wrap strtoull() which is not available on windows.
77 */ 77 */
78U64 llstrtou64(const char* str, char** end, S32 base); 78LL_COMMON_API U64 llstrtou64(const char* str, char** end, S32 base);
79 79
80#endif 80#endif