Skip to content
Snippets Groups Projects
  1. Mar 25, 2020
    • Nat Goodspeed's avatar
      aaae4478
    • Nat Goodspeed's avatar
      DRTVWR-476: Add LLEventTimer::run_every(), run_at(), run_after(). · 2f866c9d
      Nat Goodspeed authored
      Also add corresponding LLEventTimeout::post_every(), post_at(), post_after()
      methods.
      2f866c9d
    • Nat Goodspeed's avatar
      DRTVWR-476: Eliminate static LLEventPump factory maps. · 95a218fc
      Nat Goodspeed authored
      Having a map from std::string to a factory function returning LLEventPump* is
      a cool idea, especially since you could statically populate such a map with
      string literals and little lambdas.
      
      Unfortunately, static initialization of any data is a bad idea when control
      can reach consuming code before that module's static data are constructed.
      
      Since LLEventPumps is already an LLSingleton, it's simple enough to make its
      map non-static and initialize it in the constructor.
      
      But another recent static factory-function map was introduced in
      llleaplistener.cpp to support the LLLeapListener::newpump() operation. That
      involves no LLSingletons.
      
      Introduce LLEventPumps::make(name, tweak, type) to instantiate an LLEventPump
      subclass of the specified type with specified (name, tweak) parameters.
      Instances returned by make() are owned by LLEventPumps, as with obtain().
      Introduce LLEventPumps::BadType exception for when the type string isn't
      recognized.
      
      LLEventPumps::obtain() can then simply call make() when the specified instance
      name doesn't already exist. The configuration data used internally by obtain()
      becomes { string instance name, string subclass name }. Although this too is
      currently initialized in the LLEventPumps constructor, migrating it to a
      configuration file would now be far more straightforward than before.
      
      LLLeapListener::newpump(), too, can call LLEventPumps::make() with the
      caller-specified type string. This eliminates that static factory map.
      newpump() must catch BadType and report the error back to its invoker.
      
      Given that the LLEventPump subclass instances returned by make() are owned by
      LLEventPumps rather than LLLeapListener, there is no further need for the
      LLLeapListener::mEventPumps ptr_map, which was used only to manage lifetime.
      Also remove LLLeapListener's "killpump" operation since LLEventPumps provides
      no corresponding functionality.
      95a218fc
    • Nat Goodspeed's avatar
      DRTVWR-476: Seems gcc 4.8 forbids brace-init of reference vars. · 3ec92b0e
      Nat Goodspeed authored
      Although this is legal, apparently there was a bug in the C++11 standard (to
      which gcc 4.8 conforms) that was subsequently fixed in the standard (and thus
      in gcc 4.9). Thanks Henri Beauchamp.
      3ec92b0e
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: Kill LLEventQueue, per-frame LLEventPump::flush() calls. · 79a3e391
      Nat Goodspeed authored
      No one uses LLEventQueue to defer posted events until the next mainloop tick
      -- and with LLCoros moving to Boost.Fiber, cross-coroutine event posting works
      that way anyway, making LLEventQueue pretty unnecessary.
      
      The static RegisterFlush instance in llevents.cpp was used to call
      LLEventPumps::flush() once per mainloop tick, which in turn called flush() on
      every registered LLEventPump. But the only reason for that mechanism was to
      support LLEventQueue. In fact, when LLEventMailDrop overrode its flush()
      method for something quite different, it was startling to find that the new
      flush() override was being called once per frame -- which caused at least one
      fairly mysterious bug. Remove RegisterFlush. Both LLEventPumps::flush() and
      LLEventPump::flush() remain for now, though intended usage is unclear.
      
      Eliminating LLEventQueue means we must at least repurpose
      LLEventPumps::mQueueNames, a map intended to make LLEventPumps::obtain()
      instantiate an LLEventQueue rather than the default LLEventPump. Replace it
      with mFactories, a map from desired instance name to a callable returning
      LLEventPump*. New map initialization syntax plus lambda support allows us to
      populate that map at compile time with little lambdas returning the correct
      subclass instance.
      
      Similarly, LLLeapListener::newpump() used to check the ["type"] entry in the
      LLSD request specifically for "LLEventQueue". Introduce another such map in
      llleaplistener.cpp for potential future extensibility.
      
      Eliminate the LLEventQueue-specific test.
      79a3e391
    • Nat Goodspeed's avatar
      DRTVWR-476: Introduce LLEventMailDrop::discard() (instead of flush()). · 6805e82a
      Nat Goodspeed authored
      Overriding virtual LLEventPump::flush() for the semantic of discarding
      LLEventMailDrop's queued events turns out not to be such a great idea, because
      LLEventPumps::flush(), which calls every registered LLEventPump's flush()
      method, is called every mainloop tick. The first time we hit a use case in
      which we expected LLEventMailDrop to hold queued events across a mainloop tick,
      we were baffled that they were never delivered.
      
      Moving that logic to a separate method specific to LLEventMailDrop resolves
      that problem. Naming it discard() clarifies its intended functionality.
      6805e82a
    • Nat Goodspeed's avatar
      DRTVWR-476: Directly reference LLVivoxVoiceClient::mVivoxPump. · 4d65539d
      Nat Goodspeed authored
      The LLEventMailDrop used to communicate with the Vivox coroutine is a member
      of LLVivoxVoiceClient. We don't need to keep looking it up by its string name
      in LLEventPumps.
      4d65539d
    • Nat Goodspeed's avatar
      DRTVWR-476: Add LLEventLogProxy, LLEventLogProxyFor<T>. · 53aeea4d
      Nat Goodspeed authored
      LLEventLogProxy can be introduced to serve as a logging proxy for an existing
      LLEventPump subclass instance. Access through the LLEventLogProxy will be
      logged; access directly to the underlying LLEventPump will not.
      
      LLEventLogProxyFor<LLEventPumpSubclass> functions as a drop-in replacement for
      the original LLEventPumpSubclass instance. It internally instantiates
      LLEventPumpSubclass and serves as a proxy for that instance.
      
      Add unit tests for LLEventMailDrop and LLEventLogProxyFor<LLEventMailDrop>,
      both "plain" (events only) and via lleventcoro.h synchronization.
      53aeea4d
    • Nat Goodspeed's avatar
      DRTVWR-476: Validate LLEventPumpOrPumpName replyPump · 6945755e
      Nat Goodspeed authored
      passed to postAndSuspendsetup().
      
      The requestPump is optional, and the function varies its behavior depending on
      whether that parameter is empty or meaningful. But it unconditionally uses the
      replyPump. Passing an empty LLEventPumpOrPumpName caused mysterious crashes.
      Add llassert_always_msg() to make the coding error explicit in such a case.
      
      Also streamline access to meaningful requestPump and replyPump by temporarily
      caching the bound LLEventPump reference.
      6945755e
    • Nat Goodspeed's avatar
      DRTVWR-476: Remove special case for listen(boost::bind(weak_ptr)). · afaad3ce
      Nat Goodspeed authored
      LLEventDetail::visit_and_connect() promised special treatment for the
      specific case when an LLEventPump::listen() listener was composed of (possibly
      nested) boost::bind() objects storing boost::weak_ptr values -- specifically
      boost::bind() rather than std::bind or lambdas, specifically boost::weak_ptr
      rather than std::weak_ptr.
      
      Outside of self-tests, it does not appear that anyone actually uses that
      support.
      
      There is good reason not to: it's a silent side effect of a complicated
      compile-time inspection that could be silently derailed by use of std::bind()
      or a lambda or a std::weak_ptr. Can you be sure you've engaged that promise?
      How?
      
      A more robust guarantee can be achieved by storing an LLTempBoundConnection in
      the transient object itself. When the object is destroyed, the listener is
      disconnected. Normal C++ rules around object destruction guarantee it. This
      idiom is widely used.
      
      There are a couple good reasons to remove the visit_and_connect() machinery:
      
      * boost::bind() and boost::weak_ptr do not constitute the wave of the future.
        Preferring those constructs to lambdas and std::weak_ptr penalizes new code,
        whether by silently failing or by discouraging use of modern idioms.
      * The visit_and_connect() machinery was always complicated, and apparently
        never very robust. Most of its promised features have been commented out
        over the years. Making the code base simpler, clearer and more maintainable
        is always a useful effect.
      
      LLEventDetail::visit_and_connect() was also used by the four
      LLNotificationChannelBase::connectMumble() methods. Streamline those as well.
      
      Of course, remove related test code.
      afaad3ce
    • Nat Goodspeed's avatar
      DRTVWR-476: Remove llwrap(), LLListenerWrapper[Base] and support. · 18e2b9ca
      Nat Goodspeed authored
      The only usage of any of this was in test code.
      18e2b9ca
    • Nat Goodspeed's avatar
      0cde6669
    • Nat Goodspeed's avatar
      DRTVWR-476: Add llsd::array() and llsd::map() variadic functions. · 52d15b64
      Nat Goodspeed authored
      llsd::array(), as one might suspect, takes an arbitrary number of arguments of
      arbitrary convertible types and returns an LLSD::Array constructed from those
      elements. This supercedes the older LLSDArray class.
      
      llsd::map() takes an even number of arguments paired as (LLSD::String,
      arbitrary convertible type) and returns an LLSD::Map constructed from those
      (key, value) pairs. This supercedes the older LLSDMap class.
      
      These two functions not only have a simpler API -- arbitrary function
      arguments rather than an (arg list)(arg list) sequence -- but also
      specifically return a final LLSD object, rather than needing conversion to
      LLSD from the LLSDArray or LLSDMap object.
      
      Also support LLSD == LLSD and LLSD != LLSD comparisons, using llsd_equals()
      with default exact-float-equality semantics.
      52d15b64
    • Nat Goodspeed's avatar
      ce2b56b2
    • Nat Goodspeed's avatar
      DRTVWR-476: Make test program --debug switch work like LOGTEST=DEBUG. · 6b70493d
      Nat Goodspeed authored
      The comments within indra/test/test.cpp promise that --debug is, in fact, like
      LOGTEST=DEBUG. Until now, that was a lie. LOGTEST=level displayed log output
      on stderr as well as in testprogram.log, while --debug did not.
      
      Add LLError::logToStderr() function, and make initForApplication() (i.e.
      commonInit()) call that instead of instantiating RecordToStderr inline. Also
      call it when test.cpp recognizes --debug switch.
      
      Remove the mFileRecorder, mFixedBufferRecorder and mFileRecorderFileName
      members from SettingsConfig. That tactic doesn't scale.
      
      Instead, add findRecorder<RECORDER>() and removeRecorder<RECORDER>() template
      functions to locate (or remove) a RecorderPtr to an object of the specified
      subclass. Both are based on an underlying findRecorderPos<RECORDER>() template
      function. Since we never expect to manage more than a handful of RecorderPtrs,
      and since access to the deleted members is very much application setup rather
      than any kind of ongoing access, a search loop suffices.
      
      logToFile() uses removeRecorder<RecordToFile>() rather than removing
      mFileRecorder (the only use of mFileRecorder).
      
      logToFixedBuffer() uses removeRecorder<RecordToFixedBuffer>() rather than
      removing mFixedBufferRecorder (the only use of mFixedBufferRecorder).
      
      Make RecordToFile store the filename with which it was instantiated. Add a
      getFilename() method to retrieve it. logFileName() is now based on
      findRecorder<RecordToFile>() instead of mFileRecorderFileName (the only use of
      mFileRecorderFileName).
      
      Make RecordToStderr::mUseANSI a simple bool rather than a three-state enum,
      and set it immediately on construction. Apparently the reason it was set
      lazily was because it consults its own checkANSI() method, and of course
      'this' doesn't acquire the leaf class type until the constructor has completed
      successfully. But since nothing in checkANSI() depends on anything else in
      RecordToStderr, making it static solves that problem.
      6b70493d
    • Nat Goodspeed's avatar
      DRTVWR-476: Fix overflow case in llcoro::postAndSuspend(). · e4d6383c
      Nat Goodspeed authored
      Actually the fix is in postAndSuspendSetup(), which affects postAndSuspend(),
      postAndSuspendWithTimeout(), suspendUntilEventOnWithTimeout() and
      suspendUntilEventOn().
      
      By "overflow case" we mean the special circumstance in which:
      
      * the LLEventPump in question is an LLEventMailDrop, meaning its listeners
        eventually expect to see every post()ed value
      * one of the listeners is supposed to consume those values (has called
        LLCoros::set_consuming(true))
      * post() is called more than once before that listener is resumed.
      
      The magic of postAndSuspend() (et al.) is a temporary LLCoros::Promise. The
      waiting coroutine calls get() on the corresponding Future, causing it to
      suspend (as promised) until the Promise is fulfilled.
      
      With the Boost.Fiber implementation of coroutines, fulfilling the Promise
      doesn't immediately resume the suspended coroutine -- it merely marks it ready
      to resume, next time the scheduler gets control.
      
      A second post() call before the suspended coroutine is resumed results in a
      second call to Promise::set_value(). But Promise is a one-shot entity. This
      results in a promise_already_satisfied exception. Because a second post() call
      during that time window is perfectly reasonable, we catch that exception and
      carry on.
      
      The tricky part is: when that exception is thrown, what should the listener
      return? Previously we were returning the listener's current consuming setting,
      just as when the set_value() call succeeds.
      
      But when the LLEventPump is an LLEventMailDrop, and the listener's consuming
      flag is true, that told LLEventMailDrop::post() that the value got through,
      and that it needn't bother to save it in its history queue. The net effect was
      to discard the value.
      
      Instead, return the listener's consuming flag only when Promise::set_value()
      succeeds. When it throws promise_already_satisfied, unconditionally return
      false. That directs LLEventMailDrop::post() to enqueue the undelivered value
      so that the *next* suspendUntilEventOn() call can pick it up.
      e4d6383c
    • Nat Goodspeed's avatar
      DRTVWR-476: Fix Windows line endings · 16b76837
      Nat Goodspeed authored
      16b76837
    • Nat Goodspeed's avatar
      54bc5ee9
    • Nat Goodspeed's avatar
      eb75b358
    • Nat Goodspeed's avatar
      DRTVWR-476: Update vlc-bin, jsoncpp, pcre, libndofdev, libhunspell, bugsplat,... · 6a3b0363
      Nat Goodspeed authored
      DRTVWR-476: Update vlc-bin, jsoncpp, pcre, libndofdev, libhunspell, bugsplat, fmodex, llca, jpeglib, libxml2, slvoice, glod, dullahan, glext, kdu, uriparser, glh_linear, tut, nghttp2, dictionaries, zlib, llphysicsextensions_source, openjpeg, nvapi, expat, viewer-manager, google_breakpad, libpng, ogg_vorbis, openssl, xmlrpc-epi, apr_suite, freetype, boost, colladadom, googlemock, curl, havok-source
      
      Update vlc-bin to codeticket version 531366.
      Update jsoncpp to codeticket version 531360.
      Update pcre to codeticket version 531373.
      Update libndofdev to codeticket version 531359.
      Update libhunspell to codeticket version 531369.
      Update bugsplat to codeticket version 531352.
      Update fmodex to codeticket version 531266.
      Update llca to codeticket version 531253.
      Update jpeglib to codeticket version 531361.
      Update libxml2 to codeticket version 531380.
      Update slvoice to codeticket version 531358.
      Update glod to codeticket version 531370.
      Update dullahan to codeticket version 531387.
      Update glext to codeticket version 531247.
      Update kdu to codeticket version 531363.
      Update uriparser to codeticket version 531367.
      Update glh_linear to codeticket version 531260.
      Update tut to codeticket version 531246.
      Update nghttp2 to codeticket version 531364.
      Update dictionaries to codeticket version 531288.
      Update zlib to codeticket version 531372.
      Update llphysicsextensions_source to codeticket version 531362.
      Update openjpeg to codeticket version 531368.
      Update nvapi to codeticket version 531376.
      Update expat to codeticket version 531365.
      Update viewer-manager to codeticket version 531239.
      Update google_breakpad to codeticket version 531388.
      Update libpng to codeticket version 531386.
      Update ogg_vorbis to codeticket version 531357.
      Update openssl to codeticket version 531379.
      Update xmlrpc-epi to codeticket version 531374.
      Update apr_suite to codeticket version 531375.
      Update freetype to codeticket version 531385.
      Update boost to codeticket version 531381.
      Update colladadom to codeticket version 531391.
      Update googlemock to codeticket version 531390.
      Update curl to codeticket version 531389.
      Update havok-source to codeticket version 531509.
      6a3b0363
    • Nat Goodspeed's avatar
      e33a747d
    • Nat Goodspeed's avatar
      DRTVWR-476: Re-enable an llcoproceduremanager_test case. · 6f879178
      Nat Goodspeed authored
      Use new Sync class to make the driving logic wait for the coprocedure to run.
      6f879178
    • Nat Goodspeed's avatar
      DRTVWR-476: Add Sync class to help with stepwise coroutine tests. · d7c2e4a7
      Nat Goodspeed authored
      Sync is specifically intended for test programs. It is based on an
      LLScalarCond<int>. The idea is that each of two coroutines can watch for the
      other to get a chance to run, indicated by incrementing the wrapped int and
      notifying the wrapped condition_variable. This is less hand-wavy than calling
      llcoro::suspend() and hoping that the other routine will have had a chance to
      run.
      
      Use Sync in lleventcoro_test.cpp.
      
      Also refactor lleventcoro_test.cpp so that instead of a collection of static
      data requiring a clear() call at start of each individual test function, the
      relevant data is all part of the test_data struct common to all test
      functions. Make the helper coroutine functions members of test_data too.
      
      Introduce llcoro::logname(), a convenience function to log the name of the
      currently executing coroutine or "main" if in the thread's main coroutine.
      d7c2e4a7
    • Nat Goodspeed's avatar
      DRTVWR-476: Improve llprocess_test.cpp diagnostic output. · 98cfe13c
      Nat Goodspeed authored
      If the test<1>() child process terminates with nonzero rc, also report any
      stdout/stderr it might have emitted first.
      98cfe13c
    • Nat Goodspeed's avatar
      00e2e949
    • Nat Goodspeed's avatar
      DRTVWR-476: Add basic tests for LLCond. · 9a3afe96
      Nat Goodspeed authored
      9a3afe96
    • Nat Goodspeed's avatar
      3810145c
    • Nat Goodspeed's avatar
      DRTVWR-476: Fix convert(F32Milliseconds) · 72863b94
      Nat Goodspeed authored
      72863b94
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: Review response: support LLDate and llunits.h durations. · a3de1899
      Nat Goodspeed authored
      Also introduce value_type typedef.
      a3de1899
    • Nat Goodspeed's avatar
      DRTVWR-476: WIP: Untested preliminary implementation of LLCond. · d8e08ecd
      Nat Goodspeed authored
      LLCond encapsulates the usage patterns required to properly use
      condition_variable. We also provide LLScalarCond, LLBoolCond and LLOneShotCond.
      d8e08ecd
    • Nat Goodspeed's avatar
      DRTVWR-476: Fix confusing comment in LLProcess::handle_status(). · f3baa6bb
      Nat Goodspeed authored
      The global replace in changeset bd80903cf987 was a bit too sweeping: a comment
      mentioning the OS function wait() (which exists) was inadvertently changed to
      talk about an OS function suspend() (which does not).
      f3baa6bb
    • callum_linden's avatar
    • Anchor's avatar
    • Anchor's avatar
      [DRTVWR-476] - temp fix to a test · ebe1ffcb
      Anchor authored
      ebe1ffcb
    • Nat Goodspeed's avatar
      DRTVWR-476: Disable test_httprequest.hpp on Mac Release builds. · 4174bb36
      Nat Goodspeed authored
      For reasons not yet diagnosed, specifically in Mac Release builds, the tests
      in test_httprequest.hpp consistently crash with a backtrace suggesting that
      the worker thread is calling LLCore::HttpLibcurl::completeRequest() after the
      foreground thread calls HttpRequest::destroyService().
      
      Weirdly, even executing a tut::skip() call in every test<n>() function up to
      the point of the crash does not eliminate the crash.
      4174bb36
    • Nat Goodspeed's avatar
      DRTVWR-476: Remove special llcorehttp test memory manager. · 2902f23a
      Nat Goodspeed authored
      NickyD discovered that the substitute default allocator used for llcorehttp
      tests was returning badly-aligned storage, which caused access violations on
      alignment-sensitive data such as std::atomic. Thanks Nicky!!
      
      Moreover, the llcorehttp test assertions regarding memory usage, well-
      intentioned though they are, have been causing us trouble for years. Many have
      already been disabled.
      
      The problem is that use of test_allocator.h affected *everything* defined with
      that header file's declarations visible. That inevitably included specific
      functions in other subsystems. Those functions then (unintentionally) consumed
      the special allocator, throwing off the memory tracking and making certain
      memory-related assertions consistently fail.
      
      This is a particular, observable bad effect of One Definition Rule violations.
      Within a given program, C++ allows multiple definitions for the same entity,
      but requires that all such definitions be the same. Partial visibility of the
      global operator new() and operator delete() overrides meant that some
      definitions of certain entities used the default global allocator, some used
      llcorehttp's. There may have been other, more subtle bad effects of these ODR
      violations.
      
      If one wanted to reimplement verification of the memory consumption of
      llcorehttp classes:
      
      * Each llcorehttp class (for which memory tracking was desired) should declare
        class-specific operator new() and operator delete() methods. Naturally,
        these would all consume a central llcorehttp-specific allocator, but that
        allocator should *not* be named global operator new().
      * Presumably that would require runtime indirection to allow using the default
        allocator in production while substituting the special allocator for tests.
      * Recording and verifying the memory consumption in each test should be
        performed in the test-object constructor and destructor, rather than being
        sprinkled throughout the test<n>() methods.
      * With that mechanism in place, the test object should provide methods to
        adjust (or entirely disable) memory verification for a particular test.
      * The test object should also provide a "yes, we're still consuming llcorehttp
        memory" method to be used for spot checks in the middle of tests -- instead
        of sprinkling in explicit comparisons as before.
      * In fact, the llcorehttp test object in each test_*.hpp file should be
        derived from a central llcorehttp test-object base class providing those
        methods.
      2902f23a
    • Nat Goodspeed's avatar
    • Nat Goodspeed's avatar
      DRTVWR-476: Add LLCOREHTTP_TESTS CMake var, OFF by default on Mac. · c56601bc
      Nat Goodspeed authored
      Hopefully this is temporary until we solve the problem of crashy llcorehttp
      test executable on Mac.
      c56601bc
Loading