Merge branch 'master' of https://github.com/AlericInglewood/SingularityViewer.git into AlericMaster
This commit is contained in:
@@ -4,6 +4,10 @@ along with the issue identifier corresponding to the patches we've
|
||||
received from them. To see more about these contributions, visit the
|
||||
browsable version: http://wiki.secondlife.com/wiki/Source_contributions
|
||||
|
||||
Entries are related to URLs as follows:
|
||||
IMP-xxx: http://redmine.kokuaviewer.org/issues/xxx
|
||||
Everything else ([VWR|SNOW|CT|SVC|WEB]-xxx): https://jira.secondlife.com/browse/KEY-xxx
|
||||
|
||||
Able Whitman
|
||||
VWR-650
|
||||
VWR-1460
|
||||
@@ -58,12 +62,18 @@ Aimee Trescothick
|
||||
Alejandro Rosenthal
|
||||
VWR-1184
|
||||
Aleric Inglewood
|
||||
VWR-10579 (IMP-552)
|
||||
VWR-10759
|
||||
VWR-10837
|
||||
VWR-12984
|
||||
VWR-13040 (IMP-575)
|
||||
VWR-13996
|
||||
VWR-14426
|
||||
VWR-14914
|
||||
VWR-24247
|
||||
VWR-24312
|
||||
VWR-24320
|
||||
VWR-24333
|
||||
SNOW-47
|
||||
SNOW-84
|
||||
SNOW-86
|
||||
@@ -72,18 +82,37 @@ Aleric Inglewood
|
||||
SNOW-129
|
||||
SNOW-196
|
||||
SNOW-203
|
||||
SNOW-240
|
||||
SNOW-408
|
||||
SNOW-415
|
||||
SNOW-415 (IMP-576)
|
||||
SNOW-477 (IMP-577)
|
||||
SNOW-479
|
||||
SNOW-626
|
||||
SNOW-713
|
||||
SNOW-744
|
||||
SNOW-751
|
||||
SNOW-713 (IMP-692)
|
||||
SNOW-744 (IMP-578)
|
||||
SNOW-752
|
||||
SNOW-753
|
||||
SNOW-766 (IMP-553)
|
||||
SNOW-772
|
||||
SNOW-793
|
||||
SNOW-796 (IMP-581)
|
||||
SNOW-800 (IMP-556)
|
||||
SNOW-806
|
||||
IMP-429
|
||||
IMP-561
|
||||
IMP-565
|
||||
IMP-566
|
||||
IMP-567
|
||||
IMP-573
|
||||
IMP-590
|
||||
IMP-660
|
||||
IMP-661
|
||||
IMP-662
|
||||
IMP-663
|
||||
IMP-664
|
||||
IMP-670
|
||||
IMP-701
|
||||
IMP-734
|
||||
Alissa Sabre
|
||||
VWR-81
|
||||
VWR-83
|
||||
@@ -105,7 +134,7 @@ Alissa Sabre
|
||||
VWR-1351
|
||||
VWR-1353
|
||||
VWR-1410
|
||||
VWR-1843
|
||||
VWR-1843
|
||||
VWR-2116
|
||||
VWR-2826
|
||||
VWR-3290
|
||||
@@ -113,17 +142,17 @@ Alissa Sabre
|
||||
VWR-3857
|
||||
VWR-4010
|
||||
VWR-5575
|
||||
VWR-5929
|
||||
VWR-6384
|
||||
VWR-6385
|
||||
VWR-5929
|
||||
VWR-6384
|
||||
VWR-6385
|
||||
VWR-6386
|
||||
VWR-6430
|
||||
VWR-6430
|
||||
VWR-6858
|
||||
VWR-6668
|
||||
VWR-7086
|
||||
VWR-7087
|
||||
VWR-7153
|
||||
VWR-7168
|
||||
VWR-6668
|
||||
VWR-7086
|
||||
VWR-7087
|
||||
VWR-7153
|
||||
VWR-7168
|
||||
VWR-9190
|
||||
VWR-10728
|
||||
VWR-12620
|
||||
@@ -181,6 +210,7 @@ Boroondas Gupte
|
||||
SNOW-201
|
||||
SNOW-396
|
||||
SNOW-589
|
||||
SNOW-623 (IMP-554)
|
||||
SNOW-624
|
||||
VWR-233
|
||||
WEB-262
|
||||
@@ -549,7 +579,7 @@ Pf Shan
|
||||
CT-321
|
||||
princess niven
|
||||
VWR-5733
|
||||
CT-85
|
||||
CT-85
|
||||
CT-320
|
||||
CT-352
|
||||
Renault Clio
|
||||
@@ -590,6 +620,7 @@ Robin Cornelius
|
||||
VWR-11128
|
||||
VWR-12758
|
||||
VWR-12686
|
||||
VWR-12838
|
||||
Ryozu Kojima
|
||||
VWR-53
|
||||
VWR-287
|
||||
@@ -788,4 +819,3 @@ Zi Ree
|
||||
Zipherius Turas
|
||||
VWR-76
|
||||
VWR-77
|
||||
|
||||
|
||||
@@ -208,10 +208,18 @@ if (LINUX)
|
||||
# this stops us requiring a really recent glibc at runtime
|
||||
add_definitions(-fno-stack-protector)
|
||||
endif (NOT STANDALONE)
|
||||
set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS})
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS})
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
add_definitions(-DLINUX64=1 -pipe)
|
||||
set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
|
||||
set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -fomit-frame-pointer -mmmx -msse -mfpmath=sse -msse2 -ffast-math -ftree-vectorize -fweb -fexpensive-optimizations -frename-registers")
|
||||
else (${ARCH} STREQUAL "x86_64")
|
||||
set(CMAKE_CXX_FLAGS_RELEASESSE2 "${CMAKE_CXX_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELEASESSE2 "${CMAKE_C_FLAGS_RELEASESSE2} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS})
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 ${GCC_EXTRA_OPTIMIZATIONS}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -march=pentium4 -mfpmath=sse -msse2 "${GCC_EXTRA_OPTIMIZATIONS})
|
||||
endif (${ARCH} STREQUAL "x86_64")
|
||||
endif (VIEWER)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-fno-inline ${CMAKE_CXX_FLAGS_DEBUG}")
|
||||
@@ -219,6 +227,8 @@ if (LINUX)
|
||||
set(CMAKE_C_FLAGS_RELEASE "-O3 ${CMAKE_C_FLAGS_RELEASE}")
|
||||
set(CMAKE_CXX_FLAGS_RELEASESSE2 "-O3 ${CMAKE_CXX_FLAGS_RELEASESSE2}")
|
||||
set(CMAKE_C_FLAGS_RELEASESSE2 "-O3 ${CMAKE_C_FLAGS_RELEASESSE2}")
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
|
||||
set(CMAKE_C_FLAGS_RELWITHDEBINFO "-O3 ${CMAKE_C_FLAGS_RELWITHDEBINFO}")
|
||||
endif (LINUX)
|
||||
|
||||
|
||||
|
||||
@@ -14,16 +14,18 @@ else (STANDALONE)
|
||||
use_prebuilt_binary(apr_suite)
|
||||
if (WINDOWS)
|
||||
set(APR_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/apr-1.lib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/apr-1.lib
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapr-1.lib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.lib
|
||||
)
|
||||
set(APRICONV_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libapriconv-1.lib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libapriconv-1.lib
|
||||
)
|
||||
# Doesn't need to link with iconv.dll
|
||||
set(APRICONV_LIBRARIES "")
|
||||
set(APRUTIL_LIBRARIES
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/aprutil-1.lib
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/aprutil-1.lib
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libaprutil-1.lib ${APRICONV_LIBRARIES}
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.lib ${APRICONV_LIBRARIES}
|
||||
)
|
||||
elseif (DARWIN)
|
||||
set(APR_LIBRARIES
|
||||
@@ -41,9 +43,8 @@ else (STANDALONE)
|
||||
set(APRICONV_LIBRARIES iconv)
|
||||
endif (WINDOWS)
|
||||
set(APR_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/apr-1)
|
||||
set(APRUTIL_INCLUDE_DIR ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/include/apr-1)
|
||||
|
||||
if (LINUX AND VIEWER)
|
||||
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES} uuid)
|
||||
list(APPEND APRUTIL_LIBRARIES ${DB_LIBRARIES})
|
||||
endif (LINUX AND VIEWER)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -35,7 +35,6 @@ set(cmake_SOURCE_FILES
|
||||
FindNDOF.cmake
|
||||
FindOpenJPEG.cmake
|
||||
FindXmlRpcEpi.cmake
|
||||
FindMyZLIB.cmake
|
||||
FMOD.cmake
|
||||
FreeType.cmake
|
||||
GStreamer010Plugin.cmake
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
# - Find zlib
|
||||
# Find the ZLIB includes and library
|
||||
# This module defines
|
||||
# ZLIB_INCLUDE_DIRS, where to find zlib.h, etc.
|
||||
# ZLIB_LIBRARIES, the libraries needed to use zlib.
|
||||
# ZLIB_FOUND, If false, do not try to use zlib.
|
||||
#
|
||||
# This FindZLIB is about 43 times as fast the one provided with cmake (2.8.x),
|
||||
# because it doesn't look up the version of zlib, resulting in a dramatic
|
||||
# speed up for configure (from 4 minutes 22 seconds to 6 seconds).
|
||||
#
|
||||
# Note: Since this file is only used for standalone, the windows
|
||||
# specific parts were left out.
|
||||
|
||||
FIND_PATH(ZLIB_INCLUDE_DIR zlib.h
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
)
|
||||
|
||||
FIND_LIBRARY(ZLIB_LIBRARY z)
|
||||
|
||||
if (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
|
||||
SET(ZLIB_INCLUDE_DIRS ${ZLIB_INCLUDE_DIR})
|
||||
SET(ZLIB_LIBRARIES ${ZLIB_LIBRARY})
|
||||
SET(ZLIB_FOUND "YES")
|
||||
else (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
|
||||
SET(ZLIB_FOUND "NO")
|
||||
endif (ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
|
||||
|
||||
if (ZLIB_FOUND)
|
||||
if (NOT ZLIB_FIND_QUIETLY)
|
||||
message(STATUS "Found ZLIB: ${ZLIB_LIBRARIES}")
|
||||
SET(ZLIB_FIND_QUIETLY TRUE)
|
||||
endif (NOT ZLIB_FIND_QUIETLY)
|
||||
else (ZLIB_FOUND)
|
||||
if (ZLIB_FIND_REQUIRED)
|
||||
message(FATAL_ERROR "Could not find ZLIB library")
|
||||
endif (ZLIB_FIND_REQUIRED)
|
||||
endif (ZLIB_FOUND)
|
||||
|
||||
mark_as_advanced(
|
||||
ZLIB_LIBRARY
|
||||
ZLIB_INCLUDE_DIR
|
||||
)
|
||||
|
||||
@@ -25,9 +25,11 @@ else (STANDALONE)
|
||||
endif (LINUX)
|
||||
endif (STANDALONE)
|
||||
|
||||
#if (GOOGLE_PERFTOOLS_FOUND)
|
||||
# set(USE_GOOGLE_PERFTOOLS ON CACHE BOOL "Build with Google PerfTools support.")
|
||||
#endif (GOOGLE_PERFTOOLS_FOUND)
|
||||
if (GOOGLE_PERFTOOLS_FOUND)
|
||||
set(USE_GOOGLE_PERFTOOLS ON CACHE BOOL "Build with Google PerfTools support.")
|
||||
else (GOOGLE_PERFTOOLS_FOUND)
|
||||
set(USE_GOOGLE_PERFTOOLS OFF)
|
||||
endif (GOOGLE_PERFTOOLS_FOUND)
|
||||
|
||||
# XXX Disable temporarily, until we have compilation issues on 64-bit
|
||||
# Etch sorted.
|
||||
@@ -41,7 +43,7 @@ else (USE_GOOGLE_PERFTOOLS)
|
||||
set(TCMALLOC_FLAG -ULL_USE_TCMALLOC)
|
||||
endif (USE_GOOGLE_PERFTOOLS)
|
||||
|
||||
if (NOT(DISABLE_TCMALLOC OR USE_GOOGLE_PERFTOOLS))
|
||||
if (NOT(DISABLE_TCMALLOC OR NOT USE_GOOGLE_PERFTOOLS))
|
||||
message(STATUS "Building with Google TCMalloc")
|
||||
set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1_)
|
||||
include_directories(${GOOGLE_PERFTOOLS_INCLUDE_DIR})
|
||||
|
||||
@@ -7,7 +7,6 @@ include(ZLIB)
|
||||
|
||||
set(LLCOMMON_INCLUDE_DIRS
|
||||
${LIBS_OPEN_DIR}/llcommon
|
||||
${APRUTIL_INCLUDE_DIR}
|
||||
${APR_INCLUDE_DIR}
|
||||
${Boost_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
@@ -1,11 +1,44 @@
|
||||
# -*- cmake -*-
|
||||
|
||||
include(Python)
|
||||
include(FindSCP)
|
||||
|
||||
macro (use_prebuilt_binary _binary)
|
||||
if(NOT STANDALONE)
|
||||
get_property(PREBUILT_PACKAGES TARGET prepare PROPERTY PREBUILT)
|
||||
list(FIND PREBUILT_PACKAGES ${_binary} _index)
|
||||
if(_index LESS 0)
|
||||
set_property(TARGET prepare APPEND PROPERTY PREBUILT ${_binary})
|
||||
endif(_index LESS 0)
|
||||
endif(NOT STANDALONE)
|
||||
if (NOT STANDALONE)
|
||||
if(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
|
||||
if(INSTALL_PROPRIETARY)
|
||||
include(FindSCP)
|
||||
if(DEBUG_PREBUILT)
|
||||
message("cd ${SCRIPTS_DIR} && ${PYTHON_EXECUTABLE} install.py --install-dir=${CMAKE_SOURCE_DIR}/.. --scp=${SCP_EXECUTABLE} ${_binary}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE}
|
||||
install.py
|
||||
--install-dir=${CMAKE_SOURCE_DIR}/..
|
||||
--scp=${SCP_EXECUTABLE}
|
||||
${_binary}
|
||||
WORKING_DIRECTORY ${SCRIPTS_DIR}
|
||||
RESULT_VARIABLE ${_binary}_installed
|
||||
)
|
||||
else(INSTALL_PROPRIETARY)
|
||||
if(DEBUG_PREBUILT)
|
||||
message("cd ${SCRIPTS_DIR} && ${PYTHON_EXECUTABLE} install.py --install-dir=${CMAKE_SOURCE_DIR}/.. ${_binary}")
|
||||
endif(DEBUG_PREBUILT)
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE}
|
||||
install.py
|
||||
--install-dir=${CMAKE_SOURCE_DIR}/..
|
||||
${_binary}
|
||||
WORKING_DIRECTORY ${SCRIPTS_DIR}
|
||||
RESULT_VARIABLE ${_binary}_installed
|
||||
)
|
||||
endif(INSTALL_PROPRIETARY)
|
||||
file(WRITE ${CMAKE_BINARY_DIR}/temp/${_binary}_installed "${${_binary}_installed}")
|
||||
else(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
|
||||
set(${_binary}_installed 0)
|
||||
endif(${CMAKE_BINARY_DIR}/temp/sentinel_installed IS_NEWER_THAN ${CMAKE_BINARY_DIR}/temp/${_binary}_installed)
|
||||
if(NOT ${_binary}_installed EQUAL 0)
|
||||
message(FATAL_ERROR
|
||||
"Failed to download or unpack prebuilt '${_binary}'."
|
||||
" Process returned ${${_binary}_installed}.")
|
||||
endif (NOT ${_binary}_installed EQUAL 0)
|
||||
endif (NOT STANDALONE)
|
||||
endmacro (use_prebuilt_binary _binary)
|
||||
|
||||
@@ -42,6 +42,7 @@ else (STANDALONE)
|
||||
gdk_pixbuf-2.0
|
||||
Xinerama
|
||||
glib-2.0
|
||||
gio-2.0
|
||||
gmodule-2.0
|
||||
gobject-2.0
|
||||
gthread-2.0
|
||||
|
||||
@@ -2,10 +2,25 @@
|
||||
include(Prebuilt)
|
||||
|
||||
if (NOT STANDALONE)
|
||||
use_prebuilt_binary(libuuid)
|
||||
use_prebuilt_binary(vivox)
|
||||
if (LINUX)
|
||||
#use_prebuilt_binary(libuuid)
|
||||
if(LINUX)
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
use_prebuilt_binary(32bitcompatibilitylibs)
|
||||
endif (${ARCH} STREQUAL "x86_64")
|
||||
use_prebuilt_binary(fontconfig)
|
||||
endif (LINUX)
|
||||
endif(LINUX)
|
||||
else (NOT STANDALONE)
|
||||
# Download there even when using standalone.
|
||||
set(STANDALONE OFF)
|
||||
use_prebuilt_binary(vivox)
|
||||
if(LINUX AND ${ARCH} STREQUAL "x86_64")
|
||||
use_prebuilt_binary(32bitcompatibilitylibs)
|
||||
endif(LINUX AND ${ARCH} STREQUAL "x86_64")
|
||||
set(STANDALONE ON)
|
||||
endif(NOT STANDALONE)
|
||||
|
||||
if (WINDOWS)
|
||||
use_prebuilt_binary(dbghelp)
|
||||
endif (WINDOWS)
|
||||
|
||||
|
||||
@@ -3,7 +3,29 @@ include(Linking)
|
||||
include(Prebuilt)
|
||||
|
||||
if (STANDALONE)
|
||||
find_package(LLQtWebkit REQUIRED)
|
||||
# The minimal version, 4.4.3, is rather arbitrary: it's the version in Debian/Lenny.
|
||||
find_package(Qt4 4.4.3 COMPONENTS QtCore QtGui QtNetwork QtOpenGL QtWebKit REQUIRED)
|
||||
include(${QT_USE_FILE})
|
||||
set(QTDIR $ENV{QTDIR})
|
||||
if (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
|
||||
message(FATAL_ERROR "\"${QT_BINARY_DIR}\" is unequal \"${QTDIR}/bin\"; "
|
||||
"Qt is found by looking for qmake in your PATH. "
|
||||
"Please set your PATH such that 'qmake' is found in \$QTDIR/bin, "
|
||||
"or unset QTDIR if the found Qt is correct.")
|
||||
endif (QTDIR AND NOT "${QT_BINARY_DIR}" STREQUAL "${QTDIR}/bin")
|
||||
find_package(LLQtWebkit REQUIRED QUIET)
|
||||
# Add the plugins.
|
||||
set(QT_PLUGIN_LIBRARIES)
|
||||
foreach(qlibname qgif qjpeg)
|
||||
find_library(QT_PLUGIN_${qlibname} ${qlibname} PATHS ${QT_PLUGINS_DIR}/imageformats NO_DEFAULT_PATH)
|
||||
if (QT_PLUGIN_${qlibname})
|
||||
list(APPEND QT_PLUGIN_LIBRARIES ${QT_PLUGIN_${qlibname}})
|
||||
else (QT_PLUGIN_${qtlibname})
|
||||
message(FATAL_ERROR "Could not find the Qt plugin ${qlibname} in \"${QT_PLUGINS_DIR}/imageformats\"!")
|
||||
endif (QT_PLUGIN_${qlibname})
|
||||
endforeach(qlibname)
|
||||
# qjpeg depends on libjpeg
|
||||
list(APPEND QT_PLUGIN_LIBRARIES jpeg)
|
||||
set(WEBKITLIBPLUGIN OFF CACHE BOOL
|
||||
"WEBKITLIBPLUGIN support for the llplugin/llmedia test apps.")
|
||||
else (STANDALONE)
|
||||
@@ -32,25 +54,26 @@ if (WINDOWS)
|
||||
elseif (DARWIN)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES
|
||||
optimized ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
|
||||
debug ${ARCH_PREBUILT_DIRS_RELEASE}/libllqtwebkit.dylib
|
||||
debug ${ARCH_PREBUILT_DIRS_DEBUG}/libllqtwebkit.dylib
|
||||
)
|
||||
elseif (LINUX)
|
||||
if (STANDALONE)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY})
|
||||
else (STANDALONE)
|
||||
if (STANDALONE)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES ${LLQTWEBKIT_LIBRARY} ${QT_LIBRARIES} ${QT_PLUGIN_LIBRARIES})
|
||||
else (STANDALONE)
|
||||
set(WEBKIT_PLUGIN_LIBRARIES
|
||||
llqtwebkit
|
||||
qgif
|
||||
qjpeg
|
||||
QtWebKit
|
||||
QtOpenGL
|
||||
QtNetwork
|
||||
QtGui
|
||||
QtCore
|
||||
fontconfig
|
||||
X11
|
||||
Xrender
|
||||
GL
|
||||
)
|
||||
endif (STANDALONE)
|
||||
llqtwebkit
|
||||
qgif
|
||||
qjpeg
|
||||
QtWebKit
|
||||
QtOpenGL
|
||||
QtNetwork
|
||||
QtGui
|
||||
QtCore
|
||||
jpeg
|
||||
fontconfig
|
||||
X11
|
||||
Xrender
|
||||
GL
|
||||
)
|
||||
endif (STANDALONE)
|
||||
endif (WINDOWS)
|
||||
|
||||
@@ -6,7 +6,7 @@ set(ZLIB_FIND_REQUIRED ON)
|
||||
include(Prebuilt)
|
||||
|
||||
if (STANDALONE)
|
||||
include(FindMyZLIB)
|
||||
include(FindZLIB)
|
||||
else (STANDALONE)
|
||||
use_prebuilt_binary(zlib)
|
||||
if (WINDOWS)
|
||||
|
||||
@@ -119,6 +119,7 @@ ARGUMENTS=[
|
||||
Example use: %(name)s --arch=i686
|
||||
On Linux this would try to use Linux_i686Manifest.""",
|
||||
default=""),
|
||||
dict(name='artwork', description='Artwork directory.', default=DEFAULT_SRCTREE),
|
||||
dict(name='build', description='Build directory.', default=DEFAULT_SRCTREE),
|
||||
dict(name='buildtype', description="""The build type used. ('Debug', 'Release', 'ReleaseSSE2' or 'RelWithDebInfo')
|
||||
Default is Release """,
|
||||
@@ -126,6 +127,9 @@ ARGUMENTS=[
|
||||
dict(name='branding_id', description="""Identifier for the branding set to
|
||||
use. Currently, 'secondlife' or 'snowglobe')""",
|
||||
default='secondlife'),
|
||||
dict(name='channel',
|
||||
description="""The channel to use for updates, packaging, settings name, etc.""",
|
||||
default=get_channel),
|
||||
dict(name='configuration',
|
||||
description="""The build configuration used. Only used on OS X for
|
||||
now, but it could be used for other platforms as well.""",
|
||||
@@ -136,16 +140,13 @@ ARGUMENTS=[
|
||||
though it's not strictly a grid, 'firstlook' is also an acceptable
|
||||
value for this parameter.""",
|
||||
default=""),
|
||||
dict(name='channel',
|
||||
description="""The channel to use for updates, packaging, settings name, etc.""",
|
||||
default=get_channel),
|
||||
dict(name='login_channel',
|
||||
description="""The channel to use for login handshake/updates only.""",
|
||||
default=None),
|
||||
dict(name='installer_name',
|
||||
description=""" The name of the file that the installer should be
|
||||
packaged up into. Only used on Linux at the moment.""",
|
||||
default=None),
|
||||
dict(name='login_channel',
|
||||
description="""The channel to use for login handshake/updates only.""",
|
||||
default=None),
|
||||
dict(name='login_url',
|
||||
description="""The url that the login screen displays in the client.""",
|
||||
default=None),
|
||||
@@ -156,7 +157,9 @@ ARGUMENTS=[
|
||||
dict(name='source',
|
||||
description='Source directory.',
|
||||
default=DEFAULT_SRCTREE),
|
||||
dict(name='artwork', description='Artwork directory.', default=DEFAULT_SRCTREE),
|
||||
dict(name='standalone',
|
||||
description='Set to ON if this is a standalone build.',
|
||||
default="OFF"),
|
||||
dict(name='touch',
|
||||
description="""File to touch when action is finished. Touch file will
|
||||
contain the name of the final package in a form suitable
|
||||
|
||||
@@ -13,6 +13,7 @@ include_directories(
|
||||
)
|
||||
|
||||
set(llcommon_SOURCE_FILES
|
||||
aiaprpool.cpp
|
||||
imageids.cpp
|
||||
indra_constants.cpp
|
||||
llapp.cpp
|
||||
@@ -78,6 +79,8 @@ set(llcommon_SOURCE_FILES
|
||||
set(llcommon_HEADER_FILES
|
||||
CMakeLists.txt
|
||||
|
||||
aiaprpool.h
|
||||
aithreadsafe.h
|
||||
bitpack.h
|
||||
ctype_workaround.h
|
||||
doublelinkedlist.h
|
||||
@@ -155,6 +158,7 @@ set(llcommon_HEADER_FILES
|
||||
llqueuedthread.h
|
||||
llrand.h
|
||||
llrun.h
|
||||
llscopedvolatileaprpool.h
|
||||
llsd.h
|
||||
llsdserialize.h
|
||||
llsdserialize_xml.h
|
||||
@@ -201,7 +205,7 @@ set_source_files_properties(${llcommon_HEADER_FILES}
|
||||
|
||||
list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
|
||||
|
||||
add_library (llcommon ${llcommon_SOURCE_FILES})
|
||||
add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
|
||||
add_dependencies(llcommon prepare)
|
||||
target_link_libraries(
|
||||
llcommon
|
||||
|
||||
198
indra/llcommon/aiaprpool.cpp
Normal file
198
indra/llcommon/aiaprpool.cpp
Normal file
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* @file aiaprpool.cpp
|
||||
*
|
||||
* Copyright (c) 2010, Aleric Inglewood.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 04/04/2010
|
||||
* - Initial version, written by Aleric Inglewood @ SL
|
||||
*
|
||||
* 10/11/2010
|
||||
* - Changed filename, class names and license to a more
|
||||
* company-neutral format.
|
||||
* - Added APR_HAS_THREADS #if's to allow creation and destruction
|
||||
* of subpools by threads other than the parent pool owner.
|
||||
*/
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llerror.h"
|
||||
#include "aiaprpool.h"
|
||||
#include "llthread.h"
|
||||
|
||||
// Create a subpool from parent.
|
||||
void AIAPRPool::create(AIAPRPool& parent)
|
||||
{
|
||||
llassert(!mPool); // Must be non-initialized.
|
||||
mParent = &parent;
|
||||
if (!mParent) // Using the default parameter?
|
||||
{
|
||||
// By default use the root pool of the current thread.
|
||||
mParent = &AIThreadLocalData::tldata().mRootPool;
|
||||
}
|
||||
llassert(mParent->mPool); // Parent must be initialized.
|
||||
#if APR_HAS_THREADS
|
||||
// As per the documentation of APR (ie http://apr.apache.org/docs/apr/1.4/apr__pools_8h.html):
|
||||
//
|
||||
// Note that most operations on pools are not thread-safe: a single pool should only be
|
||||
// accessed by a single thread at any given time. The one exception to this rule is creating
|
||||
// a subpool of a given pool: one or more threads can safely create subpools at the same
|
||||
// time that another thread accesses the parent pool.
|
||||
//
|
||||
// In other words, it's safe for any thread to create a (sub)pool, independent of who
|
||||
// owns the parent pool.
|
||||
mOwner = apr_os_thread_current();
|
||||
#else
|
||||
mOwner = mParent->mOwner;
|
||||
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
|
||||
#endif
|
||||
apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, mParent->mPool);
|
||||
llassert_always(apr_pool_create_status == APR_SUCCESS);
|
||||
llassert(mPool); // Initialized.
|
||||
apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
|
||||
}
|
||||
|
||||
// Destroy the (sub)pool, if any.
|
||||
void AIAPRPool::destroy(void)
|
||||
{
|
||||
// Only do anything if we are not already (being) destroyed.
|
||||
if (mPool)
|
||||
{
|
||||
#if !APR_HAS_THREADS
|
||||
// If we are a root pool, then every thread may destruct us: in that case
|
||||
// we have to assume that no other thread will use this pool concurrently,
|
||||
// of course. Otherwise, if we are a subpool, only the thread that owns
|
||||
// the parent may destruct us, since that is the pool that is still alive,
|
||||
// possibly being used by others and being altered here.
|
||||
llassert(!mParent || apr_os_thread_equal(mParent->mOwner, apr_os_thread_current()));
|
||||
#endif
|
||||
apr_pool_t* pool = mPool;
|
||||
mPool = NULL; // Mark that we are BEING destructed.
|
||||
apr_pool_cleanup_kill(pool, this, &s_plain_cleanup);
|
||||
apr_pool_destroy(pool);
|
||||
}
|
||||
}
|
||||
|
||||
bool AIAPRPool::parent_is_being_destructed(void)
|
||||
{
|
||||
return mParent && (!mParent->mPool || mParent->parent_is_being_destructed());
|
||||
}
|
||||
|
||||
AIAPRInitialization::AIAPRInitialization(void)
|
||||
{
|
||||
static bool apr_initialized = false;
|
||||
|
||||
if (!apr_initialized)
|
||||
{
|
||||
apr_initialize();
|
||||
}
|
||||
|
||||
apr_initialized = true;
|
||||
}
|
||||
|
||||
bool AIAPRRootPool::sCountInitialized = false;
|
||||
apr_uint32_t volatile AIAPRRootPool::sCount;
|
||||
|
||||
extern apr_thread_mutex_t* gLogMutexp;
|
||||
extern apr_thread_mutex_t* gCallStacksLogMutexp;
|
||||
|
||||
AIAPRRootPool::AIAPRRootPool(void) : AIAPRInitialization(), AIAPRPool(0)
|
||||
{
|
||||
// sCountInitialized don't need locking because when we get here there is still only a single thread.
|
||||
if (!sCountInitialized)
|
||||
{
|
||||
// Initialize the logging mutex
|
||||
apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
|
||||
apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, mPool);
|
||||
|
||||
apr_status_t status = apr_atomic_init(mPool);
|
||||
llassert_always(status == APR_SUCCESS);
|
||||
apr_atomic_set32(&sCount, 1); // Set to 1 to account for the global root pool.
|
||||
sCountInitialized = true;
|
||||
|
||||
// Initialize thread-local APR pool support.
|
||||
// Because this recursively calls AIAPRRootPool::AIAPRRootPool(void)
|
||||
// it must be done last, so that sCount is already initialized.
|
||||
AIThreadLocalData::init();
|
||||
}
|
||||
apr_atomic_inc32(&sCount);
|
||||
}
|
||||
|
||||
AIAPRRootPool::~AIAPRRootPool()
|
||||
{
|
||||
if (!apr_atomic_dec32(&sCount))
|
||||
{
|
||||
// The last pool was destructed. Cleanup remainder of APR.
|
||||
LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
|
||||
|
||||
if (gLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gLogMutexp);
|
||||
gLogMutexp = NULL;
|
||||
}
|
||||
if (gCallStacksLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gCallStacksLogMutexp);
|
||||
gCallStacksLogMutexp = NULL;
|
||||
}
|
||||
|
||||
// Must destroy ALL, and therefore this last AIAPRRootPool, before terminating APR.
|
||||
static_cast<AIAPRRootPool*>(this)->destroy();
|
||||
|
||||
apr_terminate();
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
AIAPRRootPool& AIAPRRootPool::get(void)
|
||||
{
|
||||
static AIAPRRootPool global_APRpool(0); // This is what used to be gAPRPoolp.
|
||||
return global_APRpool;
|
||||
}
|
||||
|
||||
void AIVolatileAPRPool::clearVolatileAPRPool()
|
||||
{
|
||||
llassert_always(mNumActiveRef > 0);
|
||||
if (--mNumActiveRef == 0)
|
||||
{
|
||||
if (isOld())
|
||||
{
|
||||
destroy();
|
||||
mNumTotalRef = 0 ;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This does not actually free the memory,
|
||||
// it just allows the pool to re-use this memory for the next allocation.
|
||||
clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Paranoia check if the pool is jammed.
|
||||
llassert(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
|
||||
}
|
||||
238
indra/llcommon/aiaprpool.h
Normal file
238
indra/llcommon/aiaprpool.h
Normal file
@@ -0,0 +1,238 @@
|
||||
/**
|
||||
* @file aiaprpool.h
|
||||
* @brief Implementation of AIAPRPool.
|
||||
*
|
||||
* Copyright (c) 2010, Aleric Inglewood.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 04/04/2010
|
||||
* - Initial version, written by Aleric Inglewood @ SL
|
||||
*
|
||||
* 10/11/2010
|
||||
* - Changed filename, class names and license to a more
|
||||
* company-neutral format.
|
||||
* - Added APR_HAS_THREADS #if's to allow creation and destruction
|
||||
* of subpools by threads other than the parent pool owner.
|
||||
*/
|
||||
|
||||
#ifndef AIAPRPOOL_H
|
||||
#define AIAPRPOOL_H
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#include <ws2tcpip.h> // Needed before including apr_portable.h
|
||||
#endif
|
||||
|
||||
#include "apr_portable.h"
|
||||
#include "apr_pools.h"
|
||||
#include "llerror.h"
|
||||
|
||||
extern void ll_init_apr();
|
||||
|
||||
/**
|
||||
* @brief A wrapper around the APR memory pool API.
|
||||
*
|
||||
* Usage of this class should be restricted to passing it to libapr-1 function calls that need it.
|
||||
*
|
||||
*/
|
||||
class LL_COMMON_API AIAPRPool
|
||||
{
|
||||
protected:
|
||||
apr_pool_t* mPool; //!< Pointer to the underlaying pool. NULL if not initialized.
|
||||
AIAPRPool* mParent; //!< Pointer to the parent pool, if any. Only valid when mPool is non-zero.
|
||||
apr_os_thread_t mOwner; //!< The thread that owns this memory pool. Only valid when mPool is non-zero.
|
||||
|
||||
public:
|
||||
//! Construct an uninitialized (destructed) pool.
|
||||
AIAPRPool(void) : mPool(NULL) { }
|
||||
|
||||
//! Construct a subpool from an existing pool.
|
||||
// This is not a copy-constructor, this class doesn't have one!
|
||||
AIAPRPool(AIAPRPool& parent) : mPool(NULL) { create(parent); }
|
||||
|
||||
//! Destruct the memory pool (free all of it's subpools and allocated memory).
|
||||
~AIAPRPool() { destroy(); }
|
||||
|
||||
protected:
|
||||
// Create a pool that is allocated from the Operating System. Only used by AIAPRRootPool.
|
||||
AIAPRPool(int) : mPool(NULL), mParent(NULL), mOwner(apr_os_thread_current())
|
||||
{
|
||||
apr_status_t const apr_pool_create_status = apr_pool_create(&mPool, NULL);
|
||||
llassert_always(apr_pool_create_status == APR_SUCCESS);
|
||||
llassert(mPool);
|
||||
apr_pool_cleanup_register(mPool, this, &s_plain_cleanup, &apr_pool_cleanup_null);
|
||||
}
|
||||
|
||||
public:
|
||||
//! Create a subpool from parent. May only be called for an uninitialized/destroyed pool.
|
||||
// The default parameter causes the root pool of the current thread to be used.
|
||||
void create(AIAPRPool& parent = *static_cast<AIAPRPool*>(NULL));
|
||||
|
||||
//! Destroy the (sub)pool, if any.
|
||||
void destroy(void);
|
||||
|
||||
// Use some safebool idiom (http://www.artima.com/cppsource/safebool.html) rather than operator bool.
|
||||
typedef apr_pool_t* const AIAPRPool::* const bool_type;
|
||||
//! Return true if the pool is initialized.
|
||||
operator bool_type() const { return mPool ? &AIAPRPool::mPool : 0; }
|
||||
|
||||
// Painful, but we have to either provide access to this, or wrap
|
||||
// every APR function call that needs a apr_pool_t* to be passed.
|
||||
// NEVER destroy a pool that is returned by this function!
|
||||
apr_pool_t* operator()(void) const
|
||||
{
|
||||
llassert(mPool);
|
||||
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
|
||||
return mPool;
|
||||
}
|
||||
|
||||
// Free all memory without destructing the pool.
|
||||
void clear(void)
|
||||
{
|
||||
llassert(mPool);
|
||||
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
|
||||
apr_pool_clear(mPool);
|
||||
}
|
||||
|
||||
// These methods would make this class 'complete' (as wrapper around the libapr
|
||||
// pool functions), but we don't use memory pools in the viewer (only when
|
||||
// we are forced to pass one to a libapr call), so don't define them in order
|
||||
// not to encourage people to use them.
|
||||
#if 0
|
||||
void* palloc(size_t size)
|
||||
{
|
||||
llassert(mPool);
|
||||
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
|
||||
return apr_palloc(mPool, size);
|
||||
}
|
||||
void* pcalloc(size_t size)
|
||||
{
|
||||
llassert(mPool);
|
||||
llassert(apr_os_thread_equal(mOwner, apr_os_thread_current()));
|
||||
return apr_pcalloc(mPool, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool parent_is_being_destructed(void);
|
||||
static apr_status_t s_plain_cleanup(void* userdata) { return static_cast<AIAPRPool*>(userdata)->plain_cleanup(); }
|
||||
|
||||
apr_status_t plain_cleanup(void)
|
||||
{
|
||||
if (mPool && // We are not being destructed,
|
||||
parent_is_being_destructed()) // but our parent is.
|
||||
// This means the pool is being destructed recursively by libapr
|
||||
// because one of it's parents is being destructed.
|
||||
{
|
||||
mPool = NULL; // Stop destroy() from destructing the pool again.
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
class AIAPRInitialization
|
||||
{
|
||||
public:
|
||||
AIAPRInitialization(void);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Root memory pool (allocates memory from the operating system).
|
||||
*
|
||||
* This class should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase
|
||||
* (and LLMutexRootPool when APR_HAS_THREADS isn't defined).
|
||||
*/
|
||||
class LL_COMMON_API AIAPRRootPool : public AIAPRInitialization, public AIAPRPool
|
||||
{
|
||||
private:
|
||||
friend class AIThreadLocalData;
|
||||
friend class AIThreadSafeSimpleDCRootPool_pbase;
|
||||
#if !APR_HAS_THREADS
|
||||
friend class LLMutexRootPool;
|
||||
#endif
|
||||
//! Construct a root memory pool.
|
||||
// Should only be used by AIThreadLocalData and AIThreadSafeSimpleDCRootPool_pbase.
|
||||
AIAPRRootPool(void);
|
||||
~AIAPRRootPool();
|
||||
|
||||
private:
|
||||
// Keep track of how many root pools exist and when the last one is destructed.
|
||||
static bool sCountInitialized;
|
||||
static apr_uint32_t volatile sCount;
|
||||
|
||||
public:
|
||||
// Return a global root pool that is independent of AIThreadLocalData.
|
||||
// Normally you should not use this. Only use for early initialization
|
||||
// (before main) and deinitialization (after main).
|
||||
static AIAPRRootPool& get(void);
|
||||
|
||||
#if APR_POOL_DEBUG
|
||||
void grab_ownership(void)
|
||||
{
|
||||
// You need a patched libapr to use this.
|
||||
// See http://web.archiveorange.com/archive/v/5XO9y2zoxUOMt6Gmi1OI
|
||||
apr_pool_owner_set(mPool);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Used for constructing the Special Global Root Pool (returned by AIAPRRootPool::get).
|
||||
// It is the same as the default constructor but omits to increment sCount. As a result,
|
||||
// we must be sure that at least one other AIAPRRootPool is created before termination
|
||||
// of the application (which is the case: we create one AIAPRRootPool per thread).
|
||||
AIAPRRootPool(int) : AIAPRInitialization(), AIAPRPool(0) { }
|
||||
};
|
||||
|
||||
//! Volatile memory pool
|
||||
//
|
||||
// 'Volatile' APR memory pool which normally only clears memory,
|
||||
// and does not destroy the pool (the same pool is reused) for
|
||||
// greater efficiency. However, as a safe guard the apr pool
|
||||
// is destructed every FULL_VOLATILE_APR_POOL uses to allow
|
||||
// the system memory to be allocated more efficiently and not
|
||||
// get scattered through RAM.
|
||||
//
|
||||
class LL_COMMON_API AIVolatileAPRPool : protected AIAPRPool
|
||||
{
|
||||
public:
|
||||
AIVolatileAPRPool(void) : mNumActiveRef(0), mNumTotalRef(0) { }
|
||||
|
||||
apr_pool_t* getVolatileAPRPool(void)
|
||||
{
|
||||
if (!mPool) create();
|
||||
++mNumActiveRef;
|
||||
++mNumTotalRef;
|
||||
return AIAPRPool::operator()();
|
||||
}
|
||||
void clearVolatileAPRPool(void);
|
||||
|
||||
bool isOld(void) const { return mNumTotalRef > FULL_VOLATILE_APR_POOL; }
|
||||
bool isUnused() const { return mNumActiveRef == 0; }
|
||||
|
||||
private:
|
||||
S32 mNumActiveRef; // Number of active uses of the pool.
|
||||
S32 mNumTotalRef; // Number of total uses of the pool since last creation.
|
||||
|
||||
// Maximum number of references to AIVolatileAPRPool until the pool is recreated.
|
||||
static S32 const FULL_VOLATILE_APR_POOL = 1024;
|
||||
};
|
||||
|
||||
#endif // AIAPRPOOL_H
|
||||
482
indra/llcommon/aithreadsafe.h
Normal file
482
indra/llcommon/aithreadsafe.h
Normal file
@@ -0,0 +1,482 @@
|
||||
/**
|
||||
* @file aithreadsafe.h
|
||||
* @brief Implementation of AIThreadSafe, AIReadAccessConst, AIReadAccess and AIWriteAccess.
|
||||
*
|
||||
* Copyright (c) 2010, Aleric Inglewood.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution.
|
||||
*
|
||||
* CHANGELOG
|
||||
* and additional copyright holders.
|
||||
*
|
||||
* 31/03/2010
|
||||
* Initial version, written by Aleric Inglewood @ SL
|
||||
*/
|
||||
|
||||
#ifndef AITHREADSAFE_H
|
||||
#define AITHREADSAFE_H
|
||||
|
||||
#include <new>
|
||||
|
||||
#include "llthread.h"
|
||||
#include "llerror.h"
|
||||
|
||||
template<typename T> struct AIReadAccessConst;
|
||||
template<typename T> struct AIReadAccess;
|
||||
template<typename T> struct AIWriteAccess;
|
||||
template<typename T> struct AIAccess;
|
||||
|
||||
template<typename T>
|
||||
class AIThreadSafeBits
|
||||
{
|
||||
private:
|
||||
// AIThreadSafe is a wrapper around an instance of T.
|
||||
// Because T might not have a default constructor, it is constructed
|
||||
// 'in place', with placement new, in the memory reserved here.
|
||||
//
|
||||
// Make sure that the memory that T will be placed in is properly
|
||||
// aligned by using an array of long's.
|
||||
long mMemory[(sizeof(T) + sizeof(long) - 1) / sizeof(long)];
|
||||
|
||||
public:
|
||||
// The wrapped objects are constructed in-place with placement new *outside*
|
||||
// of this object (by AITHREADSAFE macro(s) or derived classes).
|
||||
// However, we are responsible for the destruction of the wrapped object.
|
||||
~AIThreadSafeBits() { ptr()->~T(); }
|
||||
|
||||
// Only for use by AITHREADSAFE, see below.
|
||||
void* memory() const { return const_cast<long*>(&mMemory[0]); }
|
||||
|
||||
protected:
|
||||
// Accessors.
|
||||
T const* ptr() const { return reinterpret_cast<T const*>(mMemory); }
|
||||
T* ptr() { return reinterpret_cast<T*>(mMemory); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for objects that need to be accessed by more than one thread, allowing concurrent readers.
|
||||
*
|
||||
* Use AITHREADSAFE to define instances of any type, and use AIReadAccessConst,
|
||||
* AIReadAccess and AIWriteAccess to get access to the instance.
|
||||
*
|
||||
* For example,
|
||||
*
|
||||
* <code>
|
||||
* class Foo { public: Foo(int, int); };
|
||||
*
|
||||
* AITHREADSAFE(Foo, foo, (2, 3));
|
||||
*
|
||||
* AIReadAccess<Foo> foo_r(foo);
|
||||
* // Use foo_r-> for read access.
|
||||
*
|
||||
* AIWriteAccess<Foo> foo_w(foo);
|
||||
* // Use foo_w-> for write access.
|
||||
* </code>
|
||||
*
|
||||
* If <code>foo</code> is constant, you have to use <code>AIReadAccessConst<Foo></code>.
|
||||
*
|
||||
* It is possible to pass access objects to a function that
|
||||
* downgrades the access, for example:
|
||||
*
|
||||
* <code>
|
||||
* void readfunc(AIReadAccess const& access);
|
||||
*
|
||||
* AIWriteAccess<Foo> foo_w(foo);
|
||||
* readfunc(foo_w); // readfunc will perform read access to foo_w.
|
||||
* </code>
|
||||
*
|
||||
* If <code>AIReadAccess</code> is non-const, you can upgrade the access by creating
|
||||
* an <code>AIWriteAccess</code> object from it. For example:
|
||||
*
|
||||
* <code>
|
||||
* AIWriteAccess<Foo> foo_w(foo_r);
|
||||
* </code>
|
||||
*
|
||||
* This API is Robust(tm). If you try anything that could result in problems,
|
||||
* it simply won't compile. The only mistake you can still easily make is
|
||||
* to obtain write access to an object when it is not needed, or to unlock
|
||||
* an object in between accesses while the state of the object should be
|
||||
* preserved. For example:
|
||||
*
|
||||
* <code>
|
||||
* // This resets foo to point to the first file and then returns that.
|
||||
* std::string filename = AIWriteAccess<Foo>(foo)->get_first_filename();
|
||||
*
|
||||
* // WRONG! The state between calling get_first_filename and get_next_filename should be preserved!
|
||||
*
|
||||
* AIWriteAccess<Foo> foo_w(foo); // Wrong. The code below only needs read-access.
|
||||
* while (!filename.empty())
|
||||
* {
|
||||
* something(filename);
|
||||
* filename = foo_w->next_filename();
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* Correct would be
|
||||
*
|
||||
* <code>
|
||||
* AIReadAccess<Foo> foo_r(foo);
|
||||
* std::string filename = AIWriteAccess<Foo>(foo_r)->get_first_filename();
|
||||
* while (!filename.empty())
|
||||
* {
|
||||
* something(filename);
|
||||
* filename = foo_r->next_filename();
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
*/
|
||||
template<typename T>
|
||||
class AIThreadSafe : public AIThreadSafeBits<T>
|
||||
{
|
||||
protected:
|
||||
// Only these may access the object (through ptr()).
|
||||
friend struct AIReadAccessConst<T>;
|
||||
friend struct AIReadAccess<T>;
|
||||
friend struct AIWriteAccess<T>;
|
||||
|
||||
// Locking control.
|
||||
AIRWLock mRWLock;
|
||||
|
||||
// For use by AIThreadSafeDC
|
||||
AIThreadSafe(void) { }
|
||||
AIThreadSafe(AIAPRPool& parent) : mRWLock(parent) { }
|
||||
|
||||
public:
|
||||
// Only for use by AITHREADSAFE, see below.
|
||||
AIThreadSafe(T* object) { llassert(object == AIThreadSafeBits<T>::ptr()); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Instantiate an static, global or local object of a given type wrapped in AIThreadSafe, using an arbitrary constructor.
|
||||
*
|
||||
* For example, instead of doing
|
||||
*
|
||||
* <code>
|
||||
* Foo foo(x, y);
|
||||
* static Bar bar;
|
||||
* </code>
|
||||
*
|
||||
* One can instantiate a thread-safe instance with
|
||||
*
|
||||
* <code>
|
||||
* AITHREADSAFE(Foo, foo, (x, y));
|
||||
* static AITHREADSAFE(Bar, bar, );
|
||||
* </code>
|
||||
*
|
||||
* Note: This macro does not allow to allocate such object on the heap.
|
||||
* If that is needed, have a look at AIThreadSafeDC.
|
||||
*/
|
||||
#define AITHREADSAFE(type, var, paramlist) AIThreadSafe<type> var(new (var.memory()) type paramlist)
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for objects that need to be accessed by more than one thread.
|
||||
*
|
||||
* This class is the same as an AIThreadSafe wrapper, except that it can only
|
||||
* be used for default constructed objects.
|
||||
*
|
||||
* For example, instead of
|
||||
*
|
||||
* <code>
|
||||
* Foo foo;
|
||||
* </code>
|
||||
*
|
||||
* One would use
|
||||
*
|
||||
* <code>
|
||||
* AIThreadSafeDC<Foo> foo;
|
||||
* </code>
|
||||
*
|
||||
* The advantage over AITHREADSAFE is that this object can be allocated with
|
||||
* new on the heap. For example:
|
||||
*
|
||||
* <code>
|
||||
* AIThreadSafeDC<Foo>* ptr = new AIThreadSafeDC<Foo>;
|
||||
* </code>
|
||||
*
|
||||
* which is not possible with AITHREADSAFE.
|
||||
*/
|
||||
template<typename T>
|
||||
class AIThreadSafeDC : public AIThreadSafe<T>
|
||||
{
|
||||
public:
|
||||
// Construct a wrapper around a default constructed object.
|
||||
AIThreadSafeDC(void) { new (AIThreadSafe<T>::ptr()) T; }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read lock object and provide read access.
|
||||
*/
|
||||
template<typename T>
|
||||
struct AIReadAccessConst
|
||||
{
|
||||
//! Internal enum for the lock-type of the AI*Access object.
|
||||
enum state_type
|
||||
{
|
||||
readlocked, //!< A AIReadAccessConst or AIReadAccess.
|
||||
read2writelocked, //!< A AIWriteAccess constructed from a AIReadAccess.
|
||||
writelocked, //!< A AIWriteAccess constructed from a AIThreadSafe.
|
||||
write2writelocked //!< A AIWriteAccess constructed from (the AIReadAccess base class of) a AIWriteAccess.
|
||||
};
|
||||
|
||||
//! Construct a AIReadAccessConst from a constant AIThreadSafe.
|
||||
AIReadAccessConst(AIThreadSafe<T> const& wrapper)
|
||||
: mWrapper(const_cast<AIThreadSafe<T>&>(wrapper)),
|
||||
mState(readlocked)
|
||||
{
|
||||
mWrapper.mRWLock.rdlock();
|
||||
}
|
||||
|
||||
//! Destruct the AI*Access object.
|
||||
// These should never be dynamically allocated, so there is no need to make this virtual.
|
||||
~AIReadAccessConst()
|
||||
{
|
||||
if (mState == readlocked)
|
||||
mWrapper.mRWLock.rdunlock();
|
||||
else if (mState == writelocked)
|
||||
mWrapper.mRWLock.wrunlock();
|
||||
else if (mState == read2writelocked)
|
||||
mWrapper.mRWLock.wr2rdlock();
|
||||
}
|
||||
|
||||
//! Access the underlaying object for read access.
|
||||
T const* operator->() const { return mWrapper.ptr(); }
|
||||
|
||||
//! Access the underlaying object for read access.
|
||||
T const& operator*() const { return *mWrapper.ptr(); }
|
||||
|
||||
protected:
|
||||
//! Constructor used by AIReadAccess.
|
||||
AIReadAccessConst(AIThreadSafe<T>& wrapper, state_type state)
|
||||
: mWrapper(wrapper), mState(state) { }
|
||||
|
||||
AIThreadSafe<T>& mWrapper; //!< Reference to the object that we provide access to.
|
||||
state_type const mState; //!< The lock state that mWrapper is in.
|
||||
|
||||
private:
|
||||
// Disallow copy constructing directly.
|
||||
AIReadAccessConst(AIReadAccessConst const&);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Read lock object and provide read access, with possible promotion to write access.
|
||||
*/
|
||||
template<typename T>
|
||||
struct AIReadAccess : public AIReadAccessConst<T>
|
||||
{
|
||||
typedef typename AIReadAccessConst<T>::state_type state_type;
|
||||
using AIReadAccessConst<T>::readlocked;
|
||||
|
||||
//! Construct a AIReadAccess from a non-constant AIThreadSafe.
|
||||
AIReadAccess(AIThreadSafe<T>& wrapper) : AIReadAccessConst<T>(wrapper, readlocked) { this->mWrapper.mRWLock.rdlock(); }
|
||||
|
||||
protected:
|
||||
//! Constructor used by AIWriteAccess.
|
||||
AIReadAccess(AIThreadSafe<T>& wrapper, state_type state) : AIReadAccessConst<T>(wrapper, state) { }
|
||||
|
||||
friend class AIWriteAccess<T>;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Write lock object and provide read/write access.
|
||||
*/
|
||||
template<typename T>
|
||||
struct AIWriteAccess : public AIReadAccess<T>
|
||||
{
|
||||
using AIReadAccessConst<T>::readlocked;
|
||||
using AIReadAccessConst<T>::read2writelocked;
|
||||
using AIReadAccessConst<T>::writelocked;
|
||||
using AIReadAccessConst<T>::write2writelocked;
|
||||
|
||||
//! Construct a AIWriteAccess from a non-constant AIThreadSafe.
|
||||
AIWriteAccess(AIThreadSafe<T>& wrapper) : AIReadAccess<T>(wrapper, writelocked) { this->mWrapper.mRWLock.wrlock();}
|
||||
|
||||
//! Promote read access to write access.
|
||||
explicit AIWriteAccess(AIReadAccess<T>& access)
|
||||
: AIReadAccess<T>(access.mWrapper, (access.mState == readlocked) ? read2writelocked : write2writelocked)
|
||||
{
|
||||
if (this->mState == read2writelocked)
|
||||
{
|
||||
this->mWrapper.mRWLock.rd2wrlock();
|
||||
}
|
||||
}
|
||||
|
||||
//! Access the underlaying object for (read and) write access.
|
||||
T* operator->() const { return this->mWrapper.ptr(); }
|
||||
|
||||
//! Access the underlaying object for (read and) write access.
|
||||
T& operator*() const { return *this->mWrapper.ptr(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for objects that need to be accessed by more than one thread.
|
||||
*
|
||||
* Use AITHREADSAFESIMPLE to define instances of any type, and use AIAccess
|
||||
* to get access to the instance.
|
||||
*
|
||||
* For example,
|
||||
*
|
||||
* <code>
|
||||
* class Foo { public: Foo(int, int); };
|
||||
*
|
||||
* AITHREADSAFESIMPLE(Foo, foo, (2, 3));
|
||||
*
|
||||
* AIAccess<Foo> foo_w(foo);
|
||||
* // Use foo_w-> for read and write access.
|
||||
*
|
||||
* See also AIThreadSafe
|
||||
*/
|
||||
template<typename T>
|
||||
class AIThreadSafeSimple : public AIThreadSafeBits<T>
|
||||
{
|
||||
protected:
|
||||
// Only this one may access the object (through ptr()).
|
||||
friend struct AIAccess<T>;
|
||||
|
||||
// Locking control.
|
||||
LLMutex mMutex;
|
||||
|
||||
// For use by AIThreadSafeSimpleDC
|
||||
AIThreadSafeSimple(void) { }
|
||||
AIThreadSafeSimple(AIAPRPool& parent) : mMutex(parent) { }
|
||||
|
||||
public:
|
||||
// Only for use by AITHREADSAFESIMPLE, see below.
|
||||
AIThreadSafeSimple(T* object) { llassert(object == AIThreadSafeBits<T>::ptr()); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Instantiate an static, global or local object of a given type wrapped in AIThreadSafeSimple, using an arbitrary constructor.
|
||||
*
|
||||
* For example, instead of doing
|
||||
*
|
||||
* <code>
|
||||
* Foo foo(x, y);
|
||||
* static Bar bar;
|
||||
* </code>
|
||||
*
|
||||
* One can instantiate a thread-safe instance with
|
||||
*
|
||||
* <code>
|
||||
* AITHREADSAFESIMPLE(Foo, foo, (x, y));
|
||||
* static AITHREADSAFESIMPLE(Bar, bar, );
|
||||
* </code>
|
||||
*
|
||||
* Note: This macro does not allow to allocate such object on the heap.
|
||||
* If that is needed, have a look at AIThreadSafeSimpleDC.
|
||||
*/
|
||||
#define AITHREADSAFESIMPLE(type, var, paramlist) AIThreadSafeSimple<type> var(new (var.memory()) type paramlist)
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for objects that need to be accessed by more than one thread.
|
||||
*
|
||||
* This class is the same as an AIThreadSafeSimple wrapper, except that it can only
|
||||
* be used for default constructed objects.
|
||||
*
|
||||
* For example, instead of
|
||||
*
|
||||
* <code>
|
||||
* Foo foo;
|
||||
* </code>
|
||||
*
|
||||
* One would use
|
||||
*
|
||||
* <code>
|
||||
* AIThreadSafeSimpleDC<Foo> foo;
|
||||
* </code>
|
||||
*
|
||||
* The advantage over AITHREADSAFESIMPLE is that this object can be allocated with
|
||||
* new on the heap. For example:
|
||||
*
|
||||
* <code>
|
||||
* AIThreadSafeSimpleDC<Foo>* ptr = new AIThreadSafeSimpleDC<Foo>;
|
||||
* </code>
|
||||
*
|
||||
* which is not possible with AITHREADSAFESIMPLE.
|
||||
*/
|
||||
template<typename T>
|
||||
class AIThreadSafeSimpleDC : public AIThreadSafeSimple<T>
|
||||
{
|
||||
public:
|
||||
// Construct a wrapper around a default constructed object.
|
||||
AIThreadSafeSimpleDC(void) { new (AIThreadSafeSimple<T>::ptr()) T; }
|
||||
|
||||
protected:
|
||||
// For use by AIThreadSafeSimpleDCRootPool
|
||||
AIThreadSafeSimpleDC(AIAPRPool& parent) : AIThreadSafeSimple<T>(parent) { new (AIThreadSafeSimple<T>::ptr()) T; }
|
||||
};
|
||||
|
||||
// Helper class for AIThreadSafeSimpleDCRootPool to assure initialization of
|
||||
// the root pool before constructing AIThreadSafeSimpleDC.
|
||||
class AIThreadSafeSimpleDCRootPool_pbase
|
||||
{
|
||||
protected:
|
||||
AIAPRRootPool mRootPool;
|
||||
|
||||
private:
|
||||
template<typename T> friend class AIThreadSafeSimpleDCRootPool;
|
||||
AIThreadSafeSimpleDCRootPool_pbase(void) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A wrapper class for objects that need to be accessed by more than one thread.
|
||||
*
|
||||
* The same as AIThreadSafeSimpleDC except that this class creates its own AIAPRRootPool
|
||||
* for the internally used mutexes and condition, instead of using the current threads
|
||||
* root pool. The advantage of this is that it can be used for objects that need to
|
||||
* be accessed from the destructors of global objects (after main). The disadvantage
|
||||
* is that it's less efficient to use your own root pool, therefore it's use should be
|
||||
* restricted to those cases where it is absolutely necessary.
|
||||
*/
|
||||
template<typename T>
|
||||
class AIThreadSafeSimpleDCRootPool : private AIThreadSafeSimpleDCRootPool_pbase, public AIThreadSafeSimpleDC<T>
|
||||
{
|
||||
public:
|
||||
// Construct a wrapper around a default constructed object, using memory allocated
|
||||
// from the operating system for the internal APR objects (mutexes and conditional),
|
||||
// as opposed to allocated from the current threads root pool.
|
||||
AIThreadSafeSimpleDCRootPool(void) :
|
||||
AIThreadSafeSimpleDCRootPool_pbase(),
|
||||
AIThreadSafeSimpleDC<T>(mRootPool) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Write lock object and provide read/write access.
|
||||
*/
|
||||
template<typename T>
|
||||
struct AIAccess
|
||||
{
|
||||
//! Construct a AIAccess from a non-constant AIThreadSafeSimple.
|
||||
AIAccess(AIThreadSafeSimple<T>& wrapper) : mWrapper(wrapper) { this->mWrapper.mMutex.lock(); }
|
||||
|
||||
//! Access the underlaying object for (read and) write access.
|
||||
T* operator->() const { return this->mWrapper.ptr(); }
|
||||
|
||||
//! Access the underlaying object for (read and) write access.
|
||||
T& operator*() const { return *this->mWrapper.ptr(); }
|
||||
|
||||
~AIAccess() { this->mWrapper.mMutex.unlock(); }
|
||||
|
||||
protected:
|
||||
AIThreadSafeSimple<T>& mWrapper; //!< Reference to the object that we provide access to.
|
||||
|
||||
private:
|
||||
// Disallow copy constructing directly.
|
||||
AIAccess(AIAccess const&);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -95,7 +95,6 @@ LLAppChildCallback LLApp::sDefaultChildCallback = NULL;
|
||||
LLApp::LLApp() : mThreadErrorp(NULL)
|
||||
{
|
||||
commonCtor();
|
||||
startErrorThread();
|
||||
}
|
||||
|
||||
void LLApp::commonCtor()
|
||||
@@ -123,13 +122,8 @@ void LLApp::commonCtor()
|
||||
mOptions.append(sd);
|
||||
}
|
||||
|
||||
// Make sure we clean up APR when we exit
|
||||
// Don't need to do this if we're cleaning up APR in the destructor
|
||||
//atexit(ll_cleanup_apr);
|
||||
|
||||
// Set the application to this instance.
|
||||
sApplication = this;
|
||||
|
||||
}
|
||||
|
||||
LLApp::LLApp(LLErrorThread *error_thread) :
|
||||
|
||||
@@ -256,9 +256,12 @@ protected:
|
||||
*/
|
||||
void stepFrame();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @ brief This method is called once as soon as logging is initialized.
|
||||
*/
|
||||
void startErrorThread();
|
||||
|
||||
|
||||
private:
|
||||
void setupErrorHandling(); // Do platform-specific error-handling setup (signals, structured exceptions)
|
||||
static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.
|
||||
static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread.
|
||||
|
||||
@@ -34,219 +34,7 @@
|
||||
|
||||
#include "linden_common.h"
|
||||
#include "llapr.h"
|
||||
|
||||
apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool
|
||||
apr_thread_mutex_t *gLogMutexp = NULL;
|
||||
apr_thread_mutex_t *gCallStacksLogMutexp = NULL;
|
||||
|
||||
const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool
|
||||
|
||||
void ll_init_apr()
|
||||
{
|
||||
if (!gAPRPoolp)
|
||||
{
|
||||
// Initialize APR and create the global pool
|
||||
apr_initialize();
|
||||
apr_pool_create(&gAPRPoolp, NULL);
|
||||
|
||||
// Initialize the logging mutex
|
||||
apr_thread_mutex_create(&gLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
apr_thread_mutex_create(&gCallStacksLogMutexp, APR_THREAD_MUTEX_UNNESTED, gAPRPoolp);
|
||||
|
||||
// Initialize thread-local APR pool support.
|
||||
LLVolatileAPRPool::initLocalAPRFilePool();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ll_cleanup_apr()
|
||||
{
|
||||
LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL;
|
||||
|
||||
if (gLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gLogMutexp);
|
||||
gLogMutexp = NULL;
|
||||
}
|
||||
if (gCallStacksLogMutexp)
|
||||
{
|
||||
// Clean up the logging mutex
|
||||
|
||||
// All other threads NEED to be done before we clean up APR, so this is okay.
|
||||
apr_thread_mutex_destroy(gCallStacksLogMutexp);
|
||||
gCallStacksLogMutexp = NULL;
|
||||
}
|
||||
if (gAPRPoolp)
|
||||
{
|
||||
apr_pool_destroy(gAPRPoolp);
|
||||
gAPRPoolp = NULL;
|
||||
}
|
||||
apr_terminate();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//LLAPRPool
|
||||
//
|
||||
LLAPRPool::LLAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
|
||||
: mParent(parent),
|
||||
mReleasePoolFlag(releasePoolFlag),
|
||||
mMaxSize(size),
|
||||
mPool(NULL)
|
||||
{
|
||||
createAPRPool() ;
|
||||
}
|
||||
|
||||
LLAPRPool::~LLAPRPool()
|
||||
{
|
||||
releaseAPRPool() ;
|
||||
}
|
||||
|
||||
void LLAPRPool::createAPRPool()
|
||||
{
|
||||
if(mPool)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
mStatus = apr_pool_create(&mPool, mParent);
|
||||
ll_apr_warn_status(mStatus) ;
|
||||
|
||||
if(mMaxSize > 0) //size is the number of blocks (which is usually 4K), NOT bytes.
|
||||
{
|
||||
apr_allocator_t *allocator = apr_pool_allocator_get(mPool);
|
||||
if (allocator)
|
||||
{
|
||||
apr_allocator_max_free_set(allocator, mMaxSize) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LLAPRPool::releaseAPRPool()
|
||||
{
|
||||
if(!mPool)
|
||||
{
|
||||
return ;
|
||||
}
|
||||
|
||||
if(!mParent || mReleasePoolFlag)
|
||||
{
|
||||
apr_pool_destroy(mPool) ;
|
||||
mPool = NULL ;
|
||||
}
|
||||
}
|
||||
|
||||
apr_pool_t* LLAPRPool::getAPRPool()
|
||||
{
|
||||
if(!mPool)
|
||||
{
|
||||
createAPRPool() ;
|
||||
}
|
||||
|
||||
return mPool ;
|
||||
}
|
||||
LLVolatileAPRPool::LLVolatileAPRPool(apr_pool_t *parent, apr_size_t size, BOOL releasePoolFlag)
|
||||
: LLAPRPool(parent, size, releasePoolFlag)
|
||||
{
|
||||
mNumActiveRef = 0 ;
|
||||
mNumTotalRef = 0 ;
|
||||
}
|
||||
|
||||
apr_pool_t* LLVolatileAPRPool::getVolatileAPRPool()
|
||||
{
|
||||
mNumTotalRef++ ;
|
||||
mNumActiveRef++ ;
|
||||
return getAPRPool() ;
|
||||
}
|
||||
|
||||
void LLVolatileAPRPool::clearVolatileAPRPool()
|
||||
{
|
||||
if(mNumActiveRef > 0)
|
||||
{
|
||||
mNumActiveRef--;
|
||||
if(mNumActiveRef < 1)
|
||||
{
|
||||
if(isFull())
|
||||
{
|
||||
mNumTotalRef = 0 ;
|
||||
|
||||
//destroy the apr_pool.
|
||||
releaseAPRPool() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
//This does not actually free the memory,
|
||||
//it just allows the pool to re-use this memory for the next allocation.
|
||||
apr_pool_clear(mPool) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert_always(mNumActiveRef > 0) ;
|
||||
}
|
||||
|
||||
//paranoia check if the pool is jammed.
|
||||
//will remove the check before going to release.
|
||||
llassert_always(mNumTotalRef < (FULL_VOLATILE_APR_POOL << 2)) ;
|
||||
}
|
||||
|
||||
BOOL LLVolatileAPRPool::isFull()
|
||||
{
|
||||
return mNumTotalRef > FULL_VOLATILE_APR_POOL ;
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
|
||||
static void* gIsMainThread;
|
||||
bool is_main_thread() { return gIsMainThread == LLVolatileAPRPool::getLocalAPRFilePool(); }
|
||||
#endif
|
||||
|
||||
// The thread private handle to access the LocalAPRFilePool.
|
||||
apr_threadkey_t* LLVolatileAPRPool::sLocalAPRFilePoolKey;
|
||||
|
||||
// This should be called exactly once, before the first call to createLocalAPRFilePool.
|
||||
// static
|
||||
void LLVolatileAPRPool::initLocalAPRFilePool()
|
||||
{
|
||||
apr_status_t status = apr_threadkey_private_create(&sLocalAPRFilePoolKey, &destroyLocalAPRFilePool, gAPRPoolp);
|
||||
ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the
|
||||
// total number of keys per process {PTHREAD_KEYS_MAX}
|
||||
// has been exceeded.
|
||||
// Create the thread-local pool for the main thread (this function is called by the main thread).
|
||||
createLocalAPRFilePool();
|
||||
#ifdef SHOW_ASSERT
|
||||
gIsMainThread = getLocalAPRFilePool();
|
||||
#endif
|
||||
}
|
||||
|
||||
// This should be called once for every thread, before it uses getLocalAPRFilePool.
|
||||
// static
|
||||
void LLVolatileAPRPool::createLocalAPRFilePool()
|
||||
{
|
||||
void* thread_local_data = new LLVolatileAPRPool;
|
||||
apr_status_t status = apr_threadkey_private_set(thread_local_data, sLocalAPRFilePoolKey);
|
||||
llassert_always(status == APR_SUCCESS);
|
||||
}
|
||||
|
||||
// This is called once for every thread when the thread is destructed.
|
||||
// static
|
||||
void LLVolatileAPRPool::destroyLocalAPRFilePool(void* thread_local_data)
|
||||
{
|
||||
delete reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
|
||||
}
|
||||
|
||||
// static
|
||||
LLVolatileAPRPool* LLVolatileAPRPool::getLocalAPRFilePool()
|
||||
{
|
||||
void* thread_local_data;
|
||||
apr_status_t status = apr_threadkey_private_get(&thread_local_data, sLocalAPRFilePoolKey);
|
||||
llassert_always(status == APR_SUCCESS);
|
||||
return reinterpret_cast<LLVolatileAPRPool*>(thread_local_data);
|
||||
}
|
||||
#include "llscopedvolatileaprpool.h"
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
//
|
||||
@@ -309,13 +97,15 @@ void ll_apr_assert_status(apr_status_t status)
|
||||
//
|
||||
LLAPRFile::LLAPRFile()
|
||||
: mFile(NULL),
|
||||
mCurrentFilePoolp(NULL)
|
||||
mVolatileFilePoolp(NULL),
|
||||
mRegularFilePoolp(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
LLAPRFile::LLAPRFile(const std::string& filename, apr_int32_t flags, access_t access_type)
|
||||
: mFile(NULL),
|
||||
mCurrentFilePoolp(NULL)
|
||||
mVolatileFilePoolp(NULL),
|
||||
mRegularFilePoolp(NULL)
|
||||
{
|
||||
open(filename, flags, access_type);
|
||||
}
|
||||
@@ -334,10 +124,16 @@ apr_status_t LLAPRFile::close()
|
||||
mFile = NULL ;
|
||||
}
|
||||
|
||||
if(mCurrentFilePoolp)
|
||||
if (mVolatileFilePoolp)
|
||||
{
|
||||
mCurrentFilePoolp->clearVolatileAPRPool() ;
|
||||
mCurrentFilePoolp = NULL ;
|
||||
mVolatileFilePoolp->clearVolatileAPRPool() ;
|
||||
mVolatileFilePoolp = NULL ;
|
||||
}
|
||||
|
||||
if (mRegularFilePoolp)
|
||||
{
|
||||
delete mRegularFilePoolp;
|
||||
mRegularFilePoolp = NULL;
|
||||
}
|
||||
|
||||
return ret ;
|
||||
@@ -346,25 +142,28 @@ apr_status_t LLAPRFile::close()
|
||||
apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, access_t access_type, S32* sizep)
|
||||
{
|
||||
llassert_always(!mFile);
|
||||
llassert_always(!mCurrentFilePoolp);
|
||||
llassert_always(!mVolatileFilePoolp && !mRegularFilePoolp);
|
||||
|
||||
// Access the pool and increment it's reference count.
|
||||
// The reference count of LLVolatileAPRPool objects will be decremented
|
||||
// again in LLAPRFile::close by calling mCurrentFilePoolp->clearVolatileAPRPool().
|
||||
apr_pool_t* pool;
|
||||
if (access_type == local)
|
||||
apr_status_t status;
|
||||
{
|
||||
// Use a "volatile" thread-local pool.
|
||||
mCurrentFilePoolp = LLVolatileAPRPool::getLocalAPRFilePool();
|
||||
pool = mCurrentFilePoolp->getVolatileAPRPool();
|
||||
apr_pool_t* apr_file_open_pool;
|
||||
if (access_type == local)
|
||||
{
|
||||
// Use a "volatile" thread-local pool.
|
||||
mVolatileFilePoolp = &AIThreadLocalData::tldata().mVolatileAPRPool;
|
||||
// Access the pool and increment it's reference count.
|
||||
// The reference count of AIVolatileAPRPool objects will be decremented
|
||||
// again in LLAPRFile::close by calling mVolatileFilePoolp->clearVolatileAPRPool().
|
||||
apr_file_open_pool = mVolatileFilePoolp->getVolatileAPRPool();
|
||||
}
|
||||
else
|
||||
{
|
||||
mRegularFilePoolp = new AIAPRPool(AIThreadLocalData::tldata().mRootPool);
|
||||
apr_file_open_pool = (*mRegularFilePoolp)();
|
||||
}
|
||||
status = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, apr_file_open_pool);
|
||||
}
|
||||
else
|
||||
{
|
||||
llassert(is_main_thread());
|
||||
pool = gAPRPoolp;
|
||||
}
|
||||
apr_status_t s = apr_file_open(&mFile, filename.c_str(), flags, APR_OS_DEFAULT, pool);
|
||||
if (s != APR_SUCCESS || !mFile)
|
||||
if (status != APR_SUCCESS || !mFile)
|
||||
{
|
||||
mFile = NULL ;
|
||||
close() ;
|
||||
@@ -372,7 +171,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc
|
||||
{
|
||||
*sizep = 0;
|
||||
}
|
||||
return s;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (sizep)
|
||||
@@ -389,7 +188,7 @@ apr_status_t LLAPRFile::open(std::string const& filename, apr_int32_t flags, acc
|
||||
*sizep = file_size;
|
||||
}
|
||||
|
||||
return s;
|
||||
return status;
|
||||
}
|
||||
|
||||
// File I/O
|
||||
@@ -449,17 +248,6 @@ S32 LLAPRFile::seek(apr_seek_where_t where, S32 offset)
|
||||
//static components of LLAPRFile
|
||||
//
|
||||
|
||||
// Used in the static functions below.
|
||||
class LLScopedVolatileAPRFilePool {
|
||||
private:
|
||||
LLVolatileAPRPool* mPool;
|
||||
apr_pool_t* apr_pool;
|
||||
public:
|
||||
LLScopedVolatileAPRFilePool() : mPool(LLVolatileAPRPool::getLocalAPRFilePool()), apr_pool(mPool->getVolatileAPRPool()) { }
|
||||
~LLScopedVolatileAPRFilePool() { mPool->clearVolatileAPRPool(); }
|
||||
operator apr_pool_t*() const { return apr_pool; }
|
||||
};
|
||||
|
||||
//static
|
||||
S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
|
||||
{
|
||||
@@ -496,7 +284,7 @@ S32 LLAPRFile::seek(apr_file_t* file_handle, apr_seek_where_t where, S32 offset)
|
||||
S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes)
|
||||
{
|
||||
apr_file_t* file_handle;
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
apr_status_t s = apr_file_open(&file_handle, filename.c_str(), APR_READ|APR_BINARY, APR_OS_DEFAULT, pool);
|
||||
if (s != APR_SUCCESS || !file_handle)
|
||||
{
|
||||
@@ -548,7 +336,7 @@ S32 LLAPRFile::writeEx(const std::string& filename, void *buf, S32 offset, S32 n
|
||||
}
|
||||
|
||||
apr_file_t* file_handle;
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
apr_status_t s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
|
||||
if (s != APR_SUCCESS || !file_handle)
|
||||
{
|
||||
@@ -593,7 +381,7 @@ bool LLAPRFile::remove(const std::string& filename)
|
||||
{
|
||||
apr_status_t s;
|
||||
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
s = apr_file_remove(filename.c_str(), pool);
|
||||
|
||||
if (s != APR_SUCCESS)
|
||||
@@ -613,7 +401,7 @@ bool LLAPRFile::rename(const std::string& filename, const std::string& newname)
|
||||
{
|
||||
apr_status_t s;
|
||||
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
s = apr_file_rename(filename.c_str(), newname.c_str(), pool);
|
||||
|
||||
if (s != APR_SUCCESS)
|
||||
@@ -631,7 +419,7 @@ bool LLAPRFile::isExist(const std::string& filename, apr_int32_t flags)
|
||||
apr_file_t* file_handle;
|
||||
apr_status_t s;
|
||||
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
s = apr_file_open(&file_handle, filename.c_str(), flags, APR_OS_DEFAULT, pool);
|
||||
|
||||
if (s != APR_SUCCESS || !file_handle)
|
||||
@@ -652,7 +440,7 @@ S32 LLAPRFile::size(const std::string& filename)
|
||||
apr_finfo_t info;
|
||||
apr_status_t s;
|
||||
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
s = apr_file_open(&file_handle, filename.c_str(), APR_READ, APR_OS_DEFAULT, pool);
|
||||
|
||||
if (s != APR_SUCCESS || !file_handle)
|
||||
@@ -681,7 +469,7 @@ bool LLAPRFile::makeDir(const std::string& dirname)
|
||||
{
|
||||
apr_status_t s;
|
||||
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
s = apr_dir_make(dirname.c_str(), APR_FPROT_OS_DEFAULT, pool);
|
||||
|
||||
if (s != APR_SUCCESS)
|
||||
@@ -698,7 +486,7 @@ bool LLAPRFile::removeDir(const std::string& dirname)
|
||||
{
|
||||
apr_status_t s;
|
||||
|
||||
LLScopedVolatileAPRFilePool pool;
|
||||
LLScopedVolatileAPRPool pool;
|
||||
s = apr_file_remove(dirname.c_str(), pool);
|
||||
|
||||
if (s != APR_SUCCESS)
|
||||
|
||||
@@ -48,73 +48,8 @@
|
||||
#include "apr_atomic.h"
|
||||
#include "llstring.h"
|
||||
|
||||
extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp;
|
||||
|
||||
/**
|
||||
* @brief initialize the common apr constructs -- apr itself, the
|
||||
* global pool, and a mutex.
|
||||
*/
|
||||
void LL_COMMON_API ll_init_apr();
|
||||
|
||||
/**
|
||||
* @brief Cleanup those common apr constructs.
|
||||
*/
|
||||
void LL_COMMON_API ll_cleanup_apr();
|
||||
|
||||
//
|
||||
//LL apr_pool
|
||||
//manage apr_pool_t, destroy allocated apr_pool in the destruction function.
|
||||
//
|
||||
class LL_COMMON_API LLAPRPool
|
||||
{
|
||||
public:
|
||||
LLAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE) ;
|
||||
~LLAPRPool() ;
|
||||
|
||||
apr_pool_t* getAPRPool() ;
|
||||
apr_status_t getStatus() {return mStatus ; }
|
||||
|
||||
protected:
|
||||
void releaseAPRPool() ;
|
||||
void createAPRPool() ;
|
||||
|
||||
protected:
|
||||
apr_pool_t* mPool ; //pointing to an apr_pool
|
||||
apr_pool_t* mParent ; //parent pool
|
||||
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.
|
||||
apr_status_t mStatus ; //status when creating the pool
|
||||
BOOL mReleasePoolFlag ; //if set, mPool is destroyed when LLAPRPool is deleted. default value is true.
|
||||
};
|
||||
|
||||
//
|
||||
//volatile LL apr_pool
|
||||
//which clears memory automatically.
|
||||
//so it can not hold static data or data after memory is cleared
|
||||
//
|
||||
class LL_COMMON_API LLVolatileAPRPool : protected LLAPRPool
|
||||
{
|
||||
public:
|
||||
LLVolatileAPRPool(apr_pool_t *parent = NULL, apr_size_t size = 0, BOOL releasePoolFlag = TRUE);
|
||||
~LLVolatileAPRPool(){}
|
||||
|
||||
apr_pool_t* getVolatileAPRPool() ;
|
||||
|
||||
void clearVolatileAPRPool() ;
|
||||
|
||||
BOOL isFull() ;
|
||||
BOOL isEmpty() {return !mNumActiveRef ;}
|
||||
|
||||
static void initLocalAPRFilePool();
|
||||
static void createLocalAPRFilePool();
|
||||
static void destroyLocalAPRFilePool(void* thread_local_data);
|
||||
static LLVolatileAPRPool* getLocalAPRFilePool();
|
||||
|
||||
private:
|
||||
S32 mNumActiveRef ; //number of active pointers pointing to the apr_pool.
|
||||
S32 mNumTotalRef ; //number of total pointers pointing to the apr_pool since last creating.
|
||||
|
||||
static apr_threadkey_t* sLocalAPRFilePoolKey;
|
||||
} ;
|
||||
class AIAPRPool;
|
||||
class AIVolatileAPRPool;
|
||||
|
||||
/**
|
||||
* @class LLScopedLock
|
||||
@@ -205,7 +140,8 @@ class LL_COMMON_API LLAPRFile : boost::noncopyable
|
||||
// make this non copyable since a copy closes the file
|
||||
private:
|
||||
apr_file_t* mFile ;
|
||||
LLVolatileAPRPool *mCurrentFilePoolp ; //currently in use apr_pool, could be one of them: sAPRFilePoolp, or a temp pool.
|
||||
AIVolatileAPRPool* mVolatileFilePoolp; // (Thread local) APR pool currently in use.
|
||||
AIAPRPool* mRegularFilePoolp; // ...or a regular pool.
|
||||
|
||||
public:
|
||||
enum access_t {
|
||||
@@ -260,6 +196,4 @@ bool LL_COMMON_API ll_apr_warn_status(apr_status_t status);
|
||||
|
||||
void LL_COMMON_API ll_apr_assert_status(apr_status_t status);
|
||||
|
||||
extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool
|
||||
|
||||
#endif // LL_LLAPR_H
|
||||
|
||||
@@ -34,18 +34,10 @@
|
||||
#include "llcommon.h"
|
||||
#include "llthread.h"
|
||||
|
||||
//static
|
||||
BOOL LLCommon::sAprInitialized = FALSE;
|
||||
|
||||
//static
|
||||
void LLCommon::initClass()
|
||||
{
|
||||
LLMemory::initClass();
|
||||
if (!sAprInitialized)
|
||||
{
|
||||
ll_init_apr();
|
||||
sAprInitialized = TRUE;
|
||||
}
|
||||
LLTimer::initClass();
|
||||
LLThreadSafeRefCount::initThreadSafeRefCount();
|
||||
// LLWorkerThread::initClass();
|
||||
@@ -59,10 +51,5 @@ void LLCommon::cleanupClass()
|
||||
// LLWorkerThread::cleanupClass();
|
||||
LLThreadSafeRefCount::cleanupThreadSafeRefCount();
|
||||
LLTimer::cleanupClass();
|
||||
if (sAprInitialized)
|
||||
{
|
||||
ll_cleanup_apr();
|
||||
sAprInitialized = FALSE;
|
||||
}
|
||||
LLMemory::cleanupClass();
|
||||
}
|
||||
|
||||
@@ -43,8 +43,6 @@ class LL_COMMON_API LLCommon
|
||||
public:
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
private:
|
||||
static BOOL sAprInitialized;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "llsdserialize.h"
|
||||
#include "llstl.h"
|
||||
#include "lltimer.h"
|
||||
#include "aithreadsafe.h"
|
||||
|
||||
extern apr_thread_mutex_t* gCallStacksLogMutexp;
|
||||
|
||||
@@ -357,12 +358,15 @@ namespace
|
||||
void addCallSite(LLError::CallSite&);
|
||||
void invalidateCallSites();
|
||||
|
||||
static Globals& get();
|
||||
static AIThreadSafeSimple<Globals>& get();
|
||||
// return the one instance of the globals
|
||||
|
||||
private:
|
||||
CallSiteVector callSites;
|
||||
|
||||
friend class AIThreadSafeSimpleDC<Globals>; // Calls constructor.
|
||||
friend class AIThreadSafeSimple<Globals>; // Calls destructor.
|
||||
|
||||
Globals()
|
||||
: messageStreamInUse(false)
|
||||
{ }
|
||||
@@ -386,7 +390,7 @@ namespace
|
||||
callSites.clear();
|
||||
}
|
||||
|
||||
Globals& Globals::get()
|
||||
AIThreadSafeSimple<Globals>& Globals::get()
|
||||
{
|
||||
/* This pattern, of returning a reference to a static function
|
||||
variable, is to ensure that this global is constructed before
|
||||
@@ -394,8 +398,8 @@ namespace
|
||||
is.
|
||||
See C++ FAQ Lite, sections 10.12 through 10.14
|
||||
*/
|
||||
static Globals* globals = new Globals;
|
||||
return *globals;
|
||||
static AIThreadSafeSimpleDCRootPool<Globals>* ts_globals_ptr = new AIThreadSafeSimpleDCRootPool<Globals>;
|
||||
return *ts_globals_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,13 +428,16 @@ namespace LLError
|
||||
|
||||
int shouldLogCallCounter;
|
||||
|
||||
static Settings& get();
|
||||
static AIThreadSafeSimple<Settings>& get();
|
||||
|
||||
static void reset();
|
||||
static Settings* saveAndReset();
|
||||
static void restore(Settings*);
|
||||
static AIThreadSafeSimple<Settings>* saveAndReset();
|
||||
static void restore(AIThreadSafeSimple<Settings>*);
|
||||
|
||||
private:
|
||||
friend class AIThreadSafeBits<Settings>; // Calls destructor.
|
||||
friend class AIThreadSafeSimpleDC<Settings>; // Calls constructor.
|
||||
|
||||
Settings()
|
||||
: printLocation(false),
|
||||
defaultLevel(LLError::LEVEL_DEBUG),
|
||||
@@ -446,53 +453,42 @@ namespace LLError
|
||||
for_each(recorders.begin(), recorders.end(),
|
||||
DeletePointer());
|
||||
}
|
||||
|
||||
static Settings*& getPtr();
|
||||
|
||||
static AIThreadSafeSimple<Settings>* sSettings;
|
||||
};
|
||||
|
||||
// Pointer to current AIThreadSafeSimple<Settings> object if any (NULL otherwise).
|
||||
AIThreadSafeSimple<Settings>* Settings::sSettings;
|
||||
|
||||
Settings& Settings::get()
|
||||
AIThreadSafeSimple<Settings>& Settings::get()
|
||||
{
|
||||
Settings* p = getPtr();
|
||||
if (!p)
|
||||
if (!sSettings)
|
||||
{
|
||||
reset();
|
||||
p = getPtr();
|
||||
}
|
||||
return *p;
|
||||
return *sSettings;
|
||||
}
|
||||
|
||||
void Settings::reset()
|
||||
{
|
||||
Globals::get().invalidateCallSites();
|
||||
|
||||
Settings*& p = getPtr();
|
||||
delete p;
|
||||
p = new Settings();
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
delete sSettings;
|
||||
sSettings = new AIThreadSafeSimpleDC<Settings>;
|
||||
}
|
||||
|
||||
Settings* Settings::saveAndReset()
|
||||
AIThreadSafeSimple<Settings>* Settings::saveAndReset()
|
||||
{
|
||||
Globals::get().invalidateCallSites();
|
||||
|
||||
Settings*& p = getPtr();
|
||||
Settings* originalSettings = p;
|
||||
p = new Settings();
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
AIThreadSafeSimple<Settings>* originalSettings = sSettings;
|
||||
sSettings = new AIThreadSafeSimpleDC<Settings>;
|
||||
return originalSettings;
|
||||
}
|
||||
|
||||
void Settings::restore(Settings* originalSettings)
|
||||
void Settings::restore(AIThreadSafeSimple<Settings>* originalSettings)
|
||||
{
|
||||
Globals::get().invalidateCallSites();
|
||||
|
||||
Settings*& p = getPtr();
|
||||
delete p;
|
||||
p = originalSettings;
|
||||
}
|
||||
|
||||
Settings*& Settings::getPtr()
|
||||
{
|
||||
static Settings* currentSettings = NULL;
|
||||
return currentSettings;
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
delete sSettings;
|
||||
sSettings = originalSettings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -596,68 +592,64 @@ namespace LLError
|
||||
commonInit(dir);
|
||||
}
|
||||
|
||||
void setPrintLocation(AIAccess<Settings> const& settings_w, bool print)
|
||||
{
|
||||
settings_w->printLocation = print;
|
||||
}
|
||||
|
||||
void setPrintLocation(bool print)
|
||||
{
|
||||
Settings& s = Settings::get();
|
||||
s.printLocation = print;
|
||||
setPrintLocation(AIAccess<Settings>(Settings::get()), print);
|
||||
}
|
||||
|
||||
void setFatalFunction(const FatalFunction& f)
|
||||
{
|
||||
Settings& s = Settings::get();
|
||||
s.crashFunction = f;
|
||||
AIAccess<Settings>(Settings::get())->crashFunction = f;
|
||||
}
|
||||
|
||||
FatalFunction getFatalFunction()
|
||||
{
|
||||
Settings& s = Settings::get();
|
||||
return s.crashFunction;
|
||||
return AIAccess<Settings>(Settings::get())->crashFunction;
|
||||
}
|
||||
|
||||
void setTimeFunction(TimeFunction f)
|
||||
{
|
||||
Settings& s = Settings::get();
|
||||
s.timeFunction = f;
|
||||
AIAccess<Settings>(Settings::get())->timeFunction = f;
|
||||
}
|
||||
|
||||
void setDefaultLevel(AIAccess<Settings> const& settings_w, ELevel level)
|
||||
{
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
settings_w->defaultLevel = level;
|
||||
}
|
||||
|
||||
void setDefaultLevel(ELevel level)
|
||||
{
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
g.invalidateCallSites();
|
||||
s.defaultLevel = level;
|
||||
setDefaultLevel(AIAccess<Settings>(Settings::get()), level);
|
||||
}
|
||||
|
||||
void setFunctionLevel(const std::string& function_name, ELevel level)
|
||||
{
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
g.invalidateCallSites();
|
||||
s.functionLevelMap[function_name] = level;
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
AIAccess<Settings>(Settings::get())->functionLevelMap[function_name] = level;
|
||||
}
|
||||
|
||||
void setClassLevel(const std::string& class_name, ELevel level)
|
||||
{
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
g.invalidateCallSites();
|
||||
s.classLevelMap[class_name] = level;
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
AIAccess<Settings>(Settings::get())->classLevelMap[class_name] = level;
|
||||
}
|
||||
|
||||
void setFileLevel(const std::string& file_name, ELevel level)
|
||||
{
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
g.invalidateCallSites();
|
||||
s.fileLevelMap[file_name] = level;
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
AIAccess<Settings>(Settings::get())->fileLevelMap[file_name] = level;
|
||||
}
|
||||
|
||||
void setTagLevel(const std::string& tag_name, ELevel level)
|
||||
{
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
g.invalidateCallSites();
|
||||
s.tagLevelMap[tag_name] = level;
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
AIAccess<Settings>(Settings::get())->tagLevelMap[tag_name] = level;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,18 +693,16 @@ namespace LLError
|
||||
{
|
||||
void configure(const LLSD& config)
|
||||
{
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
AIAccess<Settings> settings_w(Settings::get());
|
||||
AIAccess<Globals>(Globals::get())->invalidateCallSites();
|
||||
settings_w->functionLevelMap.clear();
|
||||
settings_w->classLevelMap.clear();
|
||||
settings_w->fileLevelMap.clear();
|
||||
settings_w->tagLevelMap.clear();
|
||||
settings_w->uniqueLogMessages.clear();
|
||||
|
||||
g.invalidateCallSites();
|
||||
s.functionLevelMap.clear();
|
||||
s.classLevelMap.clear();
|
||||
s.fileLevelMap.clear();
|
||||
s.tagLevelMap.clear();
|
||||
s.uniqueLogMessages.clear();
|
||||
|
||||
setPrintLocation(config["print-location"]);
|
||||
setDefaultLevel(decodeLevel(config["default-level"]));
|
||||
setPrintLocation(settings_w, config["print-location"]);
|
||||
setDefaultLevel(settings_w, decodeLevel(config["default-level"]));
|
||||
|
||||
LLSD sets = config["settings"];
|
||||
LLSD::array_const_iterator a, end;
|
||||
@@ -722,10 +712,10 @@ namespace LLError
|
||||
|
||||
ELevel level = decodeLevel(entry["level"]);
|
||||
|
||||
setLevels(s.functionLevelMap, entry["functions"], level);
|
||||
setLevels(s.classLevelMap, entry["classes"], level);
|
||||
setLevels(s.fileLevelMap, entry["files"], level);
|
||||
setLevels(s.tagLevelMap, entry["tags"], level);
|
||||
setLevels(settings_w->functionLevelMap, entry["functions"], level);
|
||||
setLevels(settings_w->classLevelMap, entry["classes"], level);
|
||||
setLevels(settings_w->fileLevelMap, entry["files"], level);
|
||||
setLevels(settings_w->tagLevelMap, entry["tags"], level);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -742,26 +732,34 @@ namespace LLError
|
||||
|
||||
|
||||
|
||||
void addRecorder(Recorder* recorder)
|
||||
void addRecorder(AIAccess<Settings> const& settings_w, Recorder* recorder)
|
||||
{
|
||||
if (recorder == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Settings& s = Settings::get();
|
||||
s.recorders.push_back(recorder);
|
||||
settings_w->recorders.push_back(recorder);
|
||||
}
|
||||
|
||||
void addRecorder(Recorder* recorder)
|
||||
{
|
||||
addRecorder(AIAccess<Settings>(Settings::get()), recorder);
|
||||
}
|
||||
|
||||
void removeRecorder(AIAccess<Settings> const& settings_w, Recorder* recorder)
|
||||
{
|
||||
if (recorder == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
settings_w->recorders.erase(
|
||||
std::remove(settings_w->recorders.begin(), settings_w->recorders.end(), recorder),
|
||||
settings_w->recorders.end());
|
||||
}
|
||||
|
||||
void removeRecorder(Recorder* recorder)
|
||||
{
|
||||
if (recorder == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Settings& s = Settings::get();
|
||||
s.recorders.erase(
|
||||
std::remove(s.recorders.begin(), s.recorders.end(), recorder),
|
||||
s.recorders.end());
|
||||
removeRecorder(AIAccess<Settings>(Settings::get()), recorder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -769,12 +767,12 @@ namespace LLError
|
||||
{
|
||||
void logToFile(const std::string& file_name)
|
||||
{
|
||||
LLError::Settings& s = LLError::Settings::get();
|
||||
AIAccess<Settings> settings_w(Settings::get());
|
||||
|
||||
removeRecorder(s.fileRecorder);
|
||||
delete s.fileRecorder;
|
||||
s.fileRecorder = NULL;
|
||||
s.fileRecorderFileName.clear();
|
||||
removeRecorder(settings_w, settings_w->fileRecorder);
|
||||
delete settings_w->fileRecorder;
|
||||
settings_w->fileRecorder = NULL;
|
||||
settings_w->fileRecorderFileName.clear();
|
||||
|
||||
if (file_name.empty())
|
||||
{
|
||||
@@ -788,54 +786,51 @@ namespace LLError
|
||||
return;
|
||||
}
|
||||
|
||||
s.fileRecorderFileName = file_name;
|
||||
s.fileRecorder = f;
|
||||
addRecorder(f);
|
||||
settings_w->fileRecorderFileName = file_name;
|
||||
settings_w->fileRecorder = f;
|
||||
addRecorder(settings_w, f);
|
||||
}
|
||||
|
||||
void logToFixedBuffer(LLLineBuffer* fixedBuffer)
|
||||
{
|
||||
LLError::Settings& s = LLError::Settings::get();
|
||||
AIAccess<Settings> settings_w(Settings::get());
|
||||
|
||||
removeRecorder(s.fixedBufferRecorder);
|
||||
delete s.fixedBufferRecorder;
|
||||
s.fixedBufferRecorder = NULL;
|
||||
removeRecorder(settings_w, settings_w->fixedBufferRecorder);
|
||||
delete settings_w->fixedBufferRecorder;
|
||||
settings_w->fixedBufferRecorder = NULL;
|
||||
|
||||
if (!fixedBuffer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s.fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
|
||||
addRecorder(s.fixedBufferRecorder);
|
||||
settings_w->fixedBufferRecorder = new RecordToFixedBuffer(fixedBuffer);
|
||||
addRecorder(settings_w, settings_w->fixedBufferRecorder);
|
||||
}
|
||||
|
||||
std::string logFileName()
|
||||
{
|
||||
LLError::Settings& s = LLError::Settings::get();
|
||||
return s.fileRecorderFileName;
|
||||
return AIAccess<Settings>(Settings::get())->fileRecorderFileName;
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
void writeToRecorders(LLError::ELevel level, const std::string& message)
|
||||
void writeToRecorders(AIAccess<LLError::Settings> const& settings_w, LLError::ELevel level, const std::string& message)
|
||||
{
|
||||
LLError::Settings& s = LLError::Settings::get();
|
||||
|
||||
std::string messageWithTime;
|
||||
|
||||
for (Recorders::const_iterator i = s.recorders.begin();
|
||||
i != s.recorders.end();
|
||||
|
||||
for (Recorders::const_iterator i = settings_w->recorders.begin();
|
||||
i != settings_w->recorders.end();
|
||||
++i)
|
||||
{
|
||||
LLError::Recorder* r = *i;
|
||||
|
||||
if (r->wantsTime() && s.timeFunction != NULL)
|
||||
if (r->wantsTime() && settings_w->timeFunction != NULL)
|
||||
{
|
||||
if (messageWithTime.empty())
|
||||
{
|
||||
messageWithTime = s.timeFunction() + " " + message;
|
||||
messageWithTime = settings_w->timeFunction() + " " + message;
|
||||
}
|
||||
|
||||
r->recordMessage(level, messageWithTime);
|
||||
@@ -877,6 +872,9 @@ You get:
|
||||
|
||||
*/
|
||||
|
||||
apr_thread_mutex_t* gLogMutexp;
|
||||
apr_thread_mutex_t* gCallStacksLogMutexp;
|
||||
|
||||
namespace {
|
||||
bool checkLevelMap(const LevelMap& map, const std::string& key,
|
||||
LLError::ELevel& level)
|
||||
@@ -952,10 +950,9 @@ namespace LLError
|
||||
return false;
|
||||
}
|
||||
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
AIAccess<Settings> settings_w(Settings::get());
|
||||
|
||||
s.shouldLogCallCounter += 1;
|
||||
settings_w->shouldLogCallCounter += 1;
|
||||
|
||||
std::string class_name = className(site.mClassInfo);
|
||||
std::string function_name = functionName(site.mFunction);
|
||||
@@ -964,20 +961,20 @@ namespace LLError
|
||||
function_name = class_name + "::" + function_name;
|
||||
}
|
||||
|
||||
ELevel compareLevel = s.defaultLevel;
|
||||
ELevel compareLevel = settings_w->defaultLevel;
|
||||
|
||||
// The most specific match found will be used as the log level,
|
||||
// since the computation short circuits.
|
||||
// So, in increasing order of importance:
|
||||
// Default < Broad Tag < File < Class < Function < Narrow Tag
|
||||
((site.mNarrowTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mNarrowTag, compareLevel) : false)
|
||||
|| checkLevelMap(s.functionLevelMap, function_name, compareLevel)
|
||||
|| checkLevelMap(s.classLevelMap, class_name, compareLevel)
|
||||
|| checkLevelMap(s.fileLevelMap, abbreviateFile(site.mFile), compareLevel)
|
||||
|| ((site.mBroadTag != NULL) ? checkLevelMap(s.tagLevelMap, site.mBroadTag, compareLevel) : false);
|
||||
((site.mNarrowTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mNarrowTag, compareLevel) : false)
|
||||
|| checkLevelMap(settings_w->functionLevelMap, function_name, compareLevel)
|
||||
|| checkLevelMap(settings_w->classLevelMap, class_name, compareLevel)
|
||||
|| checkLevelMap(settings_w->fileLevelMap, abbreviateFile(site.mFile), compareLevel)
|
||||
|| ((site.mBroadTag != NULL) ? checkLevelMap(settings_w->tagLevelMap, site.mBroadTag, compareLevel) : false);
|
||||
|
||||
site.mCached = true;
|
||||
g.addCallSite(site);
|
||||
AIAccess<Globals>(Globals::get())->addCallSite(site);
|
||||
return site.mShouldLog = site.mLevel >= compareLevel;
|
||||
}
|
||||
|
||||
@@ -987,16 +984,16 @@ namespace LLError
|
||||
LogLock lock;
|
||||
if (lock.ok())
|
||||
{
|
||||
Globals& g = Globals::get();
|
||||
AIAccess<Globals> globals(Globals::get());
|
||||
|
||||
if (!g.messageStreamInUse)
|
||||
if (!globals->messageStreamInUse)
|
||||
{
|
||||
g.messageStreamInUse = true;
|
||||
return &g.messageStream;
|
||||
globals->messageStreamInUse = true;
|
||||
return &globals->messageStream; // Returns pointer to member of unlocked object, apparently "protected" by having set globals->messageStreamInUse.
|
||||
}
|
||||
}
|
||||
|
||||
return new std::ostringstream;
|
||||
return new std::ostringstream; // Holy memory leak.
|
||||
}
|
||||
|
||||
void Log::flush(std::ostringstream* out, char* message)
|
||||
@@ -1017,12 +1014,12 @@ namespace LLError
|
||||
message[127] = '\0' ;
|
||||
}
|
||||
|
||||
Globals& g = Globals::get();
|
||||
if (out == &g.messageStream)
|
||||
AIAccess<Globals> globals(Globals::get());
|
||||
if (out == &globals->messageStream)
|
||||
{
|
||||
g.messageStream.clear();
|
||||
g.messageStream.str("");
|
||||
g.messageStreamInUse = false;
|
||||
globals->messageStream.clear();
|
||||
globals->messageStream.str("");
|
||||
globals->messageStreamInUse = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1039,28 +1036,31 @@ namespace LLError
|
||||
return;
|
||||
}
|
||||
|
||||
Globals& g = Globals::get();
|
||||
Settings& s = Settings::get();
|
||||
|
||||
std::string message = out->str();
|
||||
if (out == &g.messageStream)
|
||||
|
||||
{
|
||||
g.messageStream.clear();
|
||||
g.messageStream.str("");
|
||||
g.messageStreamInUse = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete out;
|
||||
AIAccess<Globals> globals(Globals::get());
|
||||
if (out == &globals->messageStream)
|
||||
{
|
||||
globals->messageStream.clear();
|
||||
globals->messageStream.str("");
|
||||
globals->messageStreamInUse = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
delete out;
|
||||
}
|
||||
}
|
||||
|
||||
AIAccess<Settings> settings_w(Settings::get());
|
||||
|
||||
if (site.mLevel == LEVEL_ERROR)
|
||||
{
|
||||
std::ostringstream fatalMessage;
|
||||
fatalMessage << abbreviateFile(site.mFile)
|
||||
<< "(" << site.mLine << ") : error";
|
||||
|
||||
writeToRecorders(site.mLevel, fatalMessage.str());
|
||||
writeToRecorders(settings_w, site.mLevel, fatalMessage.str());
|
||||
}
|
||||
|
||||
|
||||
@@ -1075,7 +1075,7 @@ namespace LLError
|
||||
default: prefix << "XXX: "; break;
|
||||
};
|
||||
|
||||
if (s.printLocation)
|
||||
if (settings_w->printLocation)
|
||||
{
|
||||
prefix << abbreviateFile(site.mFile)
|
||||
<< "(" << site.mLine << ") : ";
|
||||
@@ -1093,8 +1093,8 @@ namespace LLError
|
||||
|
||||
if (site.mPrintOnce)
|
||||
{
|
||||
std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message);
|
||||
if (messageIter != s.uniqueLogMessages.end())
|
||||
std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message);
|
||||
if (messageIter != settings_w->uniqueLogMessages.end())
|
||||
{
|
||||
messageIter->second++;
|
||||
unsigned int num_messages = messageIter->second;
|
||||
@@ -1110,14 +1110,14 @@ namespace LLError
|
||||
else
|
||||
{
|
||||
prefix << "ONCE: ";
|
||||
s.uniqueLogMessages[message] = 1;
|
||||
settings_w->uniqueLogMessages[message] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (site.mPrintOnce)
|
||||
{
|
||||
std::map<std::string, unsigned int>::iterator messageIter = s.uniqueLogMessages.find(message);
|
||||
if (messageIter != s.uniqueLogMessages.end())
|
||||
std::map<std::string, unsigned int>::iterator messageIter = settings_w->uniqueLogMessages.find(message);
|
||||
if (messageIter != settings_w->uniqueLogMessages.end())
|
||||
{
|
||||
messageIter->second++;
|
||||
unsigned int num_messages = messageIter->second;
|
||||
@@ -1133,18 +1133,18 @@ namespace LLError
|
||||
else
|
||||
{
|
||||
prefix << "ONCE: ";
|
||||
s.uniqueLogMessages[message] = 1;
|
||||
settings_w->uniqueLogMessages[message] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
prefix << message;
|
||||
message = prefix.str();
|
||||
|
||||
writeToRecorders(site.mLevel, message);
|
||||
writeToRecorders(settings_w, site.mLevel, message);
|
||||
|
||||
if (site.mLevel == LEVEL_ERROR && s.crashFunction)
|
||||
if (site.mLevel == LEVEL_ERROR && settings_w->crashFunction)
|
||||
{
|
||||
s.crashFunction(message);
|
||||
settings_w->crashFunction(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1154,14 +1154,16 @@ namespace LLError
|
||||
|
||||
namespace LLError
|
||||
{
|
||||
Settings* saveAndResetSettings()
|
||||
class ThreadSafeSettings { };
|
||||
|
||||
ThreadSafeSettings* saveAndResetSettings()
|
||||
{
|
||||
return Settings::saveAndReset();
|
||||
return reinterpret_cast<ThreadSafeSettings*>(Settings::saveAndReset());
|
||||
}
|
||||
|
||||
void restoreSettings(Settings* s)
|
||||
void restoreSettings(ThreadSafeSettings* s)
|
||||
{
|
||||
return Settings::restore(s);
|
||||
Settings::restore(reinterpret_cast<AIThreadSafeSimple<Settings>*>(s));
|
||||
}
|
||||
|
||||
std::string removePrefix(std::string& s, const std::string& p)
|
||||
@@ -1207,8 +1209,7 @@ namespace LLError
|
||||
|
||||
int shouldLogCallCount()
|
||||
{
|
||||
Settings& s = Settings::get();
|
||||
return s.shouldLogCallCounter;
|
||||
return AIAccess<Settings>(Settings::get())->shouldLogCallCounter;
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
|
||||
@@ -167,9 +167,9 @@ namespace LLError
|
||||
Utilities for use by the unit tests of LLError itself.
|
||||
*/
|
||||
|
||||
class Settings;
|
||||
LL_COMMON_API Settings* saveAndResetSettings();
|
||||
LL_COMMON_API void restoreSettings(Settings *);
|
||||
class ThreadSafeSettings;
|
||||
LL_COMMON_API ThreadSafeSettings* saveAndResetSettings();
|
||||
LL_COMMON_API void restoreSettings(ThreadSafeSettings *);
|
||||
|
||||
LL_COMMON_API std::string abbreviateFile(const std::string& filePath);
|
||||
LL_COMMON_API int shouldLogCallCount();
|
||||
|
||||
@@ -36,8 +36,7 @@
|
||||
|
||||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines),
|
||||
mMutex(NULL)
|
||||
mMaxLines(max_lines)
|
||||
{
|
||||
mTimer.reset();
|
||||
}
|
||||
|
||||
@@ -107,17 +107,7 @@
|
||||
|
||||
#endif
|
||||
|
||||
// Static linking with apr on windows needs to be declared.
|
||||
#ifdef LL_WINDOWS
|
||||
#ifndef APR_DECLARE_STATIC
|
||||
#define APR_DECLARE_STATIC // For APR on Windows
|
||||
#endif
|
||||
#ifndef APU_DECLARE_STATIC
|
||||
#define APU_DECLARE_STATIC // For APR util on Windows
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Deal with the differeneces on Windows
|
||||
// Deal with the differences on Windows
|
||||
#if defined(LL_WINDOWS)
|
||||
#define BOOST_REGEX_NO_LIB 1
|
||||
#define CURL_STATICLIB 1
|
||||
@@ -169,7 +159,6 @@
|
||||
#define LL_DLLIMPORT
|
||||
#endif // LL_WINDOWS
|
||||
|
||||
/*
|
||||
#ifdef llcommon_EXPORTS
|
||||
// Compiling llcommon (shared)
|
||||
#define LL_COMMON_API LL_DLLEXPORT
|
||||
@@ -177,9 +166,5 @@
|
||||
// Using llcommon (shared)
|
||||
#define LL_COMMON_API LL_DLLIMPORT
|
||||
#endif // llcommon_EXPORTS
|
||||
*/
|
||||
|
||||
//I hate DLLs -SG
|
||||
#define LL_COMMON_API
|
||||
|
||||
#endif // not LL_LINDEN_PREPROCESSOR_H
|
||||
|
||||
58
indra/llcommon/llscopedvolatileaprpool.h
Normal file
58
indra/llcommon/llscopedvolatileaprpool.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* @file llscopedvolatileaprpool.h
|
||||
* @brief Implementation of LLScopedVolatileAPRPool
|
||||
*
|
||||
* $LicenseInfo:firstyear=2010&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2010, Linden Research, Inc.
|
||||
*
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLSCOPEDVOLATILEAPRPOOL_H
|
||||
#define LL_LLSCOPEDVOLATILEAPRPOOL_H
|
||||
|
||||
#include "llthread.h"
|
||||
|
||||
//! Scoped volatile memory pool.
|
||||
//
|
||||
// As the AIVolatileAPRPool should never keep allocations very
|
||||
// long, it's most common use is for allocations with a lifetime
|
||||
// equal to it's scope.
|
||||
//
|
||||
// This is a convenience class that makes just a little easier to type.
|
||||
//
|
||||
class LLScopedVolatileAPRPool
|
||||
{
|
||||
private:
|
||||
AIVolatileAPRPool& mPool;
|
||||
apr_pool_t* mScopedAPRpool;
|
||||
public:
|
||||
LLScopedVolatileAPRPool() : mPool(AIThreadLocalData::tldata().mVolatileAPRPool), mScopedAPRpool(mPool.getVolatileAPRPool()) { }
|
||||
~LLScopedVolatileAPRPool() { mPool.clearVolatileAPRPool(); }
|
||||
// Only use this to pass the pointer to a libapr-1 function that requires it.
|
||||
operator apr_pool_t*() const { return mScopedAPRpool; }
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#if LL_LINUX || LL_SOLARIS
|
||||
#include <wctype.h>
|
||||
@@ -212,7 +213,7 @@ public:
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Static Utility functions that operate on std::strings
|
||||
|
||||
static std::basic_string<T> null;
|
||||
static std::basic_string<T> const null;
|
||||
|
||||
typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
|
||||
static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
|
||||
@@ -303,7 +304,7 @@ public:
|
||||
|
||||
};
|
||||
|
||||
template<class T> std::basic_string<T> LLStringUtilBase<T>::null;
|
||||
template<class T> std::basic_string<T> const LLStringUtilBase<T>::null;
|
||||
|
||||
typedef LLStringUtilBase<char> LLStringUtil;
|
||||
typedef LLStringUtilBase<llwchar> LLWStringUtil;
|
||||
|
||||
@@ -72,8 +72,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
|
||||
// Set thread state to running
|
||||
threadp->mStatus = RUNNING;
|
||||
|
||||
// Create a thread local APRFile pool.
|
||||
LLVolatileAPRPool::createLocalAPRFilePool();
|
||||
// Create a thread local data.
|
||||
AIThreadLocalData::create(threadp);
|
||||
|
||||
// Run the user supplied function
|
||||
threadp->run();
|
||||
@@ -87,24 +87,14 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap
|
||||
}
|
||||
|
||||
|
||||
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
|
||||
LLThread::LLThread(std::string const& name) :
|
||||
mPaused(FALSE),
|
||||
mName(name),
|
||||
mAPRThreadp(NULL),
|
||||
mStatus(STOPPED)
|
||||
mStatus(STOPPED),
|
||||
mThreadLocalData(NULL)
|
||||
{
|
||||
// Thread creation probably CAN be paranoid about APR being initialized, if necessary
|
||||
if (poolp)
|
||||
{
|
||||
mIsLocalPool = FALSE;
|
||||
mAPRPoolp = poolp;
|
||||
}
|
||||
else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
mRunCondition = new LLCondition(mAPRPoolp);
|
||||
mRunCondition = new LLCondition;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,24 +137,18 @@ void LLThread::shutdown()
|
||||
if (!isStopped())
|
||||
{
|
||||
// This thread just wouldn't stop, even though we gave it time
|
||||
llwarns << "LLThread::~LLThread() exiting thread before clean exit!" << llendl;
|
||||
llwarns << "LLThread::shutdown() exiting thread before clean exit!" << llendl;
|
||||
return;
|
||||
}
|
||||
mAPRThreadp = NULL;
|
||||
}
|
||||
|
||||
delete mRunCondition;
|
||||
|
||||
if (mIsLocalPool)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLThread::start()
|
||||
{
|
||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, mAPRPoolp);
|
||||
apr_thread_create(&mAPRThreadp, NULL, staticRun, (void *)this, tldata().mRootPool());
|
||||
|
||||
// We won't bother joining
|
||||
apr_thread_detach(mAPRThreadp);
|
||||
@@ -265,38 +249,72 @@ void LLThread::wakeLocked()
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// This allows the use of llassert(is_main_thread()) to assure the current thread is the main thread.
|
||||
static apr_os_thread_t main_thread_id;
|
||||
LL_COMMON_API bool is_main_thread() { return apr_os_thread_equal(main_thread_id, apr_os_thread_current()); }
|
||||
#endif
|
||||
|
||||
// The thread private handle to access the AIThreadLocalData instance.
|
||||
apr_threadkey_t* AIThreadLocalData::sThreadLocalDataKey;
|
||||
|
||||
//static
|
||||
void AIThreadLocalData::init(void)
|
||||
{
|
||||
// Only do this once.
|
||||
if (sThreadLocalDataKey)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
apr_status_t status = apr_threadkey_private_create(&sThreadLocalDataKey, &AIThreadLocalData::destroy, AIAPRRootPool::get()());
|
||||
ll_apr_assert_status(status); // Or out of memory, or system-imposed limit on the
|
||||
// total number of keys per process {PTHREAD_KEYS_MAX}
|
||||
// has been exceeded.
|
||||
|
||||
// Create the thread-local data for the main thread (this function is called by the main thread).
|
||||
AIThreadLocalData::create(NULL);
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
// This function is called by the main thread.
|
||||
main_thread_id = apr_os_thread_current();
|
||||
#endif
|
||||
}
|
||||
|
||||
// This is called once for every thread when the thread is destructed.
|
||||
//static
|
||||
void AIThreadLocalData::destroy(void* thread_local_data)
|
||||
{
|
||||
delete reinterpret_cast<AIThreadLocalData*>(thread_local_data);
|
||||
}
|
||||
|
||||
//static
|
||||
void AIThreadLocalData::create(LLThread* threadp)
|
||||
{
|
||||
AIThreadLocalData* new_tld = new AIThreadLocalData;
|
||||
if (threadp)
|
||||
{
|
||||
threadp->mThreadLocalData = new_tld;
|
||||
}
|
||||
apr_status_t status = apr_threadkey_private_set(new_tld, sThreadLocalDataKey);
|
||||
llassert_always(status == APR_SUCCESS);
|
||||
}
|
||||
|
||||
//static
|
||||
AIThreadLocalData& AIThreadLocalData::tldata(void)
|
||||
{
|
||||
if (!sThreadLocalDataKey)
|
||||
AIThreadLocalData::init();
|
||||
|
||||
void* data;
|
||||
apr_status_t status = apr_threadkey_private_get(&data, sThreadLocalDataKey);
|
||||
llassert_always(status == APR_SUCCESS);
|
||||
return *static_cast<AIThreadLocalData*>(data);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
||||
LLMutex::LLMutex(apr_pool_t *poolp) :
|
||||
mAPRMutexp(NULL)
|
||||
{
|
||||
//if (poolp)
|
||||
//{
|
||||
// mIsLocalPool = FALSE;
|
||||
// mAPRPoolp = poolp;
|
||||
//}
|
||||
//else
|
||||
{
|
||||
mIsLocalPool = TRUE;
|
||||
apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
|
||||
}
|
||||
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
|
||||
}
|
||||
|
||||
LLMutex::~LLMutex()
|
||||
{
|
||||
#if _DEBUG
|
||||
llassert(!isLocked()); // better not be locked!
|
||||
#endif
|
||||
apr_thread_mutex_destroy(mAPRMutexp);
|
||||
mAPRMutexp = NULL;
|
||||
if (mIsLocalPool)
|
||||
{
|
||||
apr_pool_destroy(mAPRPoolp);
|
||||
}
|
||||
}
|
||||
|
||||
bool LLMutex::isLocked()
|
||||
bool LLMutexBase::isLocked()
|
||||
{
|
||||
if (!tryLock())
|
||||
{
|
||||
@@ -308,12 +326,9 @@ bool LLMutex::isLocked()
|
||||
|
||||
//============================================================================
|
||||
|
||||
LLCondition::LLCondition(apr_pool_t *poolp) :
|
||||
LLMutex(poolp)
|
||||
LLCondition::LLCondition(AIAPRPool& parent) : LLMutex(parent)
|
||||
{
|
||||
// base class (LLMutex) has already ensured that mAPRPoolp is set up.
|
||||
|
||||
apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
|
||||
apr_thread_cond_create(&mAPRCondp, mPool());
|
||||
}
|
||||
|
||||
LLCondition::~LLCondition()
|
||||
@@ -349,7 +364,7 @@ void LLThreadSafeRefCount::initThreadSafeRefCount()
|
||||
{
|
||||
if (!sMutex)
|
||||
{
|
||||
sMutex = new LLMutex(0);
|
||||
sMutex = new LLMutex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,11 +38,32 @@
|
||||
#include "llmemory.h"
|
||||
|
||||
#include "apr_thread_cond.h"
|
||||
#include "aiaprpool.h"
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
extern bool is_main_thread(void);
|
||||
#endif
|
||||
|
||||
class LLThread;
|
||||
class LLMutex;
|
||||
class LLCondition;
|
||||
|
||||
class LL_COMMON_API AIThreadLocalData
|
||||
{
|
||||
private:
|
||||
static apr_threadkey_t* sThreadLocalDataKey;
|
||||
|
||||
public:
|
||||
// Thread-local memory pool.
|
||||
AIAPRRootPool mRootPool;
|
||||
AIVolatileAPRPool mVolatileAPRPool;
|
||||
|
||||
static void init(void);
|
||||
static void destroy(void* thread_local_data);
|
||||
static void create(LLThread* pthread);
|
||||
static AIThreadLocalData& tldata(void);
|
||||
};
|
||||
|
||||
class LL_COMMON_API LLThread
|
||||
{
|
||||
public:
|
||||
@@ -53,7 +74,7 @@ public:
|
||||
QUITTING= 2 // Someone wants this thread to quit
|
||||
} EThreadStatus;
|
||||
|
||||
LLThread(const std::string& name, apr_pool_t *poolp = NULL);
|
||||
LLThread(std::string const& name);
|
||||
virtual ~LLThread(); // Warning! You almost NEVER want to destroy a thread unless it's in the STOPPED state.
|
||||
virtual void shutdown(); // stops the thread
|
||||
|
||||
@@ -82,7 +103,8 @@ public:
|
||||
// this kicks off the apr thread
|
||||
void start(void);
|
||||
|
||||
apr_pool_t *getAPRPool() { return mAPRPoolp; }
|
||||
// Return thread-local data for the current thread.
|
||||
static AIThreadLocalData& tldata(void) { return AIThreadLocalData::tldata(); }
|
||||
|
||||
private:
|
||||
BOOL mPaused;
|
||||
@@ -95,10 +117,11 @@ protected:
|
||||
LLCondition* mRunCondition;
|
||||
|
||||
apr_thread_t *mAPRThreadp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
EThreadStatus mStatus;
|
||||
|
||||
friend void AIThreadLocalData::create(LLThread* threadp);
|
||||
AIThreadLocalData* mThreadLocalData;
|
||||
|
||||
void setQuitting();
|
||||
|
||||
// virtual function overridden by subclass -- this will be called when the thread runs
|
||||
@@ -125,12 +148,9 @@ protected:
|
||||
|
||||
//============================================================================
|
||||
|
||||
class LL_COMMON_API LLMutex
|
||||
class LL_COMMON_API LLMutexBase
|
||||
{
|
||||
public:
|
||||
LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
|
||||
~LLMutex();
|
||||
|
||||
void lock() { apr_thread_mutex_lock(mAPRMutexp); }
|
||||
void unlock() { apr_thread_mutex_unlock(mAPRMutexp); }
|
||||
// Returns true if lock was obtained successfully.
|
||||
@@ -139,16 +159,60 @@ public:
|
||||
bool isLocked(); // non-blocking, but does do a lock/unlock so not free
|
||||
|
||||
protected:
|
||||
apr_thread_mutex_t *mAPRMutexp;
|
||||
apr_pool_t *mAPRPoolp;
|
||||
BOOL mIsLocalPool;
|
||||
// mAPRMutexp is initialized and uninitialized in the derived class.
|
||||
apr_thread_mutex_t* mAPRMutexp;
|
||||
};
|
||||
|
||||
class LL_COMMON_API LLMutex : public LLMutexBase
|
||||
{
|
||||
public:
|
||||
LLMutex(AIAPRPool& parent = LLThread::tldata().mRootPool) : mPool(parent)
|
||||
{
|
||||
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mPool());
|
||||
}
|
||||
~LLMutex()
|
||||
{
|
||||
llassert(!isLocked()); // better not be locked!
|
||||
apr_thread_mutex_destroy(mAPRMutexp);
|
||||
mAPRMutexp = NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
AIAPRPool mPool;
|
||||
};
|
||||
|
||||
#if APR_HAS_THREADS
|
||||
// No need to use a root pool in this case.
|
||||
typedef LLMutex LLMutexRootPool;
|
||||
#else // APR_HAS_THREADS
|
||||
class LL_COMMON_API LLMutexRootPool : public LLMutexBase
|
||||
{
|
||||
public:
|
||||
LLMutexRootPool(void)
|
||||
{
|
||||
apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mRootPool());
|
||||
}
|
||||
~LLMutexRootPool()
|
||||
{
|
||||
#if APR_POOL_DEBUG
|
||||
// It is allowed to destruct root pools from a different thread.
|
||||
mRootPool.grab_ownership();
|
||||
#endif
|
||||
llassert(!isLocked()); // better not be locked!
|
||||
apr_thread_mutex_destroy(mAPRMutexp);
|
||||
mAPRMutexp = NULL;
|
||||
}
|
||||
|
||||
protected:
|
||||
AIAPRRootPool mRootPool;
|
||||
};
|
||||
#endif // APR_HAS_THREADS
|
||||
|
||||
// Actually a condition/mutex pair (since each condition needs to be associated with a mutex).
|
||||
class LL_COMMON_API LLCondition : public LLMutex
|
||||
{
|
||||
public:
|
||||
LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well.
|
||||
LLCondition(AIAPRPool& parent = LLThread::tldata().mRootPool);
|
||||
~LLCondition();
|
||||
|
||||
void wait(); // blocks
|
||||
@@ -162,7 +226,7 @@ protected:
|
||||
class LL_COMMON_API LLMutexLock
|
||||
{
|
||||
public:
|
||||
LLMutexLock(LLMutex* mutex)
|
||||
LLMutexLock(LLMutexBase* mutex)
|
||||
{
|
||||
mMutex = mutex;
|
||||
mMutex->lock();
|
||||
@@ -172,7 +236,102 @@ public:
|
||||
mMutex->unlock();
|
||||
}
|
||||
private:
|
||||
LLMutex* mMutex;
|
||||
LLMutexBase* mMutex;
|
||||
};
|
||||
|
||||
class AIRWLock
|
||||
{
|
||||
public:
|
||||
AIRWLock(AIAPRPool& parent = LLThread::tldata().mRootPool) :
|
||||
mWriterWaitingMutex(parent), mNoHoldersCondition(parent), mHoldersCount(0), mWriterIsWaiting(false) { }
|
||||
|
||||
private:
|
||||
LLMutex mWriterWaitingMutex; //!< This mutex is locked while some writer is waiting for access.
|
||||
LLCondition mNoHoldersCondition; //!< Access control for mHoldersCount. Condition true when there are no more holders.
|
||||
int mHoldersCount; //!< Number of readers or -1 if a writer locked this object.
|
||||
// This is volatile because we read it outside the critical area of mWriterWaitingMutex, at [1].
|
||||
// That means that other threads can change it while we are already in the (inlined) function rdlock.
|
||||
// Without volatile, the following assembly would fail:
|
||||
// register x = mWriterIsWaiting;
|
||||
// /* some thread changes mWriterIsWaiting */
|
||||
// if (x ...
|
||||
// However, because the function is fuzzy to begin with (we don't mind that this race
|
||||
// condition exists) it would work fine without volatile. So, basically it's just here
|
||||
// out of principle ;). -- Aleric
|
||||
bool volatile mWriterIsWaiting; //!< True when there is a writer waiting for write access.
|
||||
|
||||
public:
|
||||
void rdlock(bool high_priority = false)
|
||||
{
|
||||
// Give a writer a higher priority (kinda fuzzy).
|
||||
if (mWriterIsWaiting && !high_priority) // [1] If there is a writer interested,
|
||||
{
|
||||
mWriterWaitingMutex.lock(); // [2] then give it precedence and wait here.
|
||||
// If we get here then the writer got it's access; mHoldersCount == -1.
|
||||
mWriterWaitingMutex.unlock();
|
||||
}
|
||||
mNoHoldersCondition.lock(); // [3] Get exclusive access to mHoldersCount.
|
||||
while (mHoldersCount == -1) // [4]
|
||||
{
|
||||
mNoHoldersCondition.wait(); // [5] Wait till mHoldersCount is (or just was) 0.
|
||||
}
|
||||
++mHoldersCount; // One more reader.
|
||||
mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
|
||||
}
|
||||
void rdunlock(void)
|
||||
{
|
||||
mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
|
||||
if (--mHoldersCount == 0) // Was this the last reader?
|
||||
{
|
||||
mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7].
|
||||
}
|
||||
mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
|
||||
}
|
||||
void wrlock(void)
|
||||
{
|
||||
mWriterWaitingMutex.lock(); // Block new readers, see [2],
|
||||
mWriterIsWaiting = true; // from this moment on, see [1].
|
||||
mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
|
||||
while (mHoldersCount != 0) // Other readers or writers have this lock?
|
||||
{
|
||||
mNoHoldersCondition.wait(); // [6] Wait till mHoldersCount is (or just was) 0.
|
||||
}
|
||||
mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1].
|
||||
mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3].
|
||||
mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]).
|
||||
mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]).
|
||||
}
|
||||
void wrunlock(void)
|
||||
{
|
||||
mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
|
||||
mHoldersCount = 0; // We have no writer anymore.
|
||||
mNoHoldersCondition.signal(); // Tell waiting threads, see [5], [6] and [7].
|
||||
mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
|
||||
}
|
||||
void rd2wrlock(void)
|
||||
{
|
||||
mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount. Blocks new readers at [3].
|
||||
if (--mHoldersCount > 0) // Any other reads left?
|
||||
{
|
||||
mWriterWaitingMutex.lock(); // Block new readers, see [2],
|
||||
mWriterIsWaiting = true; // from this moment on, see [1].
|
||||
while (mHoldersCount != 0) // Other readers (still) have this lock?
|
||||
{
|
||||
mNoHoldersCondition.wait(); // [7] Wait till mHoldersCount is (or just was) 0.
|
||||
}
|
||||
mWriterIsWaiting = false; // Stop checking the lock for new readers, see [1].
|
||||
mWriterWaitingMutex.unlock(); // Release blocked readers, they will still hang at [3].
|
||||
}
|
||||
mHoldersCount = -1; // We are a writer now (will cause a hang at [5], see [4]).
|
||||
mNoHoldersCondition.unlock(); // Release lock on mHolders (readers go from [3] to [5]).
|
||||
}
|
||||
void wr2rdlock(void)
|
||||
{
|
||||
mNoHoldersCondition.lock(); // Get exclusive access to mHoldersCount.
|
||||
mHoldersCount = 1; // Turn writer into a reader.
|
||||
mNoHoldersCondition.signal(); // Tell waiting readers, see [5].
|
||||
mNoHoldersCondition.unlock(); // Release lock on mHoldersCount.
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
@@ -187,7 +346,6 @@ void LLThread::unlockData()
|
||||
mRunCondition->unlock();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
|
||||
// see llmemory.h for LLPointer<> definition
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded) :
|
||||
LLQueuedThread(name, threaded)
|
||||
{
|
||||
mDeleteMutex = new LLMutex(NULL);
|
||||
mDeleteMutex = new LLMutex;
|
||||
}
|
||||
|
||||
LLWorkerThread::~LLWorkerThread()
|
||||
@@ -205,7 +205,6 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
|
||||
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
|
||||
mWorkerClassName(name),
|
||||
mRequestHandle(LLWorkerThread::nullHandle()),
|
||||
mMutex(NULL),
|
||||
mWorkFlags(0)
|
||||
{
|
||||
if (!mWorkerThread)
|
||||
|
||||
@@ -200,7 +200,7 @@ protected:
|
||||
U32 mRequestPriority; // last priority set
|
||||
|
||||
private:
|
||||
LLMutex mMutex;
|
||||
LLMutexRootPool mMutex; // Use LLMutexRootPool since this object is created and destructed by multiple threads.
|
||||
LLAtomicU32 mWorkFlags;
|
||||
};
|
||||
|
||||
|
||||
3
indra/llcrashlogger/llcrashlogger.cpp
Executable file → Normal file
3
indra/llcrashlogger/llcrashlogger.cpp
Executable file → Normal file
@@ -387,8 +387,7 @@ bool LLCrashLogger::init()
|
||||
return false;
|
||||
}
|
||||
|
||||
gServicePump = new LLPumpIO(gAPRPoolp);
|
||||
gServicePump->prime(gAPRPoolp);
|
||||
gServicePump = new LLPumpIO;
|
||||
LLHTTPClient::setPump(*gServicePump);
|
||||
|
||||
//If we've opened the crash logger, assume we can delete the marker file if it exists
|
||||
|
||||
0
indra/llcrashlogger/llcrashlogger.h
Executable file → Normal file
0
indra/llcrashlogger/llcrashlogger.h
Executable file → Normal file
@@ -57,7 +57,7 @@ LLMutex* LLImage::sMutex = NULL;
|
||||
//static
|
||||
void LLImage::initClass()
|
||||
{
|
||||
sMutex = new LLMutex(NULL);
|
||||
sMutex = new LLMutex;
|
||||
LLImageJ2C::openDSO();
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ typedef const char* (*EngineInfoLLImageJ2CFunction)();
|
||||
CreateLLImageJ2CFunction j2cimpl_create_func;
|
||||
DestroyLLImageJ2CFunction j2cimpl_destroy_func;
|
||||
EngineInfoLLImageJ2CFunction j2cimpl_engineinfo_func;
|
||||
apr_pool_t *j2cimpl_dso_memory_pool;
|
||||
AIAPRPool j2cimpl_dso_memory_pool;
|
||||
apr_dso_handle_t *j2cimpl_dso_handle;
|
||||
|
||||
//Declare the prototype for theses functions here, their functionality
|
||||
@@ -82,13 +82,12 @@ void LLImageJ2C::openDSO()
|
||||
gDirUtilp->getExecutableDir());
|
||||
|
||||
j2cimpl_dso_handle = NULL;
|
||||
j2cimpl_dso_memory_pool = NULL;
|
||||
j2cimpl_dso_memory_pool.create();
|
||||
|
||||
//attempt to load the shared library
|
||||
apr_pool_create(&j2cimpl_dso_memory_pool, NULL);
|
||||
rv = apr_dso_load(&j2cimpl_dso_handle,
|
||||
dso_path.c_str(),
|
||||
j2cimpl_dso_memory_pool);
|
||||
j2cimpl_dso_memory_pool());
|
||||
|
||||
//now, check for success
|
||||
if ( rv == APR_SUCCESS )
|
||||
@@ -152,11 +151,7 @@ void LLImageJ2C::openDSO()
|
||||
j2cimpl_dso_handle = NULL;
|
||||
}
|
||||
|
||||
if ( j2cimpl_dso_memory_pool )
|
||||
{
|
||||
apr_pool_destroy(j2cimpl_dso_memory_pool);
|
||||
j2cimpl_dso_memory_pool = NULL;
|
||||
}
|
||||
j2cimpl_dso_memory_pool.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +159,7 @@ void LLImageJ2C::openDSO()
|
||||
void LLImageJ2C::closeDSO()
|
||||
{
|
||||
if ( j2cimpl_dso_handle ) apr_dso_unload(j2cimpl_dso_handle);
|
||||
if (j2cimpl_dso_memory_pool) apr_pool_destroy(j2cimpl_dso_memory_pool);
|
||||
j2cimpl_dso_memory_pool.destroy();
|
||||
}
|
||||
|
||||
//static
|
||||
|
||||
@@ -41,20 +41,13 @@
|
||||
LLImageDecodeThread::LLImageDecodeThread(bool threaded)
|
||||
: LLQueuedThread("imagedecode", threaded)
|
||||
{
|
||||
mCreationMutex = new LLMutex(getAPRPool());
|
||||
}
|
||||
|
||||
//virtual
|
||||
LLImageDecodeThread::~LLImageDecodeThread()
|
||||
{
|
||||
delete mCreationMutex ;
|
||||
}
|
||||
|
||||
// MAIN THREAD
|
||||
// virtual
|
||||
S32 LLImageDecodeThread::update(U32 max_time_ms)
|
||||
{
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
LLMutexLock lock(&mCreationMutex);
|
||||
for (creation_list_t::iterator iter = mCreationList.begin();
|
||||
iter != mCreationList.end(); ++iter)
|
||||
{
|
||||
@@ -77,7 +70,7 @@ S32 LLImageDecodeThread::update(U32 max_time_ms)
|
||||
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
|
||||
U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
|
||||
{
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
LLMutexLock lock(&mCreationMutex);
|
||||
handle_t handle = generateHandle();
|
||||
mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
|
||||
return handle;
|
||||
@@ -87,7 +80,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted*
|
||||
// Returns the size of the mutex guarded list as an indication of sanity
|
||||
S32 LLImageDecodeThread::tut_size()
|
||||
{
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
LLMutexLock lock(&mCreationMutex);
|
||||
S32 res = mCreationList.size();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -78,8 +78,6 @@ public:
|
||||
|
||||
public:
|
||||
LLImageDecodeThread(bool threaded = true);
|
||||
virtual ~LLImageDecodeThread();
|
||||
|
||||
handle_t decodeImage(LLImageFormatted* image,
|
||||
U32 priority, S32 discard, BOOL needs_aux,
|
||||
Responder* responder);
|
||||
@@ -103,7 +101,7 @@ private:
|
||||
};
|
||||
typedef std::list<creation_info> creation_list_t;
|
||||
creation_list_t mCreationList;
|
||||
LLMutex* mCreationMutex;
|
||||
LLMutex mCreationMutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,7 +55,7 @@ LLVolumeMgr::LLVolumeMgr()
|
||||
{
|
||||
// the LLMutex magic interferes with easy unit testing,
|
||||
// so you now must manually call useMutex() to use it
|
||||
//mDataMutex = new LLMutex(gAPRPoolp);
|
||||
//mDataMutex = new LLMutex;
|
||||
}
|
||||
|
||||
LLVolumeMgr::~LLVolumeMgr()
|
||||
@@ -222,7 +222,7 @@ void LLVolumeMgr::useMutex()
|
||||
{
|
||||
if (!mDataMutex)
|
||||
{
|
||||
mDataMutex = new LLMutex(gAPRPoolp);
|
||||
mDataMutex = new LLMutex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "llapr.h"
|
||||
#define CARES_STATICLIB
|
||||
#include "llares.h"
|
||||
#include "llscopedvolatileaprpool.h"
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
# define ns_c_in 1
|
||||
@@ -467,11 +468,6 @@ void LLAres::search(const std::string &query, LLResType type,
|
||||
|
||||
bool LLAres::process(U64 timeout)
|
||||
{
|
||||
if (!gAPRPoolp)
|
||||
{
|
||||
ll_init_apr();
|
||||
}
|
||||
|
||||
ares_socket_t socks[ARES_GETSOCK_MAXNUM];
|
||||
apr_pollfd_t aprFds[ARES_GETSOCK_MAXNUM];
|
||||
apr_int32_t nsds = 0;
|
||||
@@ -485,10 +481,7 @@ bool LLAres::process(U64 timeout)
|
||||
return nsds > 0;
|
||||
}
|
||||
|
||||
apr_status_t status;
|
||||
LLAPRPool pool;
|
||||
status = pool.getStatus() ;
|
||||
ll_apr_assert_status(status);
|
||||
LLScopedVolatileAPRPool scoped_pool;
|
||||
|
||||
for (int i = 0; i < ARES_GETSOCK_MAXNUM; i++)
|
||||
{
|
||||
@@ -505,7 +498,7 @@ bool LLAres::process(U64 timeout)
|
||||
|
||||
apr_socket_t *aprSock = NULL;
|
||||
|
||||
status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], pool.getAPRPool());
|
||||
apr_status_t status = apr_os_sock_put(&aprSock, (apr_os_sock_t *) &socks[i], scoped_pool);
|
||||
if (status != APR_SUCCESS)
|
||||
{
|
||||
ll_apr_warn_status(status);
|
||||
@@ -514,7 +507,7 @@ bool LLAres::process(U64 timeout)
|
||||
|
||||
aprFds[nactive].desc.s = aprSock;
|
||||
aprFds[nactive].desc_type = APR_POLL_SOCKET;
|
||||
aprFds[nactive].p = pool.getAPRPool();
|
||||
aprFds[nactive].p = scoped_pool;
|
||||
aprFds[nactive].rtnevents = 0;
|
||||
aprFds[nactive].client_data = &socks[i];
|
||||
|
||||
@@ -523,7 +516,7 @@ bool LLAres::process(U64 timeout)
|
||||
|
||||
if (nactive > 0)
|
||||
{
|
||||
status = apr_poll(aprFds, nactive, &nsds, timeout);
|
||||
apr_status_t status = apr_poll(aprFds, nactive, &nsds, timeout);
|
||||
|
||||
if (status != APR_SUCCESS && status != APR_TIMEUP)
|
||||
{
|
||||
|
||||
@@ -1082,7 +1082,7 @@ void LLCurl::initClass()
|
||||
S32 mutex_count = CRYPTO_num_locks();
|
||||
for (S32 i=0; i<mutex_count; i++)
|
||||
{
|
||||
sSSLMutex.push_back(new LLMutex(NULL));
|
||||
sSSLMutex.push_back(new LLMutex);
|
||||
}
|
||||
CRYPTO_set_id_callback(&LLCurl::ssl_thread_id);
|
||||
CRYPTO_set_locking_callback(&LLCurl::ssl_locking_callback);
|
||||
|
||||
@@ -960,13 +960,9 @@ private:
|
||||
|
||||
|
||||
// static
|
||||
LLHTTPNode& LLIOHTTPServer::create(
|
||||
apr_pool_t* pool, LLPumpIO& pump, U16 port)
|
||||
LLHTTPNode& LLIOHTTPServer::create(LLPumpIO& pump, U16 port)
|
||||
{
|
||||
LLSocket::ptr_t socket = LLSocket::create(
|
||||
pool,
|
||||
LLSocket::STREAM_TCP,
|
||||
port);
|
||||
LLSocket::ptr_t socket = LLSocket::create(LLSocket::STREAM_TCP, port);
|
||||
if(!socket)
|
||||
{
|
||||
llerrs << "Unable to initialize socket" << llendl;
|
||||
@@ -975,7 +971,7 @@ LLHTTPNode& LLIOHTTPServer::create(
|
||||
LLHTTPResponseFactory* factory = new LLHTTPResponseFactory;
|
||||
boost::shared_ptr<LLChainIOFactory> factory_ptr(factory);
|
||||
|
||||
LLIOServerSocket* server = new LLIOServerSocket(pool, socket, factory_ptr);
|
||||
LLIOServerSocket* server = new LLIOServerSocket(socket, factory_ptr);
|
||||
|
||||
LLPumpIO::chain_t chain;
|
||||
chain.push_back(LLIOPipe::ptr_t(server));
|
||||
|
||||
@@ -56,7 +56,7 @@ class LLIOHTTPServer
|
||||
public:
|
||||
typedef void (*timing_callback_t)(const char* hashed_name, F32 time, void* data);
|
||||
|
||||
static LLHTTPNode& create(apr_pool_t* pool, LLPumpIO& pump, U16 port);
|
||||
static LLHTTPNode& create(LLPumpIO& pump, U16 port);
|
||||
/**< Creates an HTTP wire server on the pump for the given TCP port.
|
||||
*
|
||||
* Returns the root node of the new server. Add LLHTTPNode instances
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include "llhost.h"
|
||||
#include "llmemtype.h"
|
||||
#include "llpumpio.h"
|
||||
#include "llthread.h"
|
||||
|
||||
//
|
||||
// constants
|
||||
@@ -104,51 +105,31 @@ void ll_debug_socket(const char* msg, apr_socket_t* apr_sock)
|
||||
///
|
||||
|
||||
// static
|
||||
LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
|
||||
LLSocket::ptr_t LLSocket::create(EType type, U16 port)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_TCP);
|
||||
LLSocket::ptr_t rv;
|
||||
apr_socket_t* socket = NULL;
|
||||
apr_pool_t* new_pool = NULL;
|
||||
apr_status_t status = APR_EGENERAL;
|
||||
|
||||
// create a pool for the socket
|
||||
status = apr_pool_create(&new_pool, pool);
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
if(new_pool) apr_pool_destroy(new_pool);
|
||||
return rv;
|
||||
}
|
||||
LLSocket::ptr_t rv(new LLSocket);
|
||||
|
||||
if(STREAM_TCP == type)
|
||||
{
|
||||
status = apr_socket_create(
|
||||
&socket,
|
||||
APR_INET,
|
||||
SOCK_STREAM,
|
||||
APR_PROTO_TCP,
|
||||
new_pool);
|
||||
status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_STREAM, APR_PROTO_TCP, rv->mPool());
|
||||
}
|
||||
else if(DATAGRAM_UDP == type)
|
||||
{
|
||||
status = apr_socket_create(
|
||||
&socket,
|
||||
APR_INET,
|
||||
SOCK_DGRAM,
|
||||
APR_PROTO_UDP,
|
||||
new_pool);
|
||||
status = apr_socket_create(&rv->mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, rv->mPool());
|
||||
}
|
||||
else
|
||||
{
|
||||
if(new_pool) apr_pool_destroy(new_pool);
|
||||
rv.reset();
|
||||
return rv;
|
||||
}
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
if(new_pool) apr_pool_destroy(new_pool);
|
||||
rv->mSocket = NULL;
|
||||
rv.reset();
|
||||
return rv;
|
||||
}
|
||||
rv = ptr_t(new LLSocket(socket, new_pool));
|
||||
if(port > 0)
|
||||
{
|
||||
apr_sockaddr_t* sa = NULL;
|
||||
@@ -158,7 +139,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
|
||||
APR_UNSPEC,
|
||||
port,
|
||||
0,
|
||||
new_pool);
|
||||
rv->mPool());
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
rv.reset();
|
||||
@@ -166,8 +147,8 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
|
||||
}
|
||||
// This allows us to reuse the address on quick down/up. This
|
||||
// is unlikely to create problems.
|
||||
ll_apr_warn_status(apr_socket_opt_set(socket, APR_SO_REUSEADDR, 1));
|
||||
status = apr_socket_bind(socket, sa);
|
||||
ll_apr_warn_status(apr_socket_opt_set(rv->mSocket, APR_SO_REUSEADDR, 1));
|
||||
status = apr_socket_bind(rv->mSocket, sa);
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
rv.reset();
|
||||
@@ -181,7 +162,7 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
|
||||
// to keep a queue of incoming connections for ACCEPT.
|
||||
lldebugs << "Setting listen state for socket." << llendl;
|
||||
status = apr_socket_listen(
|
||||
socket,
|
||||
rv->mSocket,
|
||||
LL_DEFAULT_LISTEN_BACKLOG);
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
@@ -202,21 +183,28 @@ LLSocket::ptr_t LLSocket::create(apr_pool_t* pool, EType type, U16 port)
|
||||
}
|
||||
|
||||
// static
|
||||
LLSocket::ptr_t LLSocket::create(apr_socket_t* socket, apr_pool_t* pool)
|
||||
LLSocket::ptr_t LLSocket::create(apr_status_t& status, LLSocket::ptr_t& listen_socket)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_TCP);
|
||||
LLSocket::ptr_t rv;
|
||||
if(!socket)
|
||||
if (!listen_socket->getSocket())
|
||||
{
|
||||
status = APR_ENOSOCKET;
|
||||
return LLSocket::ptr_t();
|
||||
}
|
||||
LLSocket::ptr_t rv(new LLSocket);
|
||||
lldebugs << "accepting socket" << llendl;
|
||||
status = apr_socket_accept(&rv->mSocket, listen_socket->getSocket(), rv->mPool());
|
||||
if (status != APR_SUCCESS)
|
||||
{
|
||||
rv->mSocket = NULL;
|
||||
rv.reset();
|
||||
return rv;
|
||||
}
|
||||
rv = ptr_t(new LLSocket(socket, pool));
|
||||
rv->mPort = PORT_EPHEMERAL;
|
||||
rv->setOptions();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
bool LLSocket::blockingConnect(const LLHost& host)
|
||||
{
|
||||
if(!mSocket) return false;
|
||||
@@ -229,7 +217,7 @@ bool LLSocket::blockingConnect(const LLHost& host)
|
||||
APR_UNSPEC,
|
||||
host.getPort(),
|
||||
0,
|
||||
mPool)))
|
||||
mPool())))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -240,13 +228,11 @@ bool LLSocket::blockingConnect(const LLHost& host)
|
||||
return true;
|
||||
}
|
||||
|
||||
LLSocket::LLSocket(apr_socket_t* socket, apr_pool_t* pool) :
|
||||
mSocket(socket),
|
||||
mPool(pool),
|
||||
LLSocket::LLSocket() :
|
||||
mSocket(NULL),
|
||||
mPool(LLThread::tldata().mRootPool),
|
||||
mPort(PORT_INVALID)
|
||||
{
|
||||
ll_debug_socket("Constructing wholely formed socket", mSocket);
|
||||
LLMemType m1(LLMemType::MTYPE_IO_TCP);
|
||||
}
|
||||
|
||||
LLSocket::~LLSocket()
|
||||
@@ -258,10 +244,6 @@ LLSocket::~LLSocket()
|
||||
ll_debug_socket("Destroying socket", mSocket);
|
||||
apr_socket_close(mSocket);
|
||||
}
|
||||
if(mPool)
|
||||
{
|
||||
apr_pool_destroy(mPool);
|
||||
}
|
||||
}
|
||||
|
||||
void LLSocket::setOptions()
|
||||
@@ -522,10 +504,8 @@ LLIOPipe::EStatus LLIOSocketWriter::process_impl(
|
||||
///
|
||||
|
||||
LLIOServerSocket::LLIOServerSocket(
|
||||
apr_pool_t* pool,
|
||||
LLIOServerSocket::socket_t listener,
|
||||
factory_t factory) :
|
||||
mPool(pool),
|
||||
mListenSocket(listener),
|
||||
mReactor(factory),
|
||||
mInitialized(false),
|
||||
@@ -585,21 +565,15 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
|
||||
lldebugs << "accepting socket" << llendl;
|
||||
|
||||
PUMP_DEBUG;
|
||||
apr_pool_t* new_pool = NULL;
|
||||
apr_status_t status = apr_pool_create(&new_pool, mPool);
|
||||
apr_socket_t* socket = NULL;
|
||||
status = apr_socket_accept(
|
||||
&socket,
|
||||
mListenSocket->getSocket(),
|
||||
new_pool);
|
||||
LLSocket::ptr_t llsocket(LLSocket::create(socket, new_pool));
|
||||
apr_status_t status;
|
||||
LLSocket::ptr_t llsocket(LLSocket::create(status, mListenSocket));
|
||||
//EStatus rv = STATUS_ERROR;
|
||||
if(llsocket)
|
||||
if(llsocket && status == APR_SUCCESS)
|
||||
{
|
||||
PUMP_DEBUG;
|
||||
|
||||
apr_sockaddr_t* remote_addr;
|
||||
apr_socket_addr_get(&remote_addr, APR_REMOTE, socket);
|
||||
apr_socket_addr_get(&remote_addr, APR_REMOTE, llsocket->getSocket());
|
||||
|
||||
char* remote_host_string;
|
||||
apr_sockaddr_ip_get(&remote_host_string, remote_addr);
|
||||
@@ -614,7 +588,6 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
|
||||
{
|
||||
chain.push_back(LLIOPipe::ptr_t(new LLIOSocketWriter(llsocket)));
|
||||
pump->addChain(chain, mResponseTimeout);
|
||||
status = STATUS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -623,7 +596,8 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "Unable to create linden socket." << llendl;
|
||||
char buf[256];
|
||||
llwarns << "Unable to accept linden socket: " << apr_strerror(status, buf, sizeof(buf)) << llendl;
|
||||
}
|
||||
|
||||
PUMP_DEBUG;
|
||||
@@ -636,11 +610,10 @@ LLIOPipe::EStatus LLIOServerSocket::process_impl(
|
||||
#if 0
|
||||
LLIODataSocket::LLIODataSocket(
|
||||
U16 suggested_port,
|
||||
U16 start_discovery_port,
|
||||
apr_pool_t* pool) :
|
||||
U16 start_discovery_port) :
|
||||
mSocket(NULL)
|
||||
{
|
||||
if(!pool || (PORT_INVALID == suggested_port)) return;
|
||||
if(PORT_INVALID == suggested_port) return;
|
||||
if(ll_apr_warn_status(apr_socket_create(&mSocket, APR_INET, SOCK_DGRAM, APR_PROTO_UDP, pool))) return;
|
||||
apr_sockaddr_t* sa = NULL;
|
||||
if(ll_apr_warn_status(apr_sockaddr_info_get(&sa, APR_ANYADDR, APR_UNSPEC, suggested_port, 0, pool))) return;
|
||||
|
||||
@@ -44,7 +44,6 @@
|
||||
*/
|
||||
|
||||
#include "lliopipe.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_network_io.h"
|
||||
#include "llchainio.h"
|
||||
|
||||
@@ -94,34 +93,22 @@ public:
|
||||
* socket. If you intend the socket to be known to external
|
||||
* clients without prior port notification, do not use
|
||||
* PORT_EPHEMERAL.
|
||||
* @param pool The apr pool to use. A child pool will be created
|
||||
* and associated with the socket.
|
||||
* @param type The type of socket to create
|
||||
* @param port The port for the socket
|
||||
* @return A valid socket shared pointer if the call worked.
|
||||
*/
|
||||
static ptr_t create(
|
||||
apr_pool_t* pool,
|
||||
EType type,
|
||||
U16 port = PORT_EPHEMERAL);
|
||||
|
||||
/**
|
||||
* @brief Create a LLSocket when you already have an apr socket.
|
||||
* @brief Create a LLSocket by accepting a connection from a listen socket.
|
||||
*
|
||||
* This method assumes an ephemeral port. This is typically used
|
||||
* by calls which spawn a socket such as a call to
|
||||
* <code>accept()</code> as in the server socket. This call should
|
||||
* not fail if you have a valid apr socket.
|
||||
* Because of the nature of how accept() works, you are expected
|
||||
* to create a new pool for the socket, use that pool for the
|
||||
* accept, and pass it in here where it will be bound with the
|
||||
* socket and destroyed at the same time.
|
||||
* @param socket The apr socket to use
|
||||
* @param pool The pool used to create the socket. *NOTE: The pool
|
||||
* passed in will be DESTROYED.
|
||||
* @param status Output. Status of the accept if a valid listen socket was passed.
|
||||
* @param listen_socket The listen socket to use.
|
||||
* @return A valid socket shared pointer if the call worked.
|
||||
*/
|
||||
static ptr_t create(apr_socket_t* socket, apr_pool_t* pool);
|
||||
static ptr_t create(apr_status_t& status, ptr_t& listen_socket);
|
||||
|
||||
/**
|
||||
* @brief Perform a blocking connect to a host. Do not use in production.
|
||||
@@ -156,7 +143,7 @@ protected:
|
||||
* @brief Protected constructor since should only make sockets
|
||||
* with one of the two <code>create()</code> calls.
|
||||
*/
|
||||
LLSocket(apr_socket_t* socket, apr_pool_t* pool);
|
||||
LLSocket(void);
|
||||
|
||||
/**
|
||||
* @brief Set default socket options.
|
||||
@@ -173,8 +160,8 @@ protected:
|
||||
// The apr socket.
|
||||
apr_socket_t* mSocket;
|
||||
|
||||
// our memory pool
|
||||
apr_pool_t* mPool;
|
||||
// Our memory pool.
|
||||
AIAPRPool mPool;
|
||||
|
||||
// The port if we know it.
|
||||
U16 mPort;
|
||||
@@ -299,7 +286,7 @@ class LLIOServerSocket : public LLIOPipe
|
||||
public:
|
||||
typedef LLSocket::ptr_t socket_t;
|
||||
typedef boost::shared_ptr<LLChainIOFactory> factory_t;
|
||||
LLIOServerSocket(apr_pool_t* pool, socket_t listener, factory_t reactor);
|
||||
LLIOServerSocket(socket_t listener, factory_t reactor);
|
||||
virtual ~LLIOServerSocket();
|
||||
|
||||
/**
|
||||
@@ -331,7 +318,6 @@ protected:
|
||||
//@}
|
||||
|
||||
protected:
|
||||
apr_pool_t* mPool;
|
||||
socket_t mListenSocket;
|
||||
factory_t mReactor;
|
||||
bool mInitialized;
|
||||
@@ -365,8 +351,7 @@ public:
|
||||
*/
|
||||
LLIODataSocket(
|
||||
U16 suggested_port,
|
||||
U16 start_discovery_port,
|
||||
apr_pool_t* pool);
|
||||
U16 start_discovery_port);
|
||||
virtual ~LLIODataSocket();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "llstring.h"
|
||||
#include "lluuid.h"
|
||||
#include "net.h"
|
||||
#include "aiaprpool.h"
|
||||
|
||||
//
|
||||
// constants
|
||||
@@ -63,7 +64,7 @@
|
||||
const size_t LL_MAX_KNOWN_GOOD_MAIL_SIZE = 4096;
|
||||
|
||||
static bool gMailEnabled = true;
|
||||
static apr_pool_t* gMailPool;
|
||||
static AIAPRPool gMailPool;
|
||||
static apr_sockaddr_t* gSockAddr;
|
||||
static apr_socket_t* gMailSocket;
|
||||
|
||||
@@ -88,7 +89,7 @@ bool connect_smtp()
|
||||
gSockAddr->sa.sin.sin_family,
|
||||
SOCK_STREAM,
|
||||
APR_PROTO_TCP,
|
||||
gMailPool);
|
||||
gMailPool());
|
||||
if(ll_apr_warn_status(status)) return false;
|
||||
status = apr_socket_connect(gMailSocket, gSockAddr);
|
||||
if(ll_apr_warn_status(status))
|
||||
@@ -145,19 +146,19 @@ BOOL LLMail::send(
|
||||
}
|
||||
|
||||
// static
|
||||
void LLMail::init(const std::string& hostname, apr_pool_t* pool)
|
||||
void LLMail::init(const std::string& hostname)
|
||||
{
|
||||
gMailSocket = NULL;
|
||||
if(hostname.empty() || !pool)
|
||||
if (hostname.empty())
|
||||
{
|
||||
gMailPool = NULL;
|
||||
gSockAddr = NULL;
|
||||
gMailPool.destroy();
|
||||
}
|
||||
else
|
||||
{
|
||||
gMailPool = pool;
|
||||
gMailPool.create();
|
||||
|
||||
// collect all the information into a socaddr sturcture. the
|
||||
// Collect all the information into a sockaddr structure. the
|
||||
// documentation is a bit unclear, but I either have to
|
||||
// specify APR_UNSPEC or not specify any flags. I am not sure
|
||||
// which option is better.
|
||||
@@ -167,7 +168,7 @@ void LLMail::init(const std::string& hostname, apr_pool_t* pool)
|
||||
APR_UNSPEC,
|
||||
25,
|
||||
APR_IPV4_ADDR_OK,
|
||||
gMailPool);
|
||||
gMailPool());
|
||||
ll_apr_warn_status(status);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,15 +33,13 @@
|
||||
#ifndef LL_LLMAIL_H
|
||||
#define LL_LLMAIL_H
|
||||
|
||||
typedef struct apr_pool_t apr_pool_t;
|
||||
|
||||
#include "llsd.h"
|
||||
|
||||
class LLMail
|
||||
{
|
||||
public:
|
||||
// if hostname is NULL, then the host is resolved as 'mail'
|
||||
static void init(const std::string& hostname, apr_pool_t* pool);
|
||||
static void init(const std::string& hostname);
|
||||
|
||||
// Allow all email transmission to be disabled/enabled.
|
||||
static void enable(bool mail_enabled);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "llmemtype.h"
|
||||
#include "llstl.h"
|
||||
#include "llstat.h"
|
||||
#include "llthread.h"
|
||||
#include "llfasttimer.h"
|
||||
#include <iterator> //VS2010
|
||||
|
||||
@@ -170,14 +171,12 @@ struct ll_delete_apr_pollset_fd_client_data
|
||||
/**
|
||||
* LLPumpIO
|
||||
*/
|
||||
LLPumpIO::LLPumpIO(apr_pool_t* pool) :
|
||||
LLPumpIO::LLPumpIO(void) :
|
||||
mState(LLPumpIO::NORMAL),
|
||||
mRebuildPollset(false),
|
||||
mPollset(NULL),
|
||||
mPollsetClientID(0),
|
||||
mNextLock(0),
|
||||
mPool(NULL),
|
||||
mCurrentPool(NULL),
|
||||
mCurrentPoolReallocCount(0),
|
||||
mChainsMutex(NULL),
|
||||
mCallbackMutex(NULL),
|
||||
@@ -186,21 +185,24 @@ LLPumpIO::LLPumpIO(apr_pool_t* pool) :
|
||||
mCurrentChain = mRunningChains.end();
|
||||
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
initialize(pool);
|
||||
initialize();
|
||||
}
|
||||
|
||||
LLPumpIO::~LLPumpIO()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
cleanup();
|
||||
}
|
||||
|
||||
bool LLPumpIO::prime(apr_pool_t* pool)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
cleanup();
|
||||
initialize(pool);
|
||||
return ((pool == NULL) ? false : true);
|
||||
#if LL_THREADS_APR
|
||||
if (mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
|
||||
if (mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
|
||||
#endif
|
||||
mChainsMutex = NULL;
|
||||
mCallbackMutex = NULL;
|
||||
if(mPollset)
|
||||
{
|
||||
// lldebugs << "cleaning up pollset" << llendl;
|
||||
apr_pollset_destroy(mPollset);
|
||||
mPollset = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool LLPumpIO::addChain(const chain_t& chain, F32 timeout)
|
||||
@@ -360,8 +362,7 @@ bool LLPumpIO::setConditional(LLIOPipe* pipe, const apr_pollfd_t* poll)
|
||||
{
|
||||
// each fd needs a pool to work with, so if one was
|
||||
// not specified, use this pool.
|
||||
// *FIX: Should it always be this pool?
|
||||
value.second.p = mPool;
|
||||
value.second.p = (*mCurrentChain).mDescriptorsPool->operator()();
|
||||
}
|
||||
value.second.client_data = new S32(++mPollsetClientID);
|
||||
(*mCurrentChain).mDescriptors.push_back(value);
|
||||
@@ -828,39 +829,15 @@ void LLPumpIO::control(LLPumpIO::EControl op)
|
||||
}
|
||||
}
|
||||
|
||||
void LLPumpIO::initialize(apr_pool_t* pool)
|
||||
void LLPumpIO::initialize(void)
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
if(!pool) return;
|
||||
mPool.create();
|
||||
#if LL_THREADS_APR
|
||||
// SJB: Windows defaults to NESTED and OSX defaults to UNNESTED, so use UNNESTED explicitly.
|
||||
apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, pool);
|
||||
apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, pool);
|
||||
apr_thread_mutex_create(&mChainsMutex, APR_THREAD_MUTEX_UNNESTED, mPool());
|
||||
apr_thread_mutex_create(&mCallbackMutex, APR_THREAD_MUTEX_UNNESTED, mPool());
|
||||
#endif
|
||||
mPool = pool;
|
||||
}
|
||||
|
||||
void LLPumpIO::cleanup()
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
#if LL_THREADS_APR
|
||||
if(mChainsMutex) apr_thread_mutex_destroy(mChainsMutex);
|
||||
if(mCallbackMutex) apr_thread_mutex_destroy(mCallbackMutex);
|
||||
#endif
|
||||
mChainsMutex = NULL;
|
||||
mCallbackMutex = NULL;
|
||||
if(mPollset)
|
||||
{
|
||||
// lldebugs << "cleaning up pollset" << llendl;
|
||||
apr_pollset_destroy(mPollset);
|
||||
mPollset = NULL;
|
||||
}
|
||||
if(mCurrentPool)
|
||||
{
|
||||
apr_pool_destroy(mCurrentPool);
|
||||
mCurrentPool = NULL;
|
||||
}
|
||||
mPool = NULL;
|
||||
}
|
||||
|
||||
void LLPumpIO::rebuildPollset()
|
||||
@@ -888,21 +865,19 @@ void LLPumpIO::rebuildPollset()
|
||||
if(mCurrentPool
|
||||
&& (0 == (++mCurrentPoolReallocCount % POLLSET_POOL_RECYCLE_COUNT)))
|
||||
{
|
||||
apr_pool_destroy(mCurrentPool);
|
||||
mCurrentPool = NULL;
|
||||
mCurrentPool.destroy();
|
||||
mCurrentPoolReallocCount = 0;
|
||||
}
|
||||
if(!mCurrentPool)
|
||||
{
|
||||
apr_status_t status = apr_pool_create(&mCurrentPool, mPool);
|
||||
(void)ll_apr_warn_status(status);
|
||||
mCurrentPool.create(mPool);
|
||||
}
|
||||
|
||||
// add all of the file descriptors
|
||||
run_it = mRunningChains.begin();
|
||||
LLChainInfo::conditionals_t::iterator fd_it;
|
||||
LLChainInfo::conditionals_t::iterator fd_end;
|
||||
apr_pollset_create(&mPollset, size, mCurrentPool, 0);
|
||||
apr_pollset_create(&mPollset, size, mCurrentPool(), 0);
|
||||
for(; run_it != run_end; ++run_it)
|
||||
{
|
||||
fd_it = (*run_it).mDescriptors.begin();
|
||||
@@ -1160,7 +1135,8 @@ bool LLPumpIO::handleChainError(
|
||||
LLPumpIO::LLChainInfo::LLChainInfo() :
|
||||
mInit(false),
|
||||
mLock(0),
|
||||
mEOS(false)
|
||||
mEOS(false),
|
||||
mDescriptorsPool(new AIAPRPool(LLThread::tldata().mRootPool))
|
||||
{
|
||||
LLMemType m1(LLMemType::MTYPE_IO_PUMP);
|
||||
mTimer.setTimerExpirySec(DEFAULT_CHAIN_EXPIRY_SECS);
|
||||
|
||||
@@ -36,11 +36,12 @@
|
||||
#define LL_LLPUMPIO_H
|
||||
|
||||
#include <set>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#if LL_LINUX // needed for PATH_MAX in APR.
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include "apr_pools.h"
|
||||
#include "aiaprpool.h"
|
||||
#include "llbuffer.h"
|
||||
#include "llframetimer.h"
|
||||
#include "lliopipe.h"
|
||||
@@ -64,9 +65,8 @@ extern const F32 NEVER_CHAIN_EXPIRY_SECS;
|
||||
* <code>pump()</code> on a thread used for IO and call
|
||||
* <code>respond()</code> on a thread that is expected to do higher
|
||||
* level processing. You can call almost any other method from any
|
||||
* thread - see notes for each method for details. In order for the
|
||||
* threading abstraction to work, you need to call <code>prime()</code>
|
||||
* with a valid apr pool.
|
||||
* thread - see notes for each method for details.
|
||||
*
|
||||
* A pump instance manages much of the state for the pipe, including
|
||||
* the list of pipes in the chain, the channel for each element in the
|
||||
* chain, the buffer, and if any pipe has marked the stream or process
|
||||
@@ -85,24 +85,13 @@ public:
|
||||
/**
|
||||
* @brief Constructor.
|
||||
*/
|
||||
LLPumpIO(apr_pool_t* pool);
|
||||
LLPumpIO(void);
|
||||
|
||||
/**
|
||||
* @brief Destructor.
|
||||
*/
|
||||
~LLPumpIO();
|
||||
|
||||
/**
|
||||
* @brief Prepare this pump for usage.
|
||||
*
|
||||
* If you fail to call this method prior to use, the pump will
|
||||
* try to work, but will not come with any thread locking
|
||||
* mechanisms.
|
||||
* @param pool The apr pool to use.
|
||||
* @return Returns true if the pump is primed.
|
||||
*/
|
||||
bool prime(apr_pool_t* pool);
|
||||
|
||||
/**
|
||||
* @brief Typedef for having a chain of pipes.
|
||||
*/
|
||||
@@ -374,6 +363,7 @@ protected:
|
||||
typedef std::pair<LLIOPipe::ptr_t, apr_pollfd_t> pipe_conditional_t;
|
||||
typedef std::vector<pipe_conditional_t> conditionals_t;
|
||||
conditionals_t mDescriptors;
|
||||
boost::shared_ptr<AIAPRPool> mDescriptorsPool;
|
||||
};
|
||||
|
||||
// All the running chains & info
|
||||
@@ -392,9 +382,9 @@ protected:
|
||||
callbacks_t mPendingCallbacks;
|
||||
callbacks_t mCallbacks;
|
||||
|
||||
// memory allocator for pollsets & mutexes.
|
||||
apr_pool_t* mPool;
|
||||
apr_pool_t* mCurrentPool;
|
||||
// Memory pool for pollsets & mutexes.
|
||||
AIAPRPool mPool;
|
||||
AIAPRPool mCurrentPool;
|
||||
S32 mCurrentPoolReallocCount;
|
||||
|
||||
#if LL_THREADS_APR
|
||||
@@ -406,8 +396,7 @@ protected:
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void initialize(apr_pool_t* pool);
|
||||
void cleanup();
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* @brief Given the internal state of the chains, rebuild the pollset
|
||||
|
||||
0
indra/llmessage/llsdmessagebuilder.cpp
Executable file → Normal file
0
indra/llmessage/llsdmessagebuilder.cpp
Executable file → Normal file
0
indra/llmessage/llsdmessagebuilder.h
Executable file → Normal file
0
indra/llmessage/llsdmessagebuilder.h
Executable file → Normal file
0
indra/llmessage/llsdmessagereader.cpp
Executable file → Normal file
0
indra/llmessage/llsdmessagereader.cpp
Executable file → Normal file
0
indra/llmessage/llsdmessagereader.h
Executable file → Normal file
0
indra/llmessage/llsdmessagereader.h
Executable file → Normal file
@@ -45,6 +45,7 @@
|
||||
#include "llstring.h"
|
||||
#include "apr_env.h"
|
||||
#include "llapr.h"
|
||||
#include "llscopedvolatileaprpool.h"
|
||||
static const U32 HTTP_STATUS_PIPE_ERROR = 499;
|
||||
|
||||
/**
|
||||
@@ -161,27 +162,31 @@ void LLURLRequest::setCallback(LLURLRequestComplete* callback)
|
||||
// is called with use_proxy = FALSE
|
||||
void LLURLRequest::useProxy(bool use_proxy)
|
||||
{
|
||||
static char *env_proxy;
|
||||
static std::string env_proxy;
|
||||
|
||||
if (use_proxy && (env_proxy == NULL))
|
||||
if (use_proxy && env_proxy.empty())
|
||||
{
|
||||
apr_status_t status;
|
||||
LLAPRPool pool;
|
||||
status = apr_env_get(&env_proxy, "ALL_PROXY", pool.getAPRPool());
|
||||
char* env_proxy_str;
|
||||
LLScopedVolatileAPRPool scoped_pool;
|
||||
apr_status_t status = apr_env_get(&env_proxy_str, "ALL_PROXY", scoped_pool);
|
||||
if (status != APR_SUCCESS)
|
||||
{
|
||||
status = apr_env_get(&env_proxy, "http_proxy", pool.getAPRPool());
|
||||
status = apr_env_get(&env_proxy_str, "http_proxy", scoped_pool);
|
||||
}
|
||||
if (status != APR_SUCCESS)
|
||||
{
|
||||
use_proxy = FALSE;
|
||||
use_proxy = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// env_proxy_str is stored in the scoped_pool, so we have to make a copy.
|
||||
env_proxy = env_proxy_str;
|
||||
}
|
||||
}
|
||||
|
||||
lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = \"" << env_proxy << "\"" << llendl;
|
||||
|
||||
lldebugs << "use_proxy = " << (use_proxy?'Y':'N') << ", env_proxy = " << (env_proxy ? env_proxy : "(null)") << llendl;
|
||||
|
||||
if (env_proxy && use_proxy)
|
||||
if (use_proxy)
|
||||
{
|
||||
mDetail->mCurlRequest->setoptString(CURLOPT_PROXY, env_proxy);
|
||||
}
|
||||
|
||||
@@ -107,8 +107,10 @@ std::string get_shared_secret();
|
||||
class LLMessagePollInfo
|
||||
{
|
||||
public:
|
||||
LLMessagePollInfo(void) : mPool(LLThread::tldata().mRootPool) { }
|
||||
apr_socket_t *mAPRSocketp;
|
||||
apr_pollfd_t mPollFD;
|
||||
AIAPRPool mPool;
|
||||
};
|
||||
|
||||
namespace
|
||||
@@ -297,20 +299,13 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port,
|
||||
}
|
||||
// LL_DEBUGS("Messaging") << << "*** port: " << mPort << llendl;
|
||||
|
||||
//
|
||||
// Create the data structure that we can poll on
|
||||
//
|
||||
if (!gAPRPoolp)
|
||||
{
|
||||
LL_ERRS("Messaging") << "No APR pool before message system initialization!" << llendl;
|
||||
ll_init_apr();
|
||||
}
|
||||
apr_socket_t *aprSocketp = NULL;
|
||||
apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, gAPRPoolp);
|
||||
|
||||
mPollInfop = new LLMessagePollInfo;
|
||||
|
||||
apr_socket_t *aprSocketp = NULL;
|
||||
apr_os_sock_put(&aprSocketp, (apr_os_sock_t*)&mSocket, mPollInfop->mPool());
|
||||
|
||||
mPollInfop->mAPRSocketp = aprSocketp;
|
||||
mPollInfop->mPollFD.p = gAPRPoolp;
|
||||
mPollInfop->mPollFD.p = mPollInfop->mPool();
|
||||
mPollInfop->mPollFD.desc_type = APR_POLL_SOCKET;
|
||||
mPollInfop->mPollFD.reqevents = APR_POLLIN;
|
||||
mPollInfop->mPollFD.rtnevents = 0;
|
||||
|
||||
0
indra/llplugin/llpluginclassmedia.cpp
Executable file → Normal file
0
indra/llplugin/llpluginclassmedia.cpp
Executable file → Normal file
0
indra/llplugin/llpluginclassmedia.h
Executable file → Normal file
0
indra/llplugin/llpluginclassmedia.h
Executable file → Normal file
0
indra/llplugin/llpluginclassmediaowner.h
Executable file → Normal file
0
indra/llplugin/llpluginclassmediaowner.h
Executable file → Normal file
5
indra/llplugin/llplugininstance.cpp
Executable file → Normal file
5
indra/llplugin/llplugininstance.cpp
Executable file → Normal file
@@ -36,8 +36,7 @@
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llplugininstance.h"
|
||||
|
||||
#include "llapr.h"
|
||||
#include "aiaprpool.h"
|
||||
|
||||
/** Virtual destructor. */
|
||||
LLPluginInstanceMessageListener::~LLPluginInstanceMessageListener()
|
||||
@@ -86,7 +85,7 @@ int LLPluginInstance::load(std::string &plugin_file)
|
||||
|
||||
int result = apr_dso_load(&mDSOHandle,
|
||||
plugin_file.c_str(),
|
||||
gAPRPoolp);
|
||||
AIAPRRootPool::get()());
|
||||
if(result != APR_SUCCESS)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
0
indra/llplugin/llplugininstance.h
Executable file → Normal file
0
indra/llplugin/llplugininstance.h
Executable file → Normal file
0
indra/llplugin/llpluginmessage.cpp
Executable file → Normal file
0
indra/llplugin/llpluginmessage.cpp
Executable file → Normal file
0
indra/llplugin/llpluginmessage.h
Executable file → Normal file
0
indra/llplugin/llpluginmessage.h
Executable file → Normal file
0
indra/llplugin/llpluginmessageclasses.h
Executable file → Normal file
0
indra/llplugin/llpluginmessageclasses.h
Executable file → Normal file
2
indra/llplugin/llpluginmessagepipe.cpp
Executable file → Normal file
2
indra/llplugin/llpluginmessagepipe.cpp
Executable file → Normal file
@@ -99,8 +99,6 @@ void LLPluginMessagePipeOwner::killMessagePipe(void)
|
||||
}
|
||||
|
||||
LLPluginMessagePipe::LLPluginMessagePipe(LLPluginMessagePipeOwner *owner, LLSocket::ptr_t socket):
|
||||
mInputMutex(gAPRPoolp),
|
||||
mOutputMutex(gAPRPoolp),
|
||||
mOwner(owner),
|
||||
mSocket(socket)
|
||||
{
|
||||
|
||||
0
indra/llplugin/llpluginmessagepipe.h
Executable file → Normal file
0
indra/llplugin/llpluginmessagepipe.h
Executable file → Normal file
2
indra/llplugin/llpluginprocesschild.cpp
Executable file → Normal file
2
indra/llplugin/llpluginprocesschild.cpp
Executable file → Normal file
@@ -47,7 +47,7 @@ LLPluginProcessChild::LLPluginProcessChild()
|
||||
{
|
||||
mState = STATE_UNINITIALIZED;
|
||||
mInstance = NULL;
|
||||
mSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
|
||||
mSocket = LLSocket::create(LLSocket::STREAM_TCP);
|
||||
mSleepTime = PLUGIN_IDLE_SECONDS; // default: send idle messages at 100Hz
|
||||
mCPUElapsed = 0.0f;
|
||||
mBlockingRequest = false;
|
||||
|
||||
0
indra/llplugin/llpluginprocesschild.h
Executable file → Normal file
0
indra/llplugin/llpluginprocesschild.h
Executable file → Normal file
55
indra/llplugin/llpluginprocessparent.cpp
Executable file → Normal file
55
indra/llplugin/llpluginprocessparent.cpp
Executable file → Normal file
@@ -49,6 +49,7 @@ LLPluginProcessParentOwner::~LLPluginProcessParentOwner()
|
||||
|
||||
bool LLPluginProcessParent::sUseReadThread = false;
|
||||
apr_pollset_t *LLPluginProcessParent::sPollSet = NULL;
|
||||
AIAPRPool LLPluginProcessParent::sPollSetPool;
|
||||
bool LLPluginProcessParent::sPollsetNeedsRebuild = false;
|
||||
LLMutex *LLPluginProcessParent::sInstancesMutex;
|
||||
std::list<LLPluginProcessParent*> LLPluginProcessParent::sInstances;
|
||||
@@ -59,7 +60,7 @@ class LLPluginProcessParentPollThread: public LLThread
|
||||
{
|
||||
public:
|
||||
LLPluginProcessParentPollThread() :
|
||||
LLThread("LLPluginProcessParentPollThread", gAPRPoolp)
|
||||
LLThread("LLPluginProcessParentPollThread")
|
||||
{
|
||||
}
|
||||
protected:
|
||||
@@ -84,12 +85,11 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
|
||||
mIncomingQueueMutex(gAPRPoolp)
|
||||
LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
|
||||
{
|
||||
if(!sInstancesMutex)
|
||||
{
|
||||
sInstancesMutex = new LLMutex(gAPRPoolp);
|
||||
sInstancesMutex = new LLMutex;
|
||||
}
|
||||
|
||||
mOwner = owner;
|
||||
@@ -102,6 +102,7 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner):
|
||||
mBlocked = false;
|
||||
mPolledInput = false;
|
||||
mPollFD.client_data = NULL;
|
||||
mPollFDPool.create();
|
||||
|
||||
mPluginLaunchTimeout = 60.0f;
|
||||
mPluginLockupTimeout = 15.0f;
|
||||
@@ -177,44 +178,28 @@ void LLPluginProcessParent::init(const std::string &launcher_filename, const std
|
||||
bool LLPluginProcessParent::accept()
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
apr_status_t status = APR_EGENERAL;
|
||||
apr_socket_t *new_socket = NULL;
|
||||
|
||||
status = apr_socket_accept(
|
||||
&new_socket,
|
||||
mListenSocket->getSocket(),
|
||||
gAPRPoolp);
|
||||
|
||||
mSocket = LLSocket::create(status, mListenSocket);
|
||||
|
||||
if(status == APR_SUCCESS)
|
||||
{
|
||||
// llinfos << "SUCCESS" << llendl;
|
||||
// Success. Create a message pipe on the new socket
|
||||
|
||||
// we MUST create a new pool for the LLSocket, since it will take ownership of it and delete it in its destructor!
|
||||
apr_pool_t* new_pool = NULL;
|
||||
status = apr_pool_create(&new_pool, gAPRPoolp);
|
||||
|
||||
mSocket = LLSocket::create(new_socket, new_pool);
|
||||
new LLPluginMessagePipe(this, mSocket);
|
||||
|
||||
result = true;
|
||||
}
|
||||
else if(APR_STATUS_IS_EAGAIN(status))
|
||||
{
|
||||
// llinfos << "EAGAIN" << llendl;
|
||||
|
||||
// No incoming connections. This is not an error.
|
||||
status = APR_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
// llinfos << "Error:" << llendl;
|
||||
ll_apr_warn_status(status);
|
||||
|
||||
// Some other error.
|
||||
errorState();
|
||||
mSocket.reset();
|
||||
// EAGAIN means "No incoming connections". This is not an error.
|
||||
if (!APR_STATUS_IS_EAGAIN(status))
|
||||
{
|
||||
// Some other error.
|
||||
ll_apr_warn_status(status);
|
||||
errorState();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -283,7 +268,7 @@ void LLPluginProcessParent::idle(void)
|
||||
|
||||
apr_status_t status = APR_SUCCESS;
|
||||
apr_sockaddr_t* addr = NULL;
|
||||
mListenSocket = LLSocket::create(gAPRPoolp, LLSocket::STREAM_TCP);
|
||||
mListenSocket = LLSocket::create(LLSocket::STREAM_TCP);
|
||||
mBoundPort = 0;
|
||||
|
||||
// This code is based on parts of LLSocket::create() in lliosocket.cpp.
|
||||
@@ -294,7 +279,7 @@ void LLPluginProcessParent::idle(void)
|
||||
APR_INET,
|
||||
0, // port 0 = ephemeral ("find me a port")
|
||||
0,
|
||||
gAPRPoolp);
|
||||
AIAPRRootPool::get()());
|
||||
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
@@ -617,7 +602,8 @@ void LLPluginProcessParent::setMessagePipe(LLPluginMessagePipe *message_pipe)
|
||||
if(message_pipe != NULL)
|
||||
{
|
||||
// Set up the apr_pollfd_t
|
||||
mPollFD.p = gAPRPoolp;
|
||||
|
||||
mPollFD.p = mPollFDPool();
|
||||
mPollFD.desc_type = APR_POLL_SOCKET;
|
||||
mPollFD.reqevents = APR_POLLIN|APR_POLLERR|APR_POLLHUP;
|
||||
mPollFD.rtnevents = 0;
|
||||
@@ -664,6 +650,7 @@ void LLPluginProcessParent::updatePollset()
|
||||
// delete the existing pollset.
|
||||
apr_pollset_destroy(sPollSet);
|
||||
sPollSet = NULL;
|
||||
sPollSetPool.destroy();
|
||||
}
|
||||
|
||||
std::list<LLPluginProcessParent*>::iterator iter;
|
||||
@@ -686,12 +673,14 @@ void LLPluginProcessParent::updatePollset()
|
||||
{
|
||||
#ifdef APR_POLLSET_NOCOPY
|
||||
// The pollset doesn't exist yet. Create it now.
|
||||
apr_status_t status = apr_pollset_create(&sPollSet, count, gAPRPoolp, APR_POLLSET_NOCOPY);
|
||||
sPollSetPool.create();
|
||||
apr_status_t status = apr_pollset_create(&sPollSet, count, sPollSetPool(), APR_POLLSET_NOCOPY);
|
||||
if(status != APR_SUCCESS)
|
||||
{
|
||||
#endif // APR_POLLSET_NOCOPY
|
||||
LL_WARNS("PluginPoll") << "Couldn't create pollset. Falling back to non-pollset mode." << LL_ENDL;
|
||||
sPollSet = NULL;
|
||||
sPollSetPool.destroy();
|
||||
#ifdef APR_POLLSET_NOCOPY
|
||||
}
|
||||
else
|
||||
|
||||
2
indra/llplugin/llpluginprocessparent.h
Executable file → Normal file
2
indra/llplugin/llpluginprocessparent.h
Executable file → Normal file
@@ -186,7 +186,9 @@ private:
|
||||
|
||||
static bool sUseReadThread;
|
||||
apr_pollfd_t mPollFD;
|
||||
AIAPRPool mPollFDPool;
|
||||
static apr_pollset_t *sPollSet;
|
||||
static AIAPRPool sPollSetPool;
|
||||
static bool sPollsetNeedsRebuild;
|
||||
static LLMutex *sInstancesMutex;
|
||||
static std::list<LLPluginProcessParent*> sInstances;
|
||||
|
||||
9
indra/llplugin/llpluginsharedmemory.cpp
Executable file → Normal file
9
indra/llplugin/llpluginsharedmemory.cpp
Executable file → Normal file
@@ -201,7 +201,8 @@ bool LLPluginSharedMemory::create(size_t size)
|
||||
mName += createName();
|
||||
mSize = size;
|
||||
|
||||
apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), gAPRPoolp );
|
||||
mPool.create();
|
||||
apr_status_t status = apr_shm_create( &(mImpl->mAprSharedMemory), mSize, mName.c_str(), mPool());
|
||||
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
@@ -224,7 +225,7 @@ bool LLPluginSharedMemory::destroy(void)
|
||||
}
|
||||
mImpl->mAprSharedMemory = NULL;
|
||||
}
|
||||
|
||||
mPool.destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -233,7 +234,8 @@ bool LLPluginSharedMemory::attach(const std::string &name, size_t size)
|
||||
mName = name;
|
||||
mSize = size;
|
||||
|
||||
apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), gAPRPoolp );
|
||||
mPool.create();
|
||||
apr_status_t status = apr_shm_attach( &(mImpl->mAprSharedMemory), mName.c_str(), mPool() );
|
||||
|
||||
if(ll_apr_warn_status(status))
|
||||
{
|
||||
@@ -255,6 +257,7 @@ bool LLPluginSharedMemory::detach(void)
|
||||
}
|
||||
mImpl->mAprSharedMemory = NULL;
|
||||
}
|
||||
mPool.destroy();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
3
indra/llplugin/llpluginsharedmemory.h
Executable file → Normal file
3
indra/llplugin/llpluginsharedmemory.h
Executable file → Normal file
@@ -35,6 +35,8 @@
|
||||
#ifndef LL_LLPLUGINSHAREDMEMORY_H
|
||||
#define LL_LLPLUGINSHAREDMEMORY_H
|
||||
|
||||
#include "aiaprpool.h"
|
||||
|
||||
class LLPluginSharedMemoryPlatformImpl;
|
||||
|
||||
/**
|
||||
@@ -115,6 +117,7 @@ private:
|
||||
bool close(void);
|
||||
bool unlink(void);
|
||||
|
||||
AIAPRPool mPool;
|
||||
std::string mName;
|
||||
size_t mSize;
|
||||
void *mMappedAddress;
|
||||
|
||||
4
indra/llplugin/slplugin/slplugin.cpp
Executable file → Normal file
4
indra/llplugin/slplugin/slplugin.cpp
Executable file → Normal file
@@ -183,8 +183,6 @@ int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdL
|
||||
int main(int argc, char **argv)
|
||||
#endif
|
||||
{
|
||||
ll_init_apr();
|
||||
|
||||
// Set up llerror logging
|
||||
{
|
||||
LLError::initForApplication(".");
|
||||
@@ -400,8 +398,6 @@ int main(int argc, char **argv)
|
||||
|
||||
delete plugin;
|
||||
|
||||
ll_cleanup_apr();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
0
indra/llui/llmemberlistener.h
Executable file → Normal file
0
indra/llui/llmemberlistener.h
Executable file → Normal file
@@ -1194,13 +1194,13 @@ void replaceSubstitutionStrings(LLXMLNodePtr node, StringMap& replacements)
|
||||
if (found != replacements.end())
|
||||
{
|
||||
replacement = found->second;
|
||||
//llwarns << "replaceSubstituionStrings: value: " << value << " repl: " << replacement << llendl;
|
||||
//llinfos << "replaceSubstitutionStrings: value: \"" << value << "\" repl: \"" << replacement << "\"." << llendl;
|
||||
|
||||
it->second->setValue(replacement);
|
||||
}
|
||||
else
|
||||
{
|
||||
llwarns << "replaceSubstituionStrings FAILURE: value: " << value << " repl: " << replacement << llendl;
|
||||
llwarns << "replaceSubstitutionStrings FAILURE: could not find replacement \"" << value << "\"." << llendl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include "llimagegl.h"
|
||||
#include "llwindow.h"
|
||||
#include "lltextparser.h"
|
||||
#include "lldir.h"
|
||||
#include <queue>
|
||||
#include "llmenugl.h"
|
||||
#include "../newview/lgghunspell_wrapper.h"
|
||||
@@ -4004,7 +4005,10 @@ void LLTextEditor::appendColoredText(const std::string &new_text,
|
||||
const std::string& font_name)
|
||||
{
|
||||
LLColor4 lcolor=color;
|
||||
if (mParseHighlights)
|
||||
// If LindenUserDir is empty then we didn't login yet.
|
||||
// In that case we can't instantiate LLTextParser, which
|
||||
// is initialized per user.
|
||||
if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty())
|
||||
{
|
||||
LLTextParser* highlight = LLTextParser::getInstance();
|
||||
highlight->parseFullLineHighlights(new_text, &lcolor);
|
||||
@@ -4082,7 +4086,10 @@ void LLTextEditor::appendHighlightedText(const std::string &new_text,
|
||||
S32 highlight_part,
|
||||
LLStyleSP stylep)
|
||||
{
|
||||
if (mParseHighlights)
|
||||
// If LindenUserDir is empty then we didn't login yet.
|
||||
// In that case we can't instantiate LLTextParser, which
|
||||
// is initialized per user.
|
||||
if (mParseHighlights && !gDirUtilp->getLindenUserDir(true).empty())
|
||||
{
|
||||
LLTextParser* highlight = LLTextParser::getInstance();
|
||||
|
||||
|
||||
0
indra/llui/lluistring.cpp
Executable file → Normal file
0
indra/llui/lluistring.cpp
Executable file → Normal file
0
indra/llui/lluistring.h
Executable file → Normal file
0
indra/llui/lluistring.h
Executable file → Normal file
@@ -193,8 +193,9 @@ const std::string &LLDir::getOSUserAppDir() const
|
||||
return mOSUserAppDir;
|
||||
}
|
||||
|
||||
const std::string &LLDir::getLindenUserDir() const
|
||||
const std::string &LLDir::getLindenUserDir(bool empty_ok) const
|
||||
{
|
||||
llassert(empty_ok || !mLindenUserDir.empty());
|
||||
return mLindenUserDir;
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ class LLDir
|
||||
const std::string &getAppRODataDir() const; // Location of read-only data files
|
||||
const std::string &getOSUserDir() const; // Location of the os-specific user dir
|
||||
const std::string &getOSUserAppDir() const; // Location of the os-specific user app dir
|
||||
const std::string &getLindenUserDir() const; // Location of the Linden user dir.
|
||||
const std::string &getLindenUserDir(bool empty_ok = false) const; // Location of the Linden user dir.
|
||||
const std::string &getChatLogsDir() const; // Location of the chat logs dir.
|
||||
const std::string &getPerAccountChatLogsDir() const; // Location of the per account chat logs dir.
|
||||
const std::string &getTempDir() const; // Common temporary directory
|
||||
|
||||
@@ -97,7 +97,7 @@ LLDir_Linux::LLDir_Linux()
|
||||
mAppRODataDir = tmp_str;
|
||||
mOSUserDir = getCurrentUserHome(tmp_str);
|
||||
mOSUserAppDir = "";
|
||||
mLindenUserDir = tmp_str;
|
||||
mLindenUserDir = "";
|
||||
|
||||
char path [32]; /* Flawfinder: ignore */
|
||||
|
||||
|
||||
@@ -100,7 +100,7 @@ LLDir_Solaris::LLDir_Solaris()
|
||||
mAppRODataDir = strdup(tmp_str);
|
||||
mOSUserDir = getCurrentUserHome(tmp_str);
|
||||
mOSUserAppDir = "";
|
||||
mLindenUserDir = tmp_str;
|
||||
mLindenUserDir = "";
|
||||
|
||||
char path [LL_MAX_PATH]; /* Flawfinder: ignore */
|
||||
|
||||
|
||||
0
indra/llvfs/llpidlock.cpp
Executable file → Normal file
0
indra/llvfs/llpidlock.cpp
Executable file → Normal file
0
indra/llvfs/llpidlock.h
Executable file → Normal file
0
indra/llvfs/llpidlock.h
Executable file → Normal file
@@ -219,7 +219,7 @@ const S32 LLVFSFileBlock::SERIAL_SIZE = 34;
|
||||
LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename, const BOOL read_only, const U32 presize, const BOOL remove_after_crash)
|
||||
: mRemoveAfterCrash(remove_after_crash)
|
||||
{
|
||||
mDataMutex = new LLMutex(0);
|
||||
mDataMutex = new LLMutex;
|
||||
|
||||
S32 i;
|
||||
for (i = 0; i < VFSLOCK_COUNT; i++)
|
||||
@@ -566,8 +566,9 @@ LLVFS::LLVFS(const std::string& index_filename, const std::string& data_filename
|
||||
}
|
||||
}
|
||||
|
||||
LL_WARNS("VFS") << "Using index file " << mIndexFilename << LL_ENDL;
|
||||
LL_WARNS("VFS") << "Using data file " << mDataFilename << LL_ENDL;
|
||||
// Success!
|
||||
LL_INFOS("VFS") << "Using index file " << mIndexFilename << LL_ENDL;
|
||||
LL_INFOS("VFS") << "Using data file " << mDataFilename << LL_ENDL;
|
||||
|
||||
mValid = VFSVALID_OK;
|
||||
}
|
||||
|
||||
0
indra/llwindow/glh/glh_linear.h
Executable file → Normal file
0
indra/llwindow/glh/glh_linear.h
Executable file → Normal file
@@ -66,7 +66,20 @@ const S32 CURRENT_VERSION = 101;
|
||||
//So, a global it is!
|
||||
bool gCOAEnabled = false;
|
||||
|
||||
LLControlVariable *LLControlVariable::getCOAActive()
|
||||
LLControlVariable* LLControlVariable::getCOAActive()
|
||||
{
|
||||
//if no coa connection, return 'this'
|
||||
//if per account is ON and this IS a parent, return child var
|
||||
//if per account is ON and this IS NOT a parent, return 'this'
|
||||
//if per account is OFF and this IS NOT a parent, return parent var
|
||||
//if per account is OFF and this IS a parent, return 'this'
|
||||
if(getCOAConnection() && gCOAEnabled == isCOAParent())
|
||||
return getCOAConnection();
|
||||
else
|
||||
return this;
|
||||
}
|
||||
|
||||
LLControlVariable const* LLControlVariable::getCOAActive() const
|
||||
{
|
||||
//if no coa connection, return 'this'
|
||||
//if per account is ON and this IS a parent, return child var
|
||||
@@ -282,11 +295,9 @@ LLSD LLControlVariable::getSaveValue() const
|
||||
|
||||
#if PROF_CTRL_CALLS
|
||||
std::vector<std::pair<std::string, U32>> gSettingsCallMap;
|
||||
#endif //PROF_CTRL_CALLS
|
||||
LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
|
||||
|
||||
static update_gSettingsCallMap(ctrl_name_table_t::const_iterator const& iter)
|
||||
{
|
||||
ctrl_name_table_t::iterator iter = mNameTable.find(name);
|
||||
#if PROF_CTRL_CALLS
|
||||
if(iter != mNameTable.end())
|
||||
{
|
||||
std::vector<std::pair<std::string, U32>>::iterator iter2 = gSettingsCallMap.begin();
|
||||
@@ -302,13 +313,32 @@ LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)
|
||||
if(iter2 == gSettingsCallMap.end())
|
||||
gSettingsCallMap.push_back(std::pair<std::string, U32>(name.c_str(),1));
|
||||
}
|
||||
}
|
||||
#endif //PROF_CTRL_CALLS
|
||||
|
||||
LLControlVariable* LLControlGroup::getControl(std::string const& name)
|
||||
{
|
||||
ctrl_name_table_t::iterator iter = mNameTable.find(name);
|
||||
#if PROF_CTRL_CALLS
|
||||
update_gSettingsCallMap(iter);
|
||||
#endif //PROF_CTRL_CALLS
|
||||
if(iter != mNameTable.end())
|
||||
return iter->second->getCOAActive();
|
||||
else
|
||||
return LLPointer<LLControlVariable>();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LLControlVariable const* LLControlGroup::getControl(std::string const& name) const
|
||||
{
|
||||
ctrl_name_table_t::const_iterator iter = mNameTable.find(name);
|
||||
#if PROF_CTRL_CALLS
|
||||
update_gSettingsCallMap(iter);
|
||||
#endif //PROF_CTRL_CALLS
|
||||
if(iter != mNameTable.end())
|
||||
return iter->second->getCOAActive();
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -502,9 +532,9 @@ std::string LLControlGroup::findString(const std::string& name)
|
||||
return LLStringUtil::null;
|
||||
}
|
||||
|
||||
std::string LLControlGroup::getString(const std::string& name)
|
||||
std::string LLControlGroup::getString(const std::string& name) const
|
||||
{
|
||||
LLControlVariable* control = getControl(name);
|
||||
LLControlVariable const* control = getControl(name);
|
||||
|
||||
if (control && control->isType(TYPE_STRING))
|
||||
return control->get().asString();
|
||||
@@ -649,9 +679,9 @@ LLSD LLControlGroup::getLLSD(const std::string& name)
|
||||
return LLSD();
|
||||
}
|
||||
|
||||
BOOL LLControlGroup::controlExists(const std::string& name)
|
||||
BOOL LLControlGroup::controlExists(const std::string& name) const
|
||||
{
|
||||
ctrl_name_table_t::iterator iter = mNameTable.find(name);
|
||||
ctrl_name_table_t::const_iterator iter = mNameTable.find(name);
|
||||
return iter != mNameTable.end();
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
const std::string& getComment() const { return mComment; }
|
||||
|
||||
eControlType type() { return mType; }
|
||||
bool isType(eControlType tp) { return tp == mType; }
|
||||
bool isType(eControlType tp) const { return tp == mType; }
|
||||
|
||||
void resetToDefault(bool fire_signal = false);
|
||||
|
||||
@@ -153,7 +153,8 @@ public:
|
||||
bool isCOA() const { return mIsCOA; }
|
||||
bool isCOAParent() const { return mIsCOAParent; }
|
||||
LLControlVariable *getCOAConnection() const { return mCOAConnectedVar; }
|
||||
LLControlVariable *getCOAActive();
|
||||
LLControlVariable* getCOAActive();
|
||||
LLControlVariable const* getCOAActive() const;
|
||||
void setIsCOA(bool IsCOA) { mIsCOA=IsCOA; }
|
||||
void setCOAConnect(LLControlVariable *pConnect, bool IsParent)
|
||||
{
|
||||
@@ -185,7 +186,8 @@ public:
|
||||
~LLControlGroup();
|
||||
void cleanup();
|
||||
|
||||
LLPointer<LLControlVariable> getControl(const std::string& name);
|
||||
LLControlVariable* getControl(std::string const& name);
|
||||
LLControlVariable const* getControl(std::string const& name) const;
|
||||
|
||||
struct ApplyFunctor
|
||||
{
|
||||
@@ -210,7 +212,7 @@ public:
|
||||
|
||||
std::string findString(const std::string& name);
|
||||
|
||||
std::string getString(const std::string& name);
|
||||
std::string getString(const std::string& name) const;
|
||||
LLWString getWString(const std::string& name);
|
||||
std::string getText(const std::string& name);
|
||||
LLVector3 getVector3(const std::string& name);
|
||||
@@ -245,7 +247,7 @@ public:
|
||||
void setValue(const std::string& name, const LLSD& val);
|
||||
|
||||
|
||||
BOOL controlExists(const std::string& name);
|
||||
BOOL controlExists(const std::string& name) const;
|
||||
|
||||
// Returns number of controls loaded, 0 if failed
|
||||
// If require_declaration is false, will auto-declare controls it finds
|
||||
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
LLControlGroupReader() {}
|
||||
virtual ~LLControlGroupReader() {}
|
||||
|
||||
virtual std::string getString(const std::string& name) = 0;
|
||||
virtual std::string getString(const std::string& name) const = 0;
|
||||
//virtual LLWString getWString(const std::string& name) = 0;
|
||||
virtual std::string getText(const std::string& name) = 0;
|
||||
//virtual LLVector3 getVector3(const std::string& name) = 0;
|
||||
|
||||
0
indra/media_plugins/CMakeLists.txt
Executable file → Normal file
0
indra/media_plugins/CMakeLists.txt
Executable file → Normal file
0
indra/media_plugins/base/media_plugin_base.cpp
Executable file → Normal file
0
indra/media_plugins/base/media_plugin_base.cpp
Executable file → Normal file
0
indra/media_plugins/base/media_plugin_base.h
Executable file → Normal file
0
indra/media_plugins/base/media_plugin_base.h
Executable file → Normal file
@@ -79,4 +79,4 @@ if (DARWIN)
|
||||
LINK_FLAGS "-exported_symbols_list ${CMAKE_CURRENT_SOURCE_DIR}/../base/media_plugin_base.exp"
|
||||
)
|
||||
|
||||
endif (DARWIN)
|
||||
endif (DARWIN)
|
||||
|
||||
0
indra/media_plugins/example/media_plugin_example.cpp
Executable file → Normal file
0
indra/media_plugins/example/media_plugin_example.cpp
Executable file → Normal file
0
indra/media_plugins/quicktime/CMakeLists.txt
Executable file → Normal file
0
indra/media_plugins/quicktime/CMakeLists.txt
Executable file → Normal file
0
indra/media_plugins/quicktime/media_plugin_quicktime.cpp
Executable file → Normal file
0
indra/media_plugins/quicktime/media_plugin_quicktime.cpp
Executable file → Normal file
1
indra/media_plugins/webkit/CMakeLists.txt
Executable file → Normal file
1
indra/media_plugins/webkit/CMakeLists.txt
Executable file → Normal file
@@ -27,6 +27,7 @@ include_directories(
|
||||
${LLIMAGE_INCLUDE_DIRS}
|
||||
${LLRENDER_INCLUDE_DIRS}
|
||||
${LLWINDOW_INCLUDE_DIRS}
|
||||
${LLQTWEBKIT_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
|
||||
|
||||
0
indra/media_plugins/webkit/dummy_volume_catcher.cpp
Executable file → Normal file
0
indra/media_plugins/webkit/dummy_volume_catcher.cpp
Executable file → Normal file
14
indra/media_plugins/webkit/linux_volume_catcher.cpp
Executable file → Normal file
14
indra/media_plugins/webkit/linux_volume_catcher.cpp
Executable file → Normal file
@@ -50,7 +50,7 @@ extern "C" {
|
||||
#include <pulse/subscribe.h>
|
||||
#include <pulse/glib-mainloop.h> // There's no special reason why we want the *glib* PA mainloop, but the generic polling implementation seems broken.
|
||||
|
||||
#include "apr_pools.h"
|
||||
#include "aiaprpool.h"
|
||||
#include "apr_dso.h"
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ extern "C" {
|
||||
#undef LL_PA_SYM
|
||||
|
||||
static bool sSymsGrabbed = false;
|
||||
static apr_pool_t *sSymPADSOMemoryPool = NULL;
|
||||
static AIAPRPool sSymPADSOMemoryPool;
|
||||
static apr_dso_handle_t *sSymPADSOHandleG = NULL;
|
||||
|
||||
bool grab_pa_syms(std::string pulse_dso_name)
|
||||
@@ -85,11 +85,11 @@ bool grab_pa_syms(std::string pulse_dso_name)
|
||||
#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##PASYM, sSymPADSOHandle, #PASYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #PASYM); if (REQUIRED) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #PASYM, (void*)ll##PASYM);}while(0)
|
||||
|
||||
//attempt to load the shared library
|
||||
apr_pool_create(&sSymPADSOMemoryPool, NULL);
|
||||
sSymPADSOMemoryPool.create();
|
||||
|
||||
if ( APR_SUCCESS == (rv = apr_dso_load(&sSymPADSOHandle,
|
||||
pulse_dso_name.c_str(),
|
||||
sSymPADSOMemoryPool) ))
|
||||
sSymPADSOMemoryPool()) ))
|
||||
{
|
||||
INFOMSG("Found DSO: %s", pulse_dso_name.c_str());
|
||||
|
||||
@@ -132,11 +132,7 @@ void ungrab_pa_syms()
|
||||
sSymPADSOHandleG = NULL;
|
||||
}
|
||||
|
||||
if ( sSymPADSOMemoryPool )
|
||||
{
|
||||
apr_pool_destroy(sSymPADSOMemoryPool);
|
||||
sSymPADSOMemoryPool = NULL;
|
||||
}
|
||||
sSymPADSOMemoryPool.destroy();
|
||||
|
||||
// NULL-out all of the symbols we'd grabbed
|
||||
#define LL_PA_SYM(REQUIRED, PASYM, RTN, ...) do{ll##PASYM = NULL;}while(0)
|
||||
|
||||
0
indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
Executable file → Normal file
0
indra/media_plugins/webkit/linux_volume_catcher_pa_syms.inc
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user