From 5ee546eb4e446632c32e62a5234241fd6498f281 Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 14 Oct 2010 17:01:39 -0600 Subject: for SH-335: create a debug tool to track of memory availability. --- indra/newview/llappviewer.cpp | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 333c92e50d..f6cff3d443 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -984,6 +984,7 @@ bool LLAppViewer::mainLoop() LLVoiceClient::getInstance()->init(gServicePump); LLTimer frameTimer,idleTimer; LLTimer debugTime; + LLFrameTimer memCheckTimer; LLViewerJoystick* joystick(LLViewerJoystick::getInstance()); joystick->setNeedsReset(true); @@ -994,11 +995,29 @@ bool LLAppViewer::mainLoop() // point of posting. LLSD newFrame; + const F32 memory_check_interval = 1.0f ; //second + // Handle messages while (!LLApp::isExiting()) { LLFastTimer::nextFrame(); // Should be outside of any timer instances + //clear call stack records + llclearcallstacks; + + //check memory availability information + { + if(memory_check_interval < memCheckTimer.getElapsedTimeF32()) + { + memCheckTimer.reset() ; + + //update the availability of memory + gSysMemory.getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + } + llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ; + llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ; + } + try { pingMainloopTimeout("Main:MiscNativeWindowEvents"); @@ -1225,11 +1244,20 @@ bool LLAppViewer::mainLoop() resumeMainloopTimeout(); pingMainloopTimeout("Main:End"); - } - + } } catch(std::bad_alloc) { + { + llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ; + + gSysMemory.getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + + llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ; + llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ; + } + //stop memory leaking simulation LLFloaterMemLeak* mem_leak_instance = LLFloaterReg::findTypedInstance("mem_leaking"); -- cgit v1.3 From 219cd6ecda60e1c48852f582f0994573fd0e10ae Mon Sep 17 00:00:00 2001 From: Xiaohong Bao Date: Thu, 14 Oct 2010 21:23:23 -0600 Subject: more debug code for SH-207: viewer crash in LLVertexBuffer::mapBuffer. --- indra/llcommon/llsys.cpp | 3 ++- indra/llcommon/llsys.h | 2 +- indra/llrender/llvertexbuffer.cpp | 8 +++++++- indra/newview/llappviewer.cpp | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-) (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 7a82a17d0b..10cdc7087b 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -635,7 +635,8 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const } } -void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb) const +//static +void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb) { #if LL_WINDOWS MEMORYSTATUSEX state; diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 35425f38ed..41a4f25000 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -116,7 +116,7 @@ public: U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes //get the available memory infomation in KiloBytes. - void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb) const; + static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb); }; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index fd5136e58b..02160b09c4 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -27,7 +27,7 @@ #include "linden_common.h" #include - +#include "llsys.h" #include "llvertexbuffer.h" // #include "llrender.h" #include "llglheaders.h" @@ -856,6 +856,12 @@ U8* LLVertexBuffer::mapBuffer(S32 access) { log_glerror(); + //check the availability of memory + U32 avail_phy_mem, avail_vir_mem; + LLMemoryInfo::getAvailableMemoryKB(avail_phy_mem, avail_vir_mem) ; + llinfos << "Available physical mwmory(KB): " << avail_phy_mem << llendl ; + llinfos << "Available virtual memory(KB): " << avail_vir_mem << llendl; + //-------------------- //print out more debug info before crash llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f6cff3d443..3a98749c0f 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -1012,7 +1012,7 @@ bool LLAppViewer::mainLoop() memCheckTimer.reset() ; //update the availability of memory - gSysMemory.getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; } llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ; llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ; @@ -1252,7 +1252,7 @@ bool LLAppViewer::mainLoop() llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ; llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ; - gSysMemory.getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; + LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ; llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ; llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ; -- cgit v1.3 From 5d7417b40ed8717b3f307ed9e53c249a3a26cf1b Mon Sep 17 00:00:00 2001 From: Vadim ProductEngine Date: Tue, 2 Nov 2010 20:26:38 +0200 Subject: STORM-422 FIXED Added command line option "-disablecrashlogger" to disable crash logger. This is a patch originally written by Robin Cornelius. I made it work with Google Breakpad. --- doc/contributions.txt | 1 + indra/llcommon/llapp.cpp | 32 ++++++++++++++++++++++++++++++++ indra/llcommon/llapp.h | 6 ++++++ indra/newview/app_settings/cmd_line.xml | 8 ++++++++ indra/newview/llappviewer.cpp | 14 ++++++++++++++ 5 files changed, 61 insertions(+) (limited to 'indra/newview/llappviewer.cpp') diff --git a/doc/contributions.txt b/doc/contributions.txt index 2ca5adc643..21c60ea362 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -573,6 +573,7 @@ Robin Cornelius SNOW-585 SNOW-599 SNOW-747 + STORM-422 VWR-2488 VWR-9557 VWR-11128 diff --git a/indra/llcommon/llapp.cpp b/indra/llcommon/llapp.cpp index eebd5ed0a6..39daefd1ad 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -90,6 +90,10 @@ S32 LL_HEARTBEAT_SIGNAL = (SIGRTMAX >= 0) ? (SIGRTMAX-0) : SIGUSR2; // the static application instance LLApp* LLApp::sApplication = NULL; +// Allows the generation of core files for post mortem under gdb +// and disables crashlogger +BOOL LLApp::sDisableCrashlogger = FALSE; + // Local flag for whether or not to do logging in signal handlers. //static BOOL LLApp::sLogInSignal = FALSE; @@ -461,11 +465,30 @@ bool LLApp::isQuitting() return (APP_STATUS_QUITTING == sStatus); } +// static bool LLApp::isExiting() { return isQuitting() || isError(); } +void LLApp::disableCrashlogger() +{ + // Disable Breakpad exception handler. + if (mExceptionHandler != 0) + { + delete mExceptionHandler; + mExceptionHandler = 0; + } + + sDisableCrashlogger = TRUE; +} + +// static +bool LLApp::isCrashloggerDisabled() +{ + return (sDisableCrashlogger == TRUE); +} + #if !LL_WINDOWS // static U32 LLApp::getSigChildCount() @@ -799,6 +822,15 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *) { llwarns << "Signal handler - Flagging error status and waiting for shutdown" << llendl; } + + if (LLApp::isCrashloggerDisabled()) // Don't gracefully handle any signal, crash and core for a gdb post mortem + { + clear_signals(); + llwarns << "Fatal signal received, not handling the crash here, passing back to operating system" << llendl; + raise(signum); + return; + } + // Flag status to ERROR, so thread_error does its work. LLApp::setError(); // Block in the signal handler until somebody says that we're done. diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index ee1d696829..a536a06ea5 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -189,6 +189,11 @@ public: // virtual bool mainLoop() = 0; // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit. + // + // Crash logging + // + void disableCrashlogger(); // Let the OS handle the crashes + static bool isCrashloggerDisabled(); // Get the here above set value // // Application status @@ -280,6 +285,7 @@ protected: static void setStatus(EAppStatus status); // Use this to change the application status. static EAppStatus sStatus; // Reflects current application status static BOOL sErrorThreadRunning; // Set while the error thread is running + static BOOL sDisableCrashlogger; // Let the OS handle crashes for us. #if !LL_WINDOWS static LLAtomicU32* sSigChildCount; // Number of SIGCHLDs received. diff --git a/indra/newview/app_settings/cmd_line.xml b/indra/newview/app_settings/cmd_line.xml index 00d69f805e..ba3b6a42a4 100644 --- a/indra/newview/app_settings/cmd_line.xml +++ b/indra/newview/app_settings/cmd_line.xml @@ -391,5 +391,13 @@ CrashOnStartup + disablecrashlogger + + desc + Disables the crash logger and lets the OS handle crashes + map-to + DisableCrashLogger + + diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 931b9fd2f3..b17e4d77d5 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -2020,6 +2020,15 @@ bool LLAppViewer::initConfiguration() // - apply command line settings clp.notify(); + // Register the core crash option as soon as we can + // if we want gdb post-mortem on cores we need to be up and running + // ASAP or we might miss init issue etc. + if(clp.hasOption("disablecrashlogger")) + { + llwarns << "Crashes will be handled by system, stack trace logs and crash logger are both disabled" << llendl; + LLAppViewer::instance()->disableCrashlogger(); + } + // Handle initialization from settings. // Start up the debugging console before handling other options. if (gSavedSettings.getBOOL("ShowConsoleWindow")) @@ -2596,6 +2605,11 @@ void LLAppViewer::handleViewerCrash() abort(); } + if (LLApp::isCrashloggerDisabled()) + { + abort(); + } + // Returns whether a dialog was shown. // Only do the logic in here once if (pApp->mReportedCrash) -- cgit v1.3 From 9ae2891a3afefcbf0c72cadaef203426cb0e5954 Mon Sep 17 00:00:00 2001 From: "Andrew A. de Laix" Date: Tue, 9 Nov 2010 15:04:44 -0800 Subject: start of a thread safe queue --- indra/llcommon/CMakeLists.txt | 2 + indra/llcommon/llthreadsafequeue.cpp | 109 +++++++++++++++++++ indra/llcommon/llthreadsafequeue.h | 205 +++++++++++++++++++++++++++++++++++ indra/newview/CMakeLists.txt | 2 + indra/newview/llappviewer.cpp | 5 + indra/newview/llmainlooprepeater.cpp | 82 ++++++++++++++ indra/newview/llmainlooprepeater.h | 65 +++++++++++ 7 files changed, 470 insertions(+) create mode 100644 indra/llcommon/llthreadsafequeue.cpp create mode 100644 indra/llcommon/llthreadsafequeue.h create mode 100644 indra/newview/llmainlooprepeater.cpp create mode 100644 indra/newview/llmainlooprepeater.h (limited to 'indra/newview/llappviewer.cpp') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 7bad780dd8..7d53667f35 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -92,6 +92,7 @@ set(llcommon_SOURCE_FILES llstringtable.cpp llsys.cpp llthread.cpp + llthreadsafequeue.cpp lltimer.cpp lluri.cpp lluuid.cpp @@ -223,6 +224,7 @@ set(llcommon_HEADER_FILES llstringtable.h llsys.h llthread.h + llthreadsafequeue.h lltimer.h lltreeiterators.h lluri.h diff --git a/indra/llcommon/llthreadsafequeue.cpp b/indra/llcommon/llthreadsafequeue.cpp new file mode 100644 index 0000000000..a7141605ef --- /dev/null +++ b/indra/llcommon/llthreadsafequeue.cpp @@ -0,0 +1,109 @@ +/** + * @file llthread.cpp + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include +#include +#include "llthreadsafequeue.h" + + + +// LLThreadSafeQueueImplementation +//----------------------------------------------------------------------------- + + +LLThreadSafeQueueImplementation::LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity): + mOwnsPool(pool == 0), + mPool(pool), + mQueue(0) +{ + if(mOwnsPool) { + apr_status_t status = apr_pool_create(&mPool, 0); + if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate pool"); + } else { + ; // No op. + } + + apr_status_t status = apr_queue_create(&mQueue, capacity, mPool); + if(status != APR_SUCCESS) throw LLThreadSafeQueueError("failed to allocate queue"); +} + + +LLThreadSafeQueueImplementation::~LLThreadSafeQueueImplementation() +{ + if(mOwnsPool && (mPool != 0)) apr_pool_destroy(mPool); + if(mQueue != 0) { + if(apr_queue_size(mQueue) != 0) llwarns << + "terminating queue which still contains elements;" << + "memory will be leaked" << LL_ENDL; + apr_queue_term(mQueue); + } +} + + +void LLThreadSafeQueueImplementation::pushFront(void * element) +{ + apr_status_t status = apr_queue_push(mQueue, element); + + if(status == APR_EINTR) { + throw LLThreadSafeQueueInterrupt(); + } else if(status != APR_SUCCESS) { + throw LLThreadSafeQueueError("push failed"); + } else { + ; // Success. + } +} + + +bool LLThreadSafeQueueImplementation::tryPushFront(void * element){ + return apr_queue_trypush(mQueue, element) == APR_SUCCESS; +} + + +void * LLThreadSafeQueueImplementation::popBack(void) +{ + void * element; + apr_status_t status = apr_queue_pop(mQueue, &element); + + if(status == APR_EINTR) { + throw LLThreadSafeQueueInterrupt(); + } else if(status != APR_SUCCESS) { + throw LLThreadSafeQueueError("pop failed"); + } else { + return element; + } +} + + +bool LLThreadSafeQueueImplementation::tryPopBack(void *& element) +{ + return apr_queue_trypop(mQueue, &element) == APR_SUCCESS; +} + + +size_t LLThreadSafeQueueImplementation::size() +{ + return apr_queue_size(mQueue); +} diff --git a/indra/llcommon/llthreadsafequeue.h b/indra/llcommon/llthreadsafequeue.h new file mode 100644 index 0000000000..46c8b91932 --- /dev/null +++ b/indra/llcommon/llthreadsafequeue.h @@ -0,0 +1,205 @@ +/** + * @file llthreadsafequeue.h + * @brief Base classes for thread, mutex and condition handling. + * + * $LicenseInfo:firstyear=2004&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLTHREADSAFEQUEUE_H +#define LL_LLTHREADSAFEQUEUE_H + + +#include +#include + + +struct apr_pool_t; // From apr_pools.h +class LLThreadSafeQueueImplementation; // See below. + + +// +// A general queue exception. +// +class LLThreadSafeQueueError: +public std::runtime_error +{ +public: + LLThreadSafeQueueError(std::string const & message): + std::runtime_error(message) + { + ; // No op. + } +}; + + +// +// An exception raised when blocking operations are interrupted. +// +class LLThreadSafeQueueInterrupt: + public LLThreadSafeQueueError +{ +public: + LLThreadSafeQueueInterrupt(void): + LLThreadSafeQueueError("queue operation interrupted") + { + ; // No op. + } +}; + + +struct apr_queue_t; // From apr_queue.h + + +// +// Implementation details. +// +class LLThreadSafeQueueImplementation +{ +public: + LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity); + ~LLThreadSafeQueueImplementation(); + void pushFront(void * element); + bool tryPushFront(void * element); + void * popBack(void); + bool tryPopBack(void *& element); + size_t size(); + +private: + bool mOwnsPool; + apr_pool_t * mPool; + apr_queue_t * mQueue; +}; + + +// +// Implements a thread safe FIFO. +// +template +class LLThreadSafeQueue +{ +public: + typedef ElementT value_type; + + // If the pool is set to NULL one will be allocated and managed by this + // queue. + LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024); + + // Add an element to the front of queue (will block if the queue has + // reached capacity). + // + // This call will raise an interrupt error if the queue is deleted while + // the caller is blocked. + void pushFront(ElementT const & element); + + // Try to add an element to the front ofqueue without blocking. Returns + // true only if the element was actually added. + bool tryPushFront(ElementT const & element); + + // Pop the element at the end of the queue (will block if the queue is + // empty). + // + // This call will raise an interrupt error if the queue is deleted while + // the caller is blocked. + ElementT popBack(void); + + // Pop an element from the end of the queue if there is one available. + // Returns true only if an element was popped. + bool tryPopBack(ElementT & element); + + // Returns the size of the queue. + size_t size(); + +private: + LLThreadSafeQueueImplementation mImplementation; +}; + + + +// LLThreadSafeQueue +//----------------------------------------------------------------------------- + + +template +LLThreadSafeQueue::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity): + mImplementation(pool, capacity) +{ + ; // No op. +} + + +template +void LLThreadSafeQueue::pushFront(ElementT const & element) +{ + ElementT * elementCopy = new ElementT(element); + try { + mImplementation.pushFront(elementCopy); + } catch (LLThreadSafeQueueInterrupt) { + delete elementCopy; + throw; + } +} + + +template +bool LLThreadSafeQueue::tryPushFront(ElementT const & element) +{ + ElementT * elementCopy = new ElementT(element); + bool result = mImplementation.tryPushFront(elementCopy); + if(!result) delete elementCopy; + return result; +} + + +template +ElementT LLThreadSafeQueue::popBack(void) +{ + ElementT * element = reinterpret_cast (mImplementation.popBack()); + ElementT result(*element); + delete element; + return result; +} + + +template +bool LLThreadSafeQueue::tryPopBack(ElementT & element) +{ + void * storedElement; + bool result = mImplementation.tryPopBack(storedElement); + if(result) { + ElementT * elementPtr = reinterpret_cast(storedElement); + element = *elementPtr; + delete elementPtr; + } else { + ; // No op. + } + return result; +} + + +template +size_t LLThreadSafeQueue::size(void) +{ + return mImplementation.size(); +} + + +#endif diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index a9d1fd9064..36cfa615f0 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -283,6 +283,7 @@ set(viewer_SOURCE_FILES llloginhandler.cpp lllogininstance.cpp llmachineid.cpp + llmainlooprepeater.cpp llmanip.cpp llmaniprotate.cpp llmanipscale.cpp @@ -815,6 +816,7 @@ set(viewer_HEADER_FILES llloginhandler.h lllogininstance.h llmachineid.h + llmainlooprepeater.h llmanip.h llmaniprotate.h llmanipscale.h diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index c0ec15f436..438f8668ae 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -197,6 +197,8 @@ #include "llsecapi.h" #include "llmachineid.h" +#include "llmainlooprepeater.h" + // *FIX: These extern globals should be cleaned up. // The globals either represent state/config/resource-storage of either // this app, or another 'component' of the viewer. App globals should be @@ -801,6 +803,9 @@ bool LLAppViewer::init() return 1; } + // Initialize the repeater service. + LLMainLoopRepeater::getInstance()->start(); + // // Initialize the window // diff --git a/indra/newview/llmainlooprepeater.cpp b/indra/newview/llmainlooprepeater.cpp new file mode 100644 index 0000000000..c2eba97641 --- /dev/null +++ b/indra/newview/llmainlooprepeater.cpp @@ -0,0 +1,82 @@ +/** + * @file llmachineid.cpp + * @brief retrieves unique machine ids + * + * $LicenseInfo:firstyear=2009&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llapr.h" +#include "llevents.h" +#include "llmainlooprepeater.h" + + + +// LLMainLoopRepeater +//----------------------------------------------------------------------------- + + +LLMainLoopRepeater::LLMainLoopRepeater(void): + mQueue(gAPRPoolp, 1024) +{ + ; // No op. +} + + +void LLMainLoopRepeater::start(void) +{ + mMainLoopConnection = LLEventPumps::instance(). + obtain("mainloop").listen("stupid name here", boost::bind(&LLMainLoopRepeater::onMainLoop, this, _1)); + mRepeaterConnection = LLEventPumps::instance(). + obtain("mainlooprepeater").listen("other stupid name here", boost::bind(&LLMainLoopRepeater::onMessage, this, _1)); +} + + +void LLMainLoopRepeater::stop(void) +{ + mMainLoopConnection.release(); + mRepeaterConnection.release(); +} + + +bool LLMainLoopRepeater::onMainLoop(LLSD const &) +{ + LLSD message; + while(mQueue.tryPopBack(message)) { + std::string pump = message["pump"].asString(); + if(pump.length() == 0 ) continue; // No pump. + LLEventPumps::instance().obtain(pump).post(message["payload"]); + } + return false; +} + + +bool LLMainLoopRepeater::onMessage(LLSD const & event) +{ + try { + mQueue.pushFront(event); + } catch(LLThreadSafeQueueError & e) { + llwarns << "could not repeat message (" << e.what() << ")" << + event.asString() << LL_ENDL; + } + return false; +} diff --git a/indra/newview/llmainlooprepeater.h b/indra/newview/llmainlooprepeater.h new file mode 100644 index 0000000000..96b83b4916 --- /dev/null +++ b/indra/newview/llmainlooprepeater.h @@ -0,0 +1,65 @@ +/** + * @file llmainlooprepeater.h + * @brief a service for repeating messages on the main loop. + * + * $LicenseInfo:firstyear=2010&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLMAINLOOPREPEATER_H +#define LL_LLMAINLOOPREPEATER_H + + +#include "llsd.h" +#include "llthreadsafequeue.h" + + +// +// A service which creates the pump 'mainlooprepeater' to which any thread can +// post a message that will be re-posted on the main loop. +// +// The posted message should contain two map elements: pump and payload. The +// pump value is a string naming the pump to which the message should be +// re-posted. The payload value is what will be posted to the designated pump. +// +class LLMainLoopRepeater: + public LLSingleton +{ +public: + LLMainLoopRepeater(void); + + // Start the repeater service. + void start(void); + + // Stop the repeater service. + void stop(void); + +private: + LLTempBoundListener mMainLoopConnection; + LLTempBoundListener mRepeaterConnection; + LLThreadSafeQueue mQueue; + + bool onMainLoop(LLSD const &); + bool onMessage(LLSD const & event); +}; + + +#endif -- cgit v1.3