summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
Diffstat (limited to 'indra/llcommon')
-rwxr-xr-xindra/llcommon/CMakeLists.txt2
-rw-r--r--indra/llcommon/llcallbacklist.cpp230
-rw-r--r--indra/llcommon/llcallbacklist.h79
-rwxr-xr-xindra/llcommon/lleventcoro.cpp32
-rwxr-xr-xindra/llcommon/lleventcoro.h87
-rwxr-xr-xindra/llcommon/llmemory.cpp3
-rwxr-xr-xindra/llcommon/llmemory.h9
-rw-r--r--indra/llcommon/llmutex.h4
-rwxr-xr-xindra/llcommon/llprocess.cpp13
-rw-r--r--indra/llcommon/llsdjson.cpp48
-rw-r--r--indra/llcommon/llsdjson.h18
-rwxr-xr-xindra/llcommon/llstl.h4
-rw-r--r--indra/llcommon/lluriparser.cpp10
-rwxr-xr-xindra/llcommon/tests/lleventcoro_test.cpp50
14 files changed, 487 insertions, 102 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index e529cea29c..8ae487354a 100755
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -39,6 +39,7 @@ set(llcommon_SOURCE_FILES
llbase32.cpp
llbase64.cpp
llbitpack.cpp
+ llcallbacklist.cpp
llcommon.cpp
llcommonutils.cpp
llcoros.cpp
@@ -132,6 +133,7 @@ set(llcommon_HEADER_FILES
llbase64.h
llbitpack.h
llboost.h
+ llcallbacklist.h
llcommon.h
llcommonutils.h
llcoros.h
diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp
new file mode 100644
index 0000000000..541ff75ee4
--- /dev/null
+++ b/indra/llcommon/llcallbacklist.cpp
@@ -0,0 +1,230 @@
+/**
+ * @file llcallbacklist.cpp
+ * @brief A simple list of callback functions to call.
+ *
+ * $LicenseInfo:firstyear=2001&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 "llcallbacklist.h"
+#include "lleventtimer.h"
+#include "llerrorlegacy.h"
+
+// Globals
+//
+LLCallbackList gIdleCallbacks;
+
+//
+// Member functions
+//
+
+LLCallbackList::LLCallbackList()
+{
+ // nothing
+}
+
+LLCallbackList::~LLCallbackList()
+{
+}
+
+
+void LLCallbackList::addFunction( callback_t func, void *data)
+{
+ if (!func)
+ {
+ return;
+ }
+
+ // only add one callback per func/data pair
+ //
+ if (containsFunction(func))
+ {
+ return;
+ }
+
+ callback_pair_t t(func, data);
+ mCallbackList.push_back(t);
+}
+
+bool LLCallbackList::containsFunction( callback_t func, void *data)
+{
+ callback_pair_t t(func, data);
+ callback_list_t::iterator iter = find(func,data);
+ if (iter != mCallbackList.end())
+ {
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+
+bool LLCallbackList::deleteFunction( callback_t func, void *data)
+{
+ callback_list_t::iterator iter = find(func,data);
+ if (iter != mCallbackList.end())
+ {
+ mCallbackList.erase(iter);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+inline
+LLCallbackList::callback_list_t::iterator
+LLCallbackList::find(callback_t func, void *data)
+{
+ callback_pair_t t(func, data);
+ return std::find(mCallbackList.begin(), mCallbackList.end(), t);
+}
+
+void LLCallbackList::deleteAllFunctions()
+{
+ mCallbackList.clear();
+}
+
+
+void LLCallbackList::callFunctions()
+{
+ for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); )
+ {
+ callback_list_t::iterator curiter = iter++;
+ curiter->first(curiter->second);
+ }
+}
+
+// Shim class to allow arbitrary boost::bind
+// expressions to be run as one-time idle callbacks.
+class OnIdleCallbackOneTime
+{
+public:
+ OnIdleCallbackOneTime(nullary_func_t callable):
+ mCallable(callable)
+ {
+ }
+ static void onIdle(void *data)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, data);
+ OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
+ self->call();
+ delete self;
+ }
+ void call()
+ {
+ mCallable();
+ }
+private:
+ nullary_func_t mCallable;
+};
+
+void doOnIdleOneTime(nullary_func_t callable)
+{
+ OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
+ gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
+}
+
+// Shim class to allow generic boost functions to be run as
+// recurring idle callbacks. Callable should return true when done,
+// false to continue getting called.
+class OnIdleCallbackRepeating
+{
+public:
+ OnIdleCallbackRepeating(bool_func_t callable):
+ mCallable(callable)
+ {
+ }
+ // Will keep getting called until the callable returns true.
+ static void onIdle(void *data)
+ {
+ OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
+ bool done = self->call();
+ if (done)
+ {
+ gIdleCallbacks.deleteFunction(onIdle, data);
+ delete self;
+ }
+ }
+ bool call()
+ {
+ return mCallable();
+ }
+private:
+ bool_func_t mCallable;
+};
+
+void doOnIdleRepeating(bool_func_t callable)
+{
+ OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
+ gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
+}
+
+class NullaryFuncEventTimer: public LLEventTimer
+{
+public:
+ NullaryFuncEventTimer(nullary_func_t callable, F32 seconds):
+ LLEventTimer(seconds),
+ mCallable(callable)
+ {
+ }
+
+private:
+ BOOL tick()
+ {
+ mCallable();
+ return TRUE;
+ }
+
+ nullary_func_t mCallable;
+};
+
+// Call a given callable once after specified interval.
+void doAfterInterval(nullary_func_t callable, F32 seconds)
+{
+ new NullaryFuncEventTimer(callable, seconds);
+}
+
+class BoolFuncEventTimer: public LLEventTimer
+{
+public:
+ BoolFuncEventTimer(bool_func_t callable, F32 seconds):
+ LLEventTimer(seconds),
+ mCallable(callable)
+ {
+ }
+private:
+ BOOL tick()
+ {
+ return mCallable();
+ }
+
+ bool_func_t mCallable;
+};
+
+// Call a given callable every specified number of seconds, until it returns true.
+void doPeriodically(bool_func_t callable, F32 seconds)
+{
+ new BoolFuncEventTimer(callable, seconds);
+}
diff --git a/indra/llcommon/llcallbacklist.h b/indra/llcommon/llcallbacklist.h
new file mode 100644
index 0000000000..89716cd74c
--- /dev/null
+++ b/indra/llcommon/llcallbacklist.h
@@ -0,0 +1,79 @@
+/**
+ * @file llcallbacklist.h
+ * @brief A simple list of callback functions to call.
+ *
+ * $LicenseInfo:firstyear=2001&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_LLCALLBACKLIST_H
+#define LL_LLCALLBACKLIST_H
+
+#include "llstl.h"
+#include <boost/function.hpp>
+#include <list>
+
+class LLCallbackList
+{
+public:
+ typedef void (*callback_t)(void*);
+
+ typedef std::pair< callback_t,void* > callback_pair_t;
+ // NOTE: It is confirmed that we DEPEND on the order provided by using a list :(
+ //
+ typedef std::list< callback_pair_t > callback_list_t;
+
+ LLCallbackList();
+ ~LLCallbackList();
+
+ void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
+ bool containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
+ bool deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
+ void callFunctions(); // calls all functions
+ void deleteAllFunctions();
+
+ static void test();
+
+protected:
+
+ inline callback_list_t::iterator find(callback_t func, void *data);
+
+ callback_list_t mCallbackList;
+};
+
+typedef boost::function<void ()> nullary_func_t;
+typedef boost::function<bool ()> bool_func_t;
+
+// Call a given callable once in idle loop.
+void doOnIdleOneTime(nullary_func_t callable);
+
+// Repeatedly call a callable in idle loop until it returns true.
+void doOnIdleRepeating(bool_func_t callable);
+
+// Call a given callable once after specified interval.
+void doAfterInterval(nullary_func_t callable, F32 seconds);
+
+// Call a given callable every specified number of seconds, until it returns true.
+void doPeriodically(bool_func_t callable, F32 seconds);
+
+extern LLCallbackList gIdleCallbacks;
+
+#endif
diff --git a/indra/llcommon/lleventcoro.cpp b/indra/llcommon/lleventcoro.cpp
index 66cc7cada0..c9bfcacedc 100755
--- a/indra/llcommon/lleventcoro.cpp
+++ b/indra/llcommon/lleventcoro.cpp
@@ -45,14 +45,14 @@ namespace
{
/**
- * waitForEventOn() permits a coroutine to temporarily listen on an
+ * suspendUntilEventOn() permits a coroutine to temporarily listen on an
* LLEventPump any number of times. We don't really want to have to ask
* the caller to label each such call with a distinct string; the whole
- * point of waitForEventOn() is to present a nice sequential interface to
+ * point of suspendUntilEventOn() is to present a nice sequential interface to
* the underlying LLEventPump-with-named-listeners machinery. So we'll use
* LLEventPump::inventName() to generate a distinct name for each
* temporary listener. On the other hand, because a given coroutine might
- * call waitForEventOn() any number of times, we don't really want to
+ * call suspendUntilEventOn() any number of times, we don't really want to
* consume an arbitrary number of generated inventName()s: that namespace,
* though large, is nonetheless finite. So we memoize an invented name for
* each distinct coroutine instance.
@@ -73,7 +73,7 @@ std::string listenerNameForCoro()
}
/**
- * Implement behavior described for postAndWait()'s @a replyPumpNamePath
+ * Implement behavior described for postAndSuspend()'s @a replyPumpNamePath
* parameter:
*
* * If <tt>path.isUndefined()</tt>, do nothing.
@@ -145,15 +145,15 @@ void storeToLLSDPath(LLSD& dest, const LLSD& rawPath, const LLSD& value)
} // anonymous
-void llcoro::yield()
+void llcoro::suspend()
{
// By viewer convention, we post an event on the "mainloop" LLEventPump
// each iteration of the main event-handling loop. So waiting for a single
- // event on "mainloop" gives us a one-frame yield.
- waitForEventOn("mainloop");
+ // event on "mainloop" gives us a one-frame suspend.
+ suspendUntilEventOn("mainloop");
}
-LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+LLSD llcoro::postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath)
{
// declare the future
@@ -171,7 +171,7 @@ LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& request
// request event.
LLSD modevent(event);
storeToLLSDPath(modevent, replyPumpNamePath, replyPump.getPump().getName());
- LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+ LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName
<< " posting to " << requestPump.getPump().getName()
<< LL_ENDL;
@@ -179,7 +179,7 @@ LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& request
// << ": " << modevent << LL_ENDL;
requestPump.getPump().post(modevent);
}
- LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+ LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName
<< " about to wait on LLEventPump " << replyPump.getPump().getName()
<< LL_ENDL;
// trying to dereference ("resolve") the future makes us wait for it
@@ -189,7 +189,7 @@ LLSD llcoro::postAndWait(const LLSD& event, const LLEventPumpOrPumpName& request
llcoro::Suspending suspended;
value = *future;
} // destroy Suspending as soon as we're back
- LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << listenerName
+ LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << listenerName
<< " resuming with " << value << LL_ENDL;
// returning should disconnect the connection
return value;
@@ -199,7 +199,7 @@ namespace
{
/**
- * This helper is specifically for the two-pump version of waitForEventOn().
+ * This helper is specifically for the two-pump version of suspendUntilEventOn().
* We use a single future object, but we want to listen on two pumps with it.
* Since we must still adapt from (the callable constructed by)
* boost::dcoroutines::make_callback() (void return) to provide an event
@@ -242,7 +242,7 @@ WaitForEventOnHelper<LISTENER> wfeoh(const LISTENER& listener, int discriminator
namespace llcoro
{
-LLEventWithID postAndWait2(const LLSD& event,
+LLEventWithID postAndSuspend2(const LLSD& event,
const LLEventPumpOrPumpName& requestPump,
const LLEventPumpOrPumpName& replyPump0,
const LLEventPumpOrPumpName& replyPump1,
@@ -270,12 +270,12 @@ LLEventWithID postAndWait2(const LLSD& event,
replyPump0.getPump().getName());
storeToLLSDPath(modevent, replyPump1NamePath,
replyPump1.getPump().getName());
- LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
+ LL_DEBUGS("lleventcoro") << "postAndSuspend2(): coroutine " << name
<< " posting to " << requestPump.getPump().getName()
<< ": " << modevent << LL_ENDL;
requestPump.getPump().post(modevent);
}
- LL_DEBUGS("lleventcoro") << "postAndWait2(): coroutine " << name
+ LL_DEBUGS("lleventcoro") << "postAndSuspend2(): coroutine " << name
<< " about to wait on LLEventPumps " << replyPump0.getPump().getName()
<< ", " << replyPump1.getPump().getName() << LL_ENDL;
// trying to dereference ("resolve") the future makes us wait for it
@@ -285,7 +285,7 @@ LLEventWithID postAndWait2(const LLSD& event,
llcoro::Suspending suspended;
value = *future;
} // destroy Suspending as soon as we're back
- LL_DEBUGS("lleventcoro") << "postAndWait(): coroutine " << name
+ LL_DEBUGS("lleventcoro") << "postAndSuspend(): coroutine " << name
<< " resuming with (" << value.first << ", " << value.second << ")"
<< LL_ENDL;
// returning should disconnect both connections
diff --git a/indra/llcommon/lleventcoro.h b/indra/llcommon/lleventcoro.h
index e2ce4bb193..6fda3d2572 100755
--- a/indra/llcommon/lleventcoro.h
+++ b/indra/llcommon/lleventcoro.h
@@ -106,34 +106,33 @@ VoidListener<LISTENER> voidlistener(const LISTENER& listener)
* runs without suspending for nontrivial time, sprinkle in calls to this
* function to avoid stalling the rest of the viewer processing.
*/
-void yield();
+void suspend();
/**
- * Post specified LLSD event on the specified LLEventPump, then wait for a
+ * Post specified LLSD event on the specified LLEventPump, then suspend for a
* response on specified other LLEventPump. This is more than mere
* convenience: the difference between this function and the sequence
* @code
* requestPump.post(myEvent);
- * LLSD reply = waitForEventOn(replyPump);
+ * LLSD reply = suspendUntilEventOn(replyPump);
* @endcode
* is that the sequence above fails if the reply is posted immediately on
* @a replyPump, that is, before <tt>requestPump.post()</tt> returns. In the
* sequence above, the running coroutine isn't even listening on @a replyPump
- * until <tt>requestPump.post()</tt> returns and @c waitForEventOn() is
+ * until <tt>requestPump.post()</tt> returns and @c suspendUntilEventOn() is
* entered. Therefore, the coroutine completely misses an immediate reply
- * event, making it wait indefinitely.
+ * event, making it suspend indefinitely.
*
- * By contrast, postAndWait() listens on the @a replyPump @em before posting
+ * By contrast, postAndSuspend() listens on the @a replyPump @em before posting
* the specified LLSD event on the specified @a requestPump.
*
- * @param self The @c self object passed into a coroutine
* @param event LLSD data to be posted on @a requestPump
* @param requestPump an LLEventPump on which to post @a event. Pass either
* the LLEventPump& or its string name. However, if you pass a
* default-constructed @c LLEventPumpOrPumpName, we skip the post() call.
- * @param replyPump an LLEventPump on which postAndWait() will listen for a
+ * @param replyPump an LLEventPump on which postAndSuspend() will listen for a
* reply. Pass either the LLEventPump& or its string name. The calling
- * coroutine will wait until that reply arrives. (If you're concerned about a
+ * coroutine will suspend until that reply arrives. (If you're concerned about a
* reply that might not arrive, please see also LLEventTimeout.)
* @param replyPumpNamePath specifies the location within @a event in which to
* store <tt>replyPump.getName()</tt>. This is a strictly optional convenience
@@ -156,21 +155,21 @@ void yield();
* @a replyPumpNamePath specifies the entry in the lowest-level structure in
* @a event into which to store <tt>replyPump.getName()</tt>.
*/
-LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+LLSD postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
const LLEventPumpOrPumpName& replyPump, const LLSD& replyPumpNamePath=LLSD());
/// Wait for the next event on the specified LLEventPump. Pass either the
/// LLEventPump& or its string name.
inline
-LLSD waitForEventOn(const LLEventPumpOrPumpName& pump)
+LLSD suspendUntilEventOn(const LLEventPumpOrPumpName& pump)
{
- // This is now a convenience wrapper for postAndWait().
- return postAndWait(LLSD(), LLEventPumpOrPumpName(), pump);
+ // This is now a convenience wrapper for postAndSuspend().
+ return postAndSuspend(LLSD(), LLEventPumpOrPumpName(), pump);
}
} // namespace llcoro
-/// return type for two-pump variant of waitForEventOn()
+/// return type for two-pump variant of suspendUntilEventOn()
typedef std::pair<LLSD, int> LLEventWithID;
namespace llcoro
@@ -178,7 +177,7 @@ namespace llcoro
/**
* This function waits for a reply on either of two specified LLEventPumps.
- * Otherwise, it closely resembles postAndWait(); please see the documentation
+ * Otherwise, it closely resembles postAndSuspend(); please see the documentation
* for that function for detailed parameter info.
*
* While we could have implemented the single-pump variant in terms of this
@@ -193,19 +192,19 @@ namespace llcoro
* the index of the pump on which it arrived (0 or 1).
*
* @note
- * I'd have preferred to overload the name postAndWait() for both signatures.
+ * I'd have preferred to overload the name postAndSuspend() for both signatures.
* But consider the following ambiguous call:
* @code
- * postAndWait(LLSD(), requestPump, replyPump, "someString");
+ * postAndSuspend(LLSD(), requestPump, replyPump, "someString");
* @endcode
* "someString" could be converted to either LLSD (@a replyPumpNamePath for
* the single-pump function) or LLEventOrPumpName (@a replyPump1 for two-pump
* function).
*
- * It seems less burdensome to write postAndWait2() than to write either
+ * It seems less burdensome to write postAndSuspend2() than to write either
* LLSD("someString") or LLEventOrPumpName("someString").
*/
-LLEventWithID postAndWait2(const LLSD& event,
+LLEventWithID postAndSuspend2(const LLSD& event,
const LLEventPumpOrPumpName& requestPump,
const LLEventPumpOrPumpName& replyPump0,
const LLEventPumpOrPumpName& replyPump1,
@@ -217,17 +216,17 @@ LLEventWithID postAndWait2(const LLSD& event,
*/
inline
LLEventWithID
-waitForEventOn(const LLEventPumpOrPumpName& pump0, const LLEventPumpOrPumpName& pump1)
+suspendUntilEventOn(const LLEventPumpOrPumpName& pump0, const LLEventPumpOrPumpName& pump1)
{
- // This is now a convenience wrapper for postAndWait2().
- return postAndWait2(LLSD(), LLEventPumpOrPumpName(), pump0, pump1);
+ // This is now a convenience wrapper for postAndSuspend2().
+ return postAndSuspend2(LLSD(), LLEventPumpOrPumpName(), pump0, pump1);
}
/**
- * Helper for the two-pump variant of waitForEventOn(), e.g.:
+ * Helper for the two-pump variant of suspendUntilEventOn(), e.g.:
*
* @code
- * LLSD reply = errorException(waitForEventOn(replyPump, errorPump),
+ * LLSD reply = errorException(suspendUntilEventOn(replyPump, errorPump),
* "error response from login.cgi");
* @endcode
*
@@ -287,7 +286,7 @@ LL_COMMON_API LLSD errorLog(const LLEventWithID& result, const std::string& desc
* 2. Provide its actual name to the event API in question as the name of the
* reply LLEventPump.
* 3. Initiate the request to the event API.
- * 4. Call your LLEventTempStream's wait() method to wait for the reply.
+ * 4. Call your LLEventTempStream's suspend() method to suspend for the reply.
* 5. Let the LLCoroEventPump go out of scope.
*/
class LL_COMMON_API LLCoroEventPump
@@ -305,15 +304,15 @@ public:
/**
* Wait for an event on this LLEventPump.
*/
- LLSD wait()
+ LLSD suspend()
{
- return llcoro::waitForEventOn(mPump);
+ return llcoro::suspendUntilEventOn(mPump);
}
- LLSD postAndWait(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
+ LLSD postAndSuspend(const LLSD& event, const LLEventPumpOrPumpName& requestPump,
const LLSD& replyPumpNamePath=LLSD())
{
- return llcoro::postAndWait(event, requestPump, mPump, replyPumpNamePath);
+ return llcoro::postAndSuspend(event, requestPump, mPump, replyPumpNamePath);
}
private:
@@ -349,49 +348,49 @@ public:
/// request pump 1
LLEventPump& getPump1() { return mPump1; }
- /// waitForEventOn(either of our two LLEventPumps)
- LLEventWithID wait()
+ /// suspendUntilEventOn(either of our two LLEventPumps)
+ LLEventWithID suspend()
{
- return llcoro::waitForEventOn(mPump0, mPump1);
+ return llcoro::suspendUntilEventOn(mPump0, mPump1);
}
- /// errorException(wait())
- LLSD waitWithException()
+ /// errorException(suspend())
+ LLSD suspendWithException()
{
- return llcoro::errorException(wait(), std::string("Error event on ") + getName1());
+ return llcoro::errorException(suspend(), std::string("Error event on ") + getName1());
}
- /// errorLog(wait())
- LLSD waitWithLog()
+ /// errorLog(suspend())
+ LLSD suspendWithLog()
{
- return llcoro::errorLog(wait(), std::string("Error event on ") + getName1());
+ return llcoro::errorLog(suspend(), std::string("Error event on ") + getName1());
}
- LLEventWithID postAndWait(const LLSD& event,
+ LLEventWithID postAndSuspend(const LLSD& event,
const LLEventPumpOrPumpName& requestPump,
const LLSD& replyPump0NamePath=LLSD(),
const LLSD& replyPump1NamePath=LLSD())
{
- return llcoro::postAndWait2(event, requestPump, mPump0, mPump1,
+ return llcoro::postAndSuspend2(event, requestPump, mPump0, mPump1,
replyPump0NamePath, replyPump1NamePath);
}
- LLSD postAndWaitWithException(const LLSD& event,
+ LLSD postAndSuspendWithException(const LLSD& event,
const LLEventPumpOrPumpName& requestPump,
const LLSD& replyPump0NamePath=LLSD(),
const LLSD& replyPump1NamePath=LLSD())
{
- return llcoro::errorException(postAndWait(event, requestPump,
+ return llcoro::errorException(postAndSuspend(event, requestPump,
replyPump0NamePath, replyPump1NamePath),
std::string("Error event on ") + getName1());
}
- LLSD postAndWaitWithLog(const LLSD& event,
+ LLSD postAndSuspendWithLog(const LLSD& event,
const LLEventPumpOrPumpName& requestPump,
const LLSD& replyPump0NamePath=LLSD(),
const LLSD& replyPump1NamePath=LLSD())
{
- return llcoro::errorLog(postAndWait(event, requestPump,
+ return llcoro::errorLog(postAndSuspend(event, requestPump,
replyPump0NamePath, replyPump1NamePath),
std::string("Error event on ") + getName1());
}
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index ae11988df8..3a8eabac09 100755
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -2176,8 +2176,7 @@ void* ll_aligned_malloc_fallback( size_t size, int align )
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
- unsigned int for_alloc = sysinfo.dwPageSize;
- while(for_alloc < size) for_alloc += sysinfo.dwPageSize;
+ unsigned int for_alloc = (size/sysinfo.dwPageSize + !!(size%sysinfo.dwPageSize)) * sysinfo.dwPageSize;
void *p = VirtualAlloc(NULL, for_alloc+sysinfo.dwPageSize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
if(NULL == p) {
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index c4c9cc0566..0fb257aab1 100755
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -28,6 +28,7 @@
#include "linden_common.h"
#include "llunits.h"
+#include "stdtypes.h"
#if !LL_WINDOWS
#include <stdint.h>
#endif
@@ -59,7 +60,7 @@ class LLMutex ;
LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
#ifdef SHOW_ASSERT
-#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
+#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(uintptr_t(ptr),((U32)alignment))
#else
#define ll_assert_aligned(ptr,alignment)
#endif
@@ -69,13 +70,13 @@ LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)
{
return reinterpret_cast<T*>(
- (reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF);
+ (uintptr_t(address) + 0xF) & ~0xF);
}
template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
{
return reinterpret_cast<T*>(
- (reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F);
+ (uintptr_t(address) + 0x3F) & ~0x3F);
}
#if LL_LINUX || LL_DARWIN
@@ -97,7 +98,7 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
// for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
- // change preprocessro code to: #if 1 && defined(LL_WINDOWS)
+ // change preprocessor code to: #if 1 && defined(LL_WINDOWS)
#if 0 && defined(LL_WINDOWS)
void* ll_aligned_malloc_fallback( size_t size, int align );
diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h
index 3659a319a2..ea535cee86 100644
--- a/indra/llcommon/llmutex.h
+++ b/indra/llcommon/llmutex.h
@@ -33,6 +33,10 @@
#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO)
+#if MUTEX_DEBUG
+#include <map>
+#endif
+
struct apr_thread_mutex_t;
struct apr_pool_t;
struct apr_thread_cond_t;
diff --git a/indra/llcommon/llprocess.cpp b/indra/llcommon/llprocess.cpp
index 715df36f39..44f56daf2d 100755
--- a/indra/llcommon/llprocess.cpp
+++ b/indra/llcommon/llprocess.cpp
@@ -710,7 +710,7 @@ LLProcess::LLProcess(const LLSDOrParams& params):
// Tie the lifespan of this child process to the lifespan of our APR
// pool: on destruction of the pool, forcibly kill the process. Tell
- // APR to try SIGTERM and wait 3 seconds. If that didn't work, use
+ // APR to try SIGTERM and suspend 3 seconds. If that didn't work, use
// SIGKILL.
apr_pool_note_subprocess(gAPRPoolp, &mProcess, APR_KILL_AFTER_TIMEOUT);
|*==========================================================================*/
@@ -738,8 +738,11 @@ LLProcess::LLProcess(const LLSDOrParams& params):
{
mPipes.replace(i, new ReadPipeImpl(desc, pipe, FILESLOT(i)));
}
- LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name()
- << "('" << desc << "')" << LL_ENDL;
+ // Removed temporaily for Xcode 7 build tests: error was:
+ // "error: expression with side effects will be evaluated despite
+ // being used as an operand to 'typeid' [-Werror,-Wpotentially-evaluated-expression]""
+ //LL_DEBUGS("LLProcess") << "Instantiating " << typeid(mPipes[i]).name()
+ // << "('" << desc << "')" << LL_ENDL;
}
}
@@ -986,9 +989,9 @@ void LLProcess::handle_status(int reason, int status)
// wi->rv = apr_proc_wait(wi->child, &wi->rc, &wi->why, APR_NOWAIT);
// It's just wrong to call apr_proc_wait() here. The only way APR knows to
// call us with APR_OC_REASON_DEATH is that it's already reaped this child
- // process, so calling wait() will only produce "huh?" from the OS. We
+ // process, so calling suspend() will only produce "huh?" from the OS. We
// must rely on the status param passed in, which unfortunately comes
- // straight from the OS wait() call, which means we have to decode it by
+ // straight from the OS suspend() call, which means we have to decode it by
// hand.
mStatus = interpret_status(status);
LL_INFOS("LLProcess") << getStatusString() << LL_ENDL;
diff --git a/indra/llcommon/llsdjson.cpp b/indra/llcommon/llsdjson.cpp
index 2afdba388a..8caaaee534 100644
--- a/indra/llcommon/llsdjson.cpp
+++ b/indra/llcommon/llsdjson.cpp
@@ -76,3 +76,51 @@ LLSD LlsdFromJson(const Json::Value &val)
}
return result;
}
+
+//=========================================================================
+Json::Value LlsdToJson(const LLSD &val)
+{
+ Json::Value result;
+
+ switch (val.type())
+ {
+ case LLSD::TypeUndefined:
+ result = Json::Value::null;
+ break;
+ case LLSD::TypeBoolean:
+ result = Json::Value(static_cast<bool>(val.asBoolean()));
+ break;
+ case LLSD::TypeInteger:
+ result = Json::Value(static_cast<int>(val.asInteger()));
+ break;
+ case LLSD::TypeReal:
+ result = Json::Value(static_cast<double>(val.asReal()));
+ break;
+ case LLSD::TypeURI:
+ case LLSD::TypeDate:
+ case LLSD::TypeUUID:
+ case LLSD::TypeString:
+ result = Json::Value(val.asString());
+ break;
+ case LLSD::TypeMap:
+ result = Json::Value(Json::objectValue);
+ for (LLSD::map_const_iterator it = val.beginMap(); it != val.endMap(); ++it)
+ {
+ result[it->first] = LlsdToJson(it->second);
+ }
+ break;
+ case LLSD::TypeArray:
+ result = Json::Value(Json::arrayValue);
+ for (LLSD::array_const_iterator it = val.beginArray(); it != val.endArray(); ++it)
+ {
+ result.append(LlsdToJson(*it));
+ }
+ break;
+ case LLSD::TypeBinary:
+ default:
+ LL_ERRS("LlsdToJson") << "Unsupported conversion to JSON from LLSD type (" << val.type() << ")." << LL_ENDL;
+ break;
+ }
+
+ return result;
+}
diff --git a/indra/llcommon/llsdjson.h b/indra/llcommon/llsdjson.h
index cdf9fed500..2be7112404 100644
--- a/indra/llcommon/llsdjson.h
+++ b/indra/llcommon/llsdjson.h
@@ -55,5 +55,23 @@
/// Order is preserved for an array but not for objects.
LLSD LlsdFromJson(const Json::Value &val);
+/// Convert an LLSD object into Parsed JSON object maintaining member names and
+/// array indexs.
+///
+/// Types are converted as follows:
+/// LLSD Type | JSON Type
+/// --------------+----------------
+/// TypeUndefined | null
+/// TypeBoolean | boolean
+/// TypeInteger | integer
+/// TypeReal | real/numeric
+/// TypeString | string
+/// TypeURI | string
+/// TypeDate | string
+/// TypeUUID | string
+/// TypeMap | object
+/// TypeArray | array
+/// TypeBinary | unsupported
+Json::Value LlsdToJson(const LLSD &val);
#endif // LL_LLSDJSON_H
diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h
index 02f10fa2ba..0435cb8a08 100755
--- a/indra/llcommon/llstl.h
+++ b/indra/llcommon/llstl.h
@@ -27,6 +27,7 @@
#ifndef LL_LLSTL_H
#define LL_LLSTL_H
+#include "stdtypes.h"
#include <functional>
#include <algorithm>
#include <map>
@@ -272,6 +273,7 @@ inline T get_if_there(const std::map<K,T>& inmap, const K& key, T default_value)
}
};
+// Useful for replacing the removeObj() functionality of LLDynamicArray
// Example:
// for (std::vector<T>::iterator iter = mList.begin(); iter != mList.end(); )
// {
@@ -530,7 +532,7 @@ bool before(const std::type_info* lhs, const std::type_info* rhs)
return strcmp(lhs->name(), rhs->name()) < 0;
#else // not Linux, or gcc 4.4+
// Just use before(), as we normally would
- return lhs->before(*rhs);
+ return lhs->before(*rhs) ? true : false;
#endif
}
diff --git a/indra/llcommon/lluriparser.cpp b/indra/llcommon/lluriparser.cpp
index d98bc297e5..82d0dc8b4b 100644
--- a/indra/llcommon/lluriparser.cpp
+++ b/indra/llcommon/lluriparser.cpp
@@ -238,12 +238,12 @@ void LLUriParser::glueSecond(std::string& uri) const
{
uri += '?';
uri += mQuery;
+ }
- if (mFragment.size())
- {
- uri += '#';
- uri += mFragment;
- }
+ if (mFragment.size())
+ {
+ uri += '#';
+ uri += mFragment;
}
}
diff --git a/indra/llcommon/tests/lleventcoro_test.cpp b/indra/llcommon/tests/lleventcoro_test.cpp
index 00be5035f2..1ee79e9eb6 100755
--- a/indra/llcommon/tests/lleventcoro_test.cpp
+++ b/indra/llcommon/tests/lleventcoro_test.cpp
@@ -129,8 +129,8 @@ typedef coroutine<std::string::iterator(void)> match_coroutine_type;
*****************************************************************************/
/// Simulate an event API whose response is immediate: sent on receipt of the
/// initial request, rather than after some delay. This is the case that
-/// distinguishes postAndWait() from calling post(), then calling
-/// waitForEventOn().
+/// distinguishes postAndSuspend() from calling post(), then calling
+/// suspendUntilEventOn().
class ImmediateAPI
{
public:
@@ -241,13 +241,13 @@ namespace tut
// declare the future
boost::dcoroutines::future<LLSD> future(self);
- // tell the future what to wait for
+ // tell the future what to suspend for
LLTempBoundListener connection(
LLEventPumps::instance().obtain("source").listen("coro", voidlistener(boost::dcoroutines::make_callback(future))));
ensure("Not yet", ! future);
// attempting to dereference ("resolve") the future causes the calling
- // coroutine to wait for it
- debug("about to wait");
+ // coroutine to suspend for it
+ debug("about to suspend");
result = *future;
ensure("Got it", future);
}
@@ -269,9 +269,9 @@ namespace tut
coro(std::nothrow);
// When the coroutine waits for the event pump, it returns here.
debug("about to send");
- // Satisfy the wait.
+ // Satisfy the suspend.
LLEventPumps::instance().obtain("source").post("received");
- // Now wait for the coroutine to complete.
+ // Now suspend for the coroutine to complete.
ensure("coroutine complete", ! coro);
// ensure the coroutine ran and woke up again with the intended result
ensure_equals(result.asString(), "received");
@@ -281,7 +281,7 @@ namespace tut
{
BEGIN
{
- result = waitForEventOn("source");
+ result = suspendUntilEventOn("source");
}
END
}
@@ -303,7 +303,7 @@ namespace tut
{
BEGIN
{
- LLEventWithID pair = waitForEventOn("reply", "error");
+ LLEventWithID pair = suspendUntilEventOn("reply", "error");
result = pair.first;
which = pair.second;
debug(STRINGIZE("result = " << result << ", which = " << which));
@@ -347,7 +347,7 @@ namespace tut
{
LLCoroEventPump waiter;
replyName = waiter.getName();
- result = waiter.wait();
+ result = waiter.suspend();
}
END
}
@@ -372,7 +372,7 @@ namespace tut
LLCoroEventPumps waiter;
replyName = waiter.getName0();
errorName = waiter.getName1();
- LLEventWithID pair(waiter.wait());
+ LLEventWithID pair(waiter.suspend());
result = pair.first;
which = pair.second;
}
@@ -414,7 +414,7 @@ namespace tut
LLCoroEventPumps waiter;
replyName = waiter.getName0();
errorName = waiter.getName1();
- result = waiter.waitWithException();
+ result = waiter.suspendWithException();
}
END
}
@@ -441,7 +441,7 @@ namespace tut
errorName = waiter.getName1();
try
{
- result = waiter.waitWithException();
+ result = waiter.suspendWithException();
debug("no exception");
}
catch (const LLErrorEvent& e)
@@ -474,7 +474,7 @@ namespace tut
LLCoroEventPumps waiter;
replyName = waiter.getName0();
errorName = waiter.getName1();
- result = waiter.waitWithLog();
+ result = waiter.suspendWithLog();
}
END
}
@@ -502,7 +502,7 @@ namespace tut
WrapLLErrs capture;
try
{
- result = waiter.waitWithLog();
+ result = waiter.suspendWithLog();
debug("no exception");
}
catch (const WrapLLErrs::FatalException& e)
@@ -532,7 +532,7 @@ namespace tut
{
BEGIN
{
- result = postAndWait(LLSDMap("value", 17), // request event
+ result = postAndSuspend(LLSDMap("value", 17), // request event
immediateAPI.getPump(), // requestPump
"reply1", // replyPump
"reply"); // request["reply"] = name
@@ -554,7 +554,7 @@ namespace tut
{
BEGIN
{
- LLEventWithID pair = ::postAndWait2(LLSDMap("value", 18),
+ LLEventWithID pair = ::postAndSuspend2(LLSDMap("value", 18),
immediateAPI.getPump(),
"reply2",
"error2",
@@ -582,7 +582,7 @@ namespace tut
{
BEGIN
{
- LLEventWithID pair = ::postAndWait2(LLSDMap("value", 18)("fail", LLSD()),
+ LLEventWithID pair = ::postAndSuspend2(LLSDMap("value", 18)("fail", LLSD()),
immediateAPI.getPump(),
"reply2",
"error2",
@@ -611,7 +611,7 @@ namespace tut
BEGIN
{
LLCoroEventPump waiter;
- result = waiter.postAndWait(LLSDMap("value", 17),
+ result = waiter.postAndSuspend(LLSDMap("value", 17),
immediateAPI.getPump(), "reply");
}
END
@@ -632,7 +632,7 @@ namespace tut
BEGIN
{
LLCoroEventPumps waiter;
- LLEventWithID pair(waiter.postAndWait(LLSDMap("value", 23),
+ LLEventWithID pair(waiter.postAndSuspend(LLSDMap("value", 23),
immediateAPI.getPump(), "reply", "error"));
result = pair.first;
which = pair.second;
@@ -657,7 +657,7 @@ namespace tut
{
LLCoroEventPumps waiter;
LLEventWithID pair(
- waiter.postAndWait(LLSDMap("value", 23)("fail", LLSD()),
+ waiter.postAndSuspend(LLSDMap("value", 23)("fail", LLSD()),
immediateAPI.getPump(), "reply", "error"));
result = pair.first;
which = pair.second;
@@ -681,7 +681,7 @@ namespace tut
BEGIN
{
LLCoroEventPumps waiter;
- result = waiter.postAndWaitWithException(LLSDMap("value", 8),
+ result = waiter.postAndSuspendWithException(LLSDMap("value", 8),
immediateAPI.getPump(), "reply", "error");
}
END
@@ -704,7 +704,7 @@ namespace tut
LLCoroEventPumps waiter;
try
{
- result = waiter.postAndWaitWithException(
+ result = waiter.postAndSuspendWithException(
LLSDMap("value", 9)("fail", LLSD()),
immediateAPI.getPump(), "reply", "error");
debug("no exception");
@@ -734,7 +734,7 @@ namespace tut
BEGIN
{
LLCoroEventPumps waiter;
- result = waiter.postAndWaitWithLog(LLSDMap("value", 30),
+ result = waiter.postAndSuspendWithLog(LLSDMap("value", 30),
immediateAPI.getPump(), "reply", "error");
}
END
@@ -758,7 +758,7 @@ namespace tut
WrapLLErrs capture;
try
{
- result = waiter.postAndWaitWithLog(
+ result = waiter.postAndSuspendWithLog(
LLSDMap("value", 31)("fail", LLSD()),
immediateAPI.getPump(), "reply", "error");
debug("no exception");