From a17ca8260aa4a1e414b6a19d3faeb18f914c3f31 Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Mon, 26 Oct 2009 16:08:43 -0400 Subject: Beginning work for DEV-41722 normalizing shared lib staging on all 3 platforms. Renamed CopyWinLibs.cmake to Copy3rdPartyLibs.cmake. --- indra/llcommon/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index e7aaf3c984..7a7281a4a7 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -8,9 +8,7 @@ include(Linking) include(Boost) include (Pth) -if (WINDOWS) - include(CopyWinLibs) -endif (WINDOWS) +include(Copy3rdPartyLibs) include_directories( ${EXPAT_INCLUDE_DIRS} -- cgit v1.2.3 From 4bff7b085381a514afb7e8546beaac5ad6117f9b Mon Sep 17 00:00:00 2001 From: brad kittenbrink Date: Wed, 4 Nov 2009 18:50:35 -0500 Subject: Wrap-up work for DEV-41724/DEV-41725 - normalizing shared library staging on all 3 platforms. Should now work out of the box on all 3 platforms and in the debugger. --- indra/llcommon/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 7a7281a4a7..1e39a4474f 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -248,6 +248,13 @@ if(LLCOMMON_LINK_SHARED) if(NOT WINDOWS) get_target_property(LLCOMMON_PATH llcommon LOCATION) get_filename_component(LLCOMMON_FILE ${LLCOMMON_PATH} NAME) + if(DARWIN) + set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources) + else(DARWIN) + set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}) + endif(DARWIN) + + # *TODO - maybe make this a symbolic link? -brad add_custom_command( TARGET llcommon POST_BUILD COMMAND ${CMAKE_COMMAND} @@ -255,7 +262,7 @@ if(LLCOMMON_LINK_SHARED) -E copy_if_different ${LLCOMMON_PATH} - ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/${LLCOMMON_FILE} + ${SHARED_LIB_STAGING_DIR_CONFIG}/${LLCOMMON_FILE} COMMENT "Copying llcommon to the staging folder." ) endif(NOT WINDOWS) -- cgit v1.2.3 From ec32310c8602bf4dc69ed27e8c177cbd32c24411 Mon Sep 17 00:00:00 2001 From: palange Date: Thu, 5 Nov 2009 17:51:50 -0800 Subject: Removed search_dirs and dst_path arguments from ll_deploy_sharedlibs_command() Fixed mac breakage. --- indra/llcommon/CMakeLists.txt | 42 ++++-------------------------------------- 1 file changed, 4 insertions(+), 38 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index ea36e65729..f40359790a 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -1,3 +1,4 @@ + # -*- cmake -*- project(llcommon) @@ -6,8 +7,8 @@ include(00-Common) include(LLCommon) include(Linking) include(Boost) -include (Pth) - +include(Pth) +include(LLSharedLibs) include(Copy3rdPartyLibs) include_directories( @@ -241,42 +242,7 @@ list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES}) if(LLCOMMON_LINK_SHARED) add_library (llcommon SHARED ${llcommon_SOURCE_FILES}) - - if(SHARED_LIB_STAGING_DIR) - # *FIX:Mani --- - # llcommon.dll get written to the DLL staging directory. - # Also this directory is shared with RunBuildTest.cmake, y'know, for the tests. - set_target_properties(llcommon PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${SHARED_LIB_STAGING_DIR}) - if(NOT WINDOWS) - get_target_property(LLCOMMON_PATH llcommon LOCATION) - get_filename_component(LLCOMMON_FILE ${LLCOMMON_PATH} NAME) - if(DARWIN) - set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/Resources) - else(DARWIN) - set(SHARED_LIB_STAGING_DIR_CONFIG ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}) - endif(DARWIN) - - # *TODO - maybe make this a symbolic link? -brad - add_custom_command( - TARGET llcommon POST_BUILD - COMMAND ${CMAKE_COMMAND} - ARGS - -E - copy_if_different - ${LLCOMMON_PATH} - ${SHARED_LIB_STAGING_DIR_CONFIG}/${LLCOMMON_FILE} - COMMENT "Copying llcommon to the staging folder." - ) - endif(NOT WINDOWS) - endif(SHARED_LIB_STAGING_DIR) - - if (DARWIN) - set_target_properties(llcommon PROPERTIES - BUILD_WITH_INSTALL_RPATH 1 - INSTALL_NAME_DIR "@executable_path/../Resources" - ) - endif(DARWIN) - + ll_stage_sharedlib(llcommon) else(LLCOMMON_LINK_SHARED) add_library (llcommon ${llcommon_SOURCE_FILES}) endif(LLCOMMON_LINK_SHARED) -- cgit v1.2.3 From fc849873abb839b013efbae5e44b150d4be1f236 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 10 Nov 2009 13:16:33 -0500 Subject: Remove dangling LLEVENTS_LISTENER_ARITY control --- indra/llcommon/llevents.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index 192d79b27d..f52cf33fd8 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -45,10 +45,12 @@ #include "llsingleton.h" #include "lldependencies.h" +/*==========================================================================*| // override this to allow binding free functions with more parameters #ifndef LLEVENTS_LISTENER_ARITY #define LLEVENTS_LISTENER_ARITY 10 #endif +|*==========================================================================*/ // hack for testing #ifndef testable -- cgit v1.2.3 From a97aebb84a8b5b43de01fd3823d1b38e711e6ab7 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 10 Nov 2009 13:30:29 -0500 Subject: Enhance LLInstanceTracker variants to be more uniform. For both the (so far unused) generic KEY form and the KEY = T* form, provide key_iter, beginKeys(), endKeys(). Change instance_iter so that when dereferenced, it gives you a T& rather than a T*, to be more harmonious with a typical STL container. (You parameterize LLInstanceTracker with T, not with T*.) Fix existing usage in llfasttimer.cpp and lltimer.cpp to agree. For the KEY = T* specialization, add T* getInstance(T*) so client isn't forced to know which variant was used. Add unit tests for uniformity of public operations on both variants. --- indra/llcommon/CMakeLists.txt | 1 + indra/llcommon/llinstancetracker.h | 90 +++++++++---- indra/llcommon/lltimer.cpp | 12 +- indra/llcommon/tests/llinstancetracker_test.cpp | 160 ++++++++++++++++++++++++ 4 files changed, 231 insertions(+), 32 deletions(-) create mode 100644 indra/llcommon/tests/llinstancetracker_test.cpp (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index f785698612..3a36b8430c 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -305,6 +305,7 @@ LL_ADD_INTEGRATION_TEST(lldate "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lldependencies "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") +LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index ea50acbbc5..039d68faef 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -38,22 +38,53 @@ #include "string_table.h" #include - -// This mix-in class adds support for tracking all instances of the specified class parameter T -// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup -// If KEY is not provided, then instances are stored in a simple set -// *NOTE: see explicit specialization below for default KEY==T* case +#include +#include +#include +#include + +/// This mix-in class adds support for tracking all instances of the specified class parameter T +/// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup +/// If KEY is not provided, then instances are stored in a simple set +/// @NOTE: see explicit specialization below for default KEY==T* case template class LLInstanceTracker : boost::noncopyable { + typedef typename std::map InstanceMap; + typedef boost::function KeyGetter; + typedef boost::function InstancePtrGetter; public: - typedef typename std::map::iterator instance_iter; - typedef typename std::map::const_iterator instance_const_iter; - - static T* getInstance(const KEY& k) { instance_iter found = getMap().find(k); return (found == getMap().end()) ? NULL : found->second; } + /// Dereferencing key_iter gives you a const KEY& + typedef boost::transform_iterator key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator< boost::transform_iterator > instance_iter; + + static T* getInstance(const KEY& k) + { + typename InstanceMap::const_iterator found = getMap().find(k); + return (found == getMap().end()) ? NULL : found->second; + } - static instance_iter beginInstances() { return getMap().begin(); } - static instance_iter endInstances() { return getMap().end(); } + static key_iter beginKeys() + { + return boost::make_transform_iterator(getMap().begin(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static key_iter endKeys() + { + return boost::make_transform_iterator(getMap().end(), + boost::bind(&InstanceMap::value_type::first, _1)); + } + static instance_iter beginInstances() + { + return instance_iter(boost::make_transform_iterator(getMap().begin(), + boost::bind(&InstanceMap::value_type::second, _1))); + } + static instance_iter endInstances() + { + return instance_iter(boost::make_transform_iterator(getMap().end(), + boost::bind(&InstanceMap::value_type::second, _1))); + } static S32 instanceCount() { return getMap().size(); } protected: LLInstanceTracker(KEY key) { add(key); } @@ -69,11 +100,11 @@ private: } void remove() { getMap().erase(mKey); } - static std::map& getMap() + static InstanceMap& getMap() { if (! sInstances) { - sInstances = new std::map; + sInstances = new InstanceMap; } return *sInstances; } @@ -81,20 +112,27 @@ private: private: KEY mKey; - static std::map* sInstances; + static InstanceMap* sInstances; }; -// explicit specialization for default case where KEY is T* -// use a simple std::set +/// explicit specialization for default case where KEY is T* +/// use a simple std::set template class LLInstanceTracker { + typedef typename std::set InstanceSet; public: - typedef typename std::set::iterator instance_iter; - typedef typename std::set::const_iterator instance_const_iter; - - static instance_iter beginInstances() { return getSet().begin(); } - static instance_iter endInstances() { return getSet().end(); } + /// Dereferencing key_iter gives you a T* (since T* is the key) + typedef typename InstanceSet::iterator key_iter; + /// Dereferencing instance_iter gives you a T& + typedef boost::indirect_iterator instance_iter; + + /// for completeness of analogy with the generic implementation + static T* getInstance(T* k) { return k; } + static key_iter beginKeys() { return getSet().begin(); } + static key_iter endKeys() { return getSet().end(); } + static instance_iter beginInstances() { return instance_iter(getSet().begin()); } + static instance_iter endInstances() { return instance_iter(getSet().end()); } static S32 instanceCount() { return getSet().size(); } protected: @@ -103,19 +141,19 @@ protected: LLInstanceTracker(const LLInstanceTracker& other) { getSet().insert(static_cast(this)); } - static std::set& getSet() // called after getReady() but before go() + static InstanceSet& getSet() // called after getReady() but before go() { if (! sInstances) { - sInstances = new std::set; + sInstances = new InstanceSet; } return *sInstances; } - static std::set* sInstances; + static InstanceSet* sInstances; }; -template std::map* LLInstanceTracker::sInstances = NULL; -template std::set* LLInstanceTracker::sInstances = NULL; +template typename LLInstanceTracker::InstanceMap* LLInstanceTracker::sInstances = NULL; +template typename LLInstanceTracker::InstanceSet* LLInstanceTracker::sInstances = NULL; #endif diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index ea5b0c03ef..ef3e8dbc94 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -583,13 +583,13 @@ void LLEventTimer::updateClass() std::list completed_timers; for (instance_iter iter = beginInstances(); iter != endInstances(); ) { - LLEventTimer* timer = *iter++; - F32 et = timer->mEventTimer.getElapsedTimeF32(); - if (timer->mEventTimer.getStarted() && et > timer->mPeriod) { - timer->mEventTimer.reset(); - if ( timer->tick() ) + LLEventTimer& timer = *iter++; + F32 et = timer.mEventTimer.getElapsedTimeF32(); + if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { + timer.mEventTimer.reset(); + if ( timer.tick() ) { - completed_timers.push_back( timer ); + completed_timers.push_back( &timer ); } } } diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp new file mode 100644 index 0000000000..7415f2d33b --- /dev/null +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -0,0 +1,160 @@ +/** + * @file llinstancetracker_test.cpp + * @author Nat Goodspeed + * @date 2009-11-10 + * @brief Test for llinstancetracker. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llinstancetracker.h" +// STL headers +#include +#include +#include +#include // std::sort() +// std headers +// external library headers +#include +// other Linden headers +#include "../test/lltut.h" + +struct Keyed: public LLInstanceTracker +{ + Keyed(const std::string& name): + LLInstanceTracker(name), + mName(name) + {} + std::string mName; +}; + +struct Unkeyed: public LLInstanceTracker +{ +}; + +/***************************************************************************** +* TUT +*****************************************************************************/ +namespace tut +{ + struct llinstancetracker_data + { + }; + typedef test_group llinstancetracker_group; + typedef llinstancetracker_group::object object; + llinstancetracker_group llinstancetrackergrp("llinstancetracker"); + + template<> template<> + void object::test<1>() + { + ensure_equals(Keyed::instanceCount(), 0); + { + Keyed one("one"); + ensure_equals(Keyed::instanceCount(), 1); + Keyed* found = Keyed::getInstance("one"); + ensure("couldn't find stack Keyed", found); + ensure_equals("found wrong Keyed instance", found, &one); + { + boost::scoped_ptr two(new Keyed("two")); + ensure_equals(Keyed::instanceCount(), 2); + Keyed* found = Keyed::getInstance("two"); + ensure("couldn't find heap Keyed", found); + ensure_equals("found wrong Keyed instance", found, two.get()); + } + ensure_equals(Keyed::instanceCount(), 1); + } + Keyed* found = Keyed::getInstance("one"); + ensure("Keyed key lives too long", ! found); + ensure_equals(Keyed::instanceCount(), 0); + } + + template<> template<> + void object::test<2>() + { + ensure_equals(Unkeyed::instanceCount(), 0); + { + Unkeyed one; + ensure_equals(Unkeyed::instanceCount(), 1); + Unkeyed* found = Unkeyed::getInstance(&one); + ensure_equals(found, &one); + { + boost::scoped_ptr two(new Unkeyed); + ensure_equals(Unkeyed::instanceCount(), 2); + Unkeyed* found = Unkeyed::getInstance(two.get()); + ensure_equals(found, two.get()); + } + ensure_equals(Unkeyed::instanceCount(), 1); + } + ensure_equals(Unkeyed::instanceCount(), 0); + } + + template<> template<> + void object::test<3>() + { + Keyed one("one"), two("two"), three("three"); + // We don't want to rely on the underlying container delivering keys + // in any particular order. That allows us the flexibility to + // reimplement LLInstanceTracker using, say, a hash map instead of a + // std::map. We DO insist that every key appear exactly once. + typedef std::vector StringVector; + StringVector keys(Keyed::beginKeys(), Keyed::endKeys()); + std::sort(keys.begin(), keys.end()); + StringVector::const_iterator ki(keys.begin()); + ensure_equals(*ki++, "one"); + ensure_equals(*ki++, "three"); + ensure_equals(*ki++, "two"); + // Use ensure() here because ensure_equals would want to display + // mismatched values, and frankly that wouldn't help much. + ensure("didn't reach end", ki == keys.end()); + + // Use a somewhat different approach to order independence with + // beginInstances(): explicitly capture the instances we know in a + // set, and delete them as we iterate through. + typedef std::set InstanceSet; + InstanceSet instances; + instances.insert(&one); + instances.insert(&two); + instances.insert(&three); + for (Keyed::instance_iter ii(Keyed::beginInstances()), iend(Keyed::endInstances()); + ii != iend; ++ii) + { + Keyed& ref = *ii; + ensure_equals("spurious instance", instances.erase(&ref), 1); + } + ensure_equals("unreported instance", instances.size(), 0); + } + + template<> template<> + void object::test<4>() + { + Unkeyed one, two, three; + typedef std::set KeySet; + KeySet keys; + keys.insert(&one); + keys.insert(&two); + keys.insert(&three); + for (Unkeyed::key_iter ki(Unkeyed::beginKeys()), kend(Unkeyed::endKeys()); + ki != kend; ++ki) + { + ensure_equals("spurious key", keys.erase(*ki), 1); + } + ensure_equals("unreported key", keys.size(), 0); + + KeySet instances; + instances.insert(&one); + instances.insert(&two); + instances.insert(&three); + for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); + ii != iend; ++ii) + { + Unkeyed& ref = *ii; + ensure_equals("spurious instance", instances.erase(&ref), 1); + } + ensure_equals("unreported instance", instances.size(), 0); + } +} // namespace tut -- cgit v1.2.3 From 2fd31363f747aaf0ec3d3d6b5711e0ecc99b2cf3 Mon Sep 17 00:00:00 2001 From: Monroe Linden Date: Tue, 10 Nov 2009 15:57:26 -0800 Subject: Added PluginAttachDebuggerToPlugins debug setting. Added accessors to get platform-specific process ID from LLProcessLauncher. Added an optional "debug" argument to LLPluginClassMedia::init() and LLPluginProcessParent::init() (defaults to false). Mac only: made the state machine in LLPluginProcessParent::idle() open a new window in Terminal.app with a gdb session attached to the plugin process upon successful launch. --- indra/llcommon/llprocesslauncher.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llprocesslauncher.h b/indra/llcommon/llprocesslauncher.h index 880562157f..929d547f6e 100644 --- a/indra/llcommon/llprocesslauncher.h +++ b/indra/llcommon/llprocesslauncher.h @@ -70,6 +70,14 @@ public: // This needs to be called periodically on Mac/Linux to clean up zombie processes. static void reap(void); + + // Accessors for platform-specific process ID +#if LL_WINDOWS + HANDLE getProcessHandle() { return mProcessHandle; }; +#else + pid_t getProcessID() { return mProcessID; }; +#endif + private: std::string mExecutable; std::string mWorkingDir; -- cgit v1.2.3 From 43ae94ab0f35dafaa0e1787a155290e371e317a1 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 11 Nov 2009 07:32:59 -0500 Subject: Rename private methods to avoid ambiguity with subclasses --- indra/llcommon/llinstancetracker.h | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'indra/llcommon') diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 039d68faef..11fe523651 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -61,46 +61,46 @@ public: static T* getInstance(const KEY& k) { - typename InstanceMap::const_iterator found = getMap().find(k); - return (found == getMap().end()) ? NULL : found->second; + typename InstanceMap::const_iterator found = getMap_().find(k); + return (found == getMap_().end()) ? NULL : found->second; } static key_iter beginKeys() { - return boost::make_transform_iterator(getMap().begin(), + return boost::make_transform_iterator(getMap_().begin(), boost::bind(&InstanceMap::value_type::first, _1)); } static key_iter endKeys() { - return boost::make_transform_iterator(getMap().end(), + return boost::make_transform_iterator(getMap_().end(), boost::bind(&InstanceMap::value_type::first, _1)); } static instance_iter beginInstances() { - return instance_iter(boost::make_transform_iterator(getMap().begin(), + return instance_iter(boost::make_transform_iterator(getMap_().begin(), boost::bind(&InstanceMap::value_type::second, _1))); } static instance_iter endInstances() { - return instance_iter(boost::make_transform_iterator(getMap().end(), + return instance_iter(boost::make_transform_iterator(getMap_().end(), boost::bind(&InstanceMap::value_type::second, _1))); } - static S32 instanceCount() { return getMap().size(); } + static S32 instanceCount() { return getMap_().size(); } protected: - LLInstanceTracker(KEY key) { add(key); } - virtual ~LLInstanceTracker() { remove(); } - virtual void setKey(KEY key) { remove(); add(key); } + LLInstanceTracker(KEY key) { add_(key); } + virtual ~LLInstanceTracker() { remove_(); } + virtual void setKey(KEY key) { remove_(); add_(key); } virtual const KEY& getKey() const { return mKey; } private: - void add(KEY key) + void add_(KEY key) { mKey = key; - getMap()[key] = static_cast(this); + getMap_()[key] = static_cast(this); } - void remove() { getMap().erase(mKey); } + void remove_() { getMap_().erase(mKey); } - static InstanceMap& getMap() + static InstanceMap& getMap_() { if (! sInstances) { @@ -129,19 +129,19 @@ public: /// for completeness of analogy with the generic implementation static T* getInstance(T* k) { return k; } - static key_iter beginKeys() { return getSet().begin(); } - static key_iter endKeys() { return getSet().end(); } - static instance_iter beginInstances() { return instance_iter(getSet().begin()); } - static instance_iter endInstances() { return instance_iter(getSet().end()); } - static S32 instanceCount() { return getSet().size(); } + static key_iter beginKeys() { return getSet_().begin(); } + static key_iter endKeys() { return getSet_().end(); } + static instance_iter beginInstances() { return instance_iter(getSet_().begin()); } + static instance_iter endInstances() { return instance_iter(getSet_().end()); } + static S32 instanceCount() { return getSet_().size(); } protected: - LLInstanceTracker() { getSet().insert(static_cast(this)); } - virtual ~LLInstanceTracker() { getSet().erase(static_cast(this)); } + LLInstanceTracker() { getSet_().insert(static_cast(this)); } + virtual ~LLInstanceTracker() { getSet_().erase(static_cast(this)); } - LLInstanceTracker(const LLInstanceTracker& other) { getSet().insert(static_cast(this)); } + LLInstanceTracker(const LLInstanceTracker& other) { getSet_().insert(static_cast(this)); } - static InstanceSet& getSet() // called after getReady() but before go() + static InstanceSet& getSet_() // called after getReady() but before go() { if (! sInstances) { -- cgit v1.2.3 From 062d0a13db505636b186084d42c527a49637f380 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Wed, 11 Nov 2009 07:41:50 -0500 Subject: Add LLEventAPI class, formalizing the mechanism by which we wrap a C++ API with an event API. In addition to the LLEventPump name on which to listen, LLEventAPI accepts a documentation string for event API introspection. Give every LLEventDispatcher::add() overload a new documentation string parameter for event API introspection. Convert every existing event API to new conventions, introducing suitable documentation strings for the API and each of its operations. --- indra/llcommon/CMakeLists.txt | 2 ++ indra/llcommon/lleventapi.cpp | 30 ++++++++++++++++++++ indra/llcommon/lleventapi.h | 53 ++++++++++++++++++++++++++++++++++++ indra/llcommon/lleventdispatcher.cpp | 12 ++++---- indra/llcommon/lleventdispatcher.h | 35 ++++++++++++++++++------ 5 files changed, 119 insertions(+), 13 deletions(-) create mode 100644 indra/llcommon/lleventapi.cpp create mode 100644 indra/llcommon/lleventapi.h (limited to 'indra/llcommon') diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 2d0363d188..e41c75846b 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -41,6 +41,7 @@ set(llcommon_SOURCE_FILES llerror.cpp llerrorthread.cpp llevent.cpp + lleventapi.cpp lleventcoro.cpp lleventdispatcher.cpp lleventfilter.cpp @@ -140,6 +141,7 @@ set(llcommon_HEADER_FILES llerrorlegacy.h llerrorthread.h llevent.h + lleventapi.h lleventcoro.h lleventdispatcher.h lleventfilter.h diff --git a/indra/llcommon/lleventapi.cpp b/indra/llcommon/lleventapi.cpp new file mode 100644 index 0000000000..1dd104da8f --- /dev/null +++ b/indra/llcommon/lleventapi.cpp @@ -0,0 +1,30 @@ +/** + * @file lleventapi.cpp + * @author Nat Goodspeed + * @date 2009-11-10 + * @brief Implementation for lleventapi. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "lleventapi.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +LLEventAPI::LLEventAPI(const std::string& name, const std::string& desc, const std::string& field): + lbase(name, field), + ibase(name), + mDesc(desc) +{ +} + +LLEventAPI::~LLEventAPI() +{ +} diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h new file mode 100644 index 0000000000..fef12988cb --- /dev/null +++ b/indra/llcommon/lleventapi.h @@ -0,0 +1,53 @@ +/** + * @file lleventapi.h + * @author Nat Goodspeed + * @date 2009-10-28 + * @brief LLEventAPI is the base class for every class that wraps a C++ API + * in an event API + * (see https://wiki.lindenlab.com/wiki/Incremental_Viewer_Automation/Event_API). + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLEVENTAPI_H) +#define LL_LLEVENTAPI_H + +#include "lleventdispatcher.h" +#include "llinstancetracker.h" +#include + +/** + * LLEventAPI not only provides operation dispatch functionality, inherited + * from LLDispatchListener -- it also gives us event API introspection. + * Deriving from LLInstanceTracker lets us enumerate instances. + */ +class LLEventAPI: public LLDispatchListener, + public LLInstanceTracker +{ + typedef LLDispatchListener lbase; + typedef LLInstanceTracker ibase; + +public: + /** + * @param name LLEventPump name on which this LLEventAPI will listen. This + * also serves as the LLInstanceTracker instance key. + * @param desc Documentation string shown to a client trying to discover + * available event APIs. + * @param field LLSD::Map key used by LLDispatchListener to look up the + * subclass method to invoke [default "op"]. + */ + LLEventAPI(const std::string& name, const std::string& desc, const std::string& field="op"); + virtual ~LLEventAPI(); + + /// Get the string name of this LLEventAPI + std::string getName() const { return ibase::getKey(); } + /// Get the documentation string + std::string getDesc() const { return mDesc; } + +private: + std::string mDesc; +}; + +#endif /* ! defined(LL_LLEVENTAPI_H) */ diff --git a/indra/llcommon/lleventdispatcher.cpp b/indra/llcommon/lleventdispatcher.cpp index 6b1413d054..017bf3a521 100644 --- a/indra/llcommon/lleventdispatcher.cpp +++ b/indra/llcommon/lleventdispatcher.cpp @@ -36,9 +36,11 @@ LLEventDispatcher::~LLEventDispatcher() } /// Register a callable by name -void LLEventDispatcher::add(const std::string& name, const Callable& callable, const LLSD& required) +void LLEventDispatcher::add(const std::string& name, const std::string& desc, + const Callable& callable, const LLSD& required) { - mDispatch[name] = DispatchMap::mapped_type(callable, required); + mDispatch.insert(DispatchMap::value_type(name, + DispatchMap::mapped_type(callable, desc, required))); } void LLEventDispatcher::addFail(const std::string& name, const std::string& classname) const @@ -98,14 +100,14 @@ bool LLEventDispatcher::attemptCall(const std::string& name, const LLSD& event) } // Found the name, so it's plausible to even attempt the call. But first, // validate the syntax of the event itself. - std::string mismatch(llsd_matches(found->second.second, event)); + std::string mismatch(llsd_matches(found->second.mRequired, event)); if (! mismatch.empty()) { LL_ERRS("LLEventDispatcher") << "LLEventDispatcher(" << mDesc << ") calling '" << name << "': bad request: " << mismatch << LL_ENDL; } // Event syntax looks good, go for it! - (found->second.first)(event); + (found->second.mFunc)(event); return true; // tell caller we were able to call } @@ -116,7 +118,7 @@ LLEventDispatcher::Callable LLEventDispatcher::get(const std::string& name) cons { return Callable(); } - return found->second.first; + return found->second.mFunc; } LLDispatchListener::LLDispatchListener(const std::string& pumpname, const std::string& key): diff --git a/indra/llcommon/lleventdispatcher.h b/indra/llcommon/lleventdispatcher.h index 5a86b90bff..eba7b607f1 100644 --- a/indra/llcommon/lleventdispatcher.h +++ b/indra/llcommon/lleventdispatcher.h @@ -44,7 +44,10 @@ public: * is used to validate the structure of each incoming event (see * llsd_matches()). */ - void add(const std::string& name, const Callable& callable, const LLSD& required=LLSD()); + void add(const std::string& name, + const std::string& desc, + const Callable& callable, + const LLSD& required=LLSD()); /** * Special case: a subclass of this class can pass an unbound member @@ -52,18 +55,22 @@ public: * boost::bind() expression. */ template - void add(const std::string& name, void (CLASS::*method)(const LLSD&), + void add(const std::string& name, + const std::string& desc, + void (CLASS::*method)(const LLSD&), const LLSD& required=LLSD()) { - addMethod(name, method, required); + addMethod(name, desc, method, required); } /// Overload for both const and non-const methods template - void add(const std::string& name, void (CLASS::*method)(const LLSD&) const, + void add(const std::string& name, + const std::string& desc, + void (CLASS::*method)(const LLSD&) const, const LLSD& required=LLSD()) { - addMethod(name, method, required); + addMethod(name, desc, method, required); } /// Unregister a callable @@ -86,7 +93,8 @@ public: private: template - void addMethod(const std::string& name, const METHOD& method, const LLSD& required) + void addMethod(const std::string& name, const std::string& desc, + const METHOD& method, const LLSD& required) { CLASS* downcast = dynamic_cast(this); if (! downcast) @@ -95,7 +103,7 @@ private: } else { - add(name, boost::bind(method, downcast, _1), required); + add(name, desc, boost::bind(method, downcast, _1), required); } } void addFail(const std::string& name, const std::string& classname) const; @@ -103,7 +111,18 @@ private: bool attemptCall(const std::string& name, const LLSD& event) const; std::string mDesc, mKey; - typedef std::map > DispatchMap; + struct DispatchEntry + { + DispatchEntry(const Callable& func, const std::string& desc, const LLSD& required): + mFunc(func), + mDesc(desc), + mRequired(required) + {} + Callable mFunc; + std::string mDesc; + LLSD mRequired; + }; + typedef std::map DispatchMap; DispatchMap mDispatch; }; -- cgit v1.2.3