llcoros.h
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:7k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /**
  2.  * @file   llcoros.h
  3.  * @author Nat Goodspeed
  4.  * @date   2009-06-02
  5.  * @brief  Manage running boost::coroutine instances
  6.  * 
  7.  * $LicenseInfo:firstyear=2009&license=viewergpl$
  8.  * 
  9.  * Copyright (c) 2009-2010, Linden Research, Inc.
  10.  * 
  11.  * Second Life Viewer Source Code
  12.  * The source code in this file ("Source Code") is provided by Linden Lab
  13.  * to you under the terms of the GNU General Public License, version 2.0
  14.  * ("GPL"), unless you have obtained a separate licensing agreement
  15.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  16.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18.  * 
  19.  * There are special exceptions to the terms and conditions of the GPL as
  20.  * it is applied to this Source Code. View the full text of the exception
  21.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  22.  * online at
  23.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24.  * 
  25.  * By copying, modifying or distributing this software, you acknowledge
  26.  * that you have read and understood your obligations described above,
  27.  * and agree to abide by those obligations.
  28.  * 
  29.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31.  * COMPLETENESS OR PERFORMANCE.
  32.  * $/LicenseInfo$
  33.  */
  34. #if ! defined(LL_LLCOROS_H)
  35. #define LL_LLCOROS_H
  36. #include <boost/coroutine/coroutine.hpp>
  37. #include "llsingleton.h"
  38. #include <boost/ptr_container/ptr_map.hpp>
  39. #include <string>
  40. #include <boost/preprocessor/repetition/enum_params.hpp>
  41. #include <boost/preprocessor/repetition/enum_binary_params.hpp>
  42. #include <boost/preprocessor/iteration/local.hpp>
  43. #include <stdexcept>
  44. /**
  45.  * Registry of named Boost.Coroutine instances
  46.  *
  47.  * The Boost.Coroutine library supports the general case of a coroutine
  48.  * accepting arbitrary parameters and yielding multiple (sets of) results. For
  49.  * such use cases, it's natural for the invoking code to retain the coroutine
  50.  * instance: the consumer repeatedly calls into the coroutine, perhaps passing
  51.  * new parameter values, prompting it to yield its next result.
  52.  *
  53.  * Our typical coroutine usage is different, though. For us, coroutines
  54.  * provide an alternative to the @c Responder pattern. Our typical coroutine
  55.  * has @c void return, invoked in fire-and-forget mode: the handler for some
  56.  * user gesture launches the coroutine and promptly returns to the main loop.
  57.  * The coroutine initiates some action that will take multiple frames (e.g. a
  58.  * capability request), waits for its result, processes it and silently steals
  59.  * away.
  60.  *
  61.  * This usage poses two (related) problems:
  62.  *
  63.  * # Who should own the coroutine instance? If it's simply local to the
  64.  *   handler code that launches it, return from the handler will destroy the
  65.  *   coroutine object, terminating the coroutine.
  66.  * # Once the coroutine terminates, in whatever way, who's responsible for
  67.  *   cleaning up the coroutine object?
  68.  *
  69.  * LLCoros is a Singleton collection of currently-active coroutine instances.
  70.  * Each has a name. You ask LLCoros to launch a new coroutine with a suggested
  71.  * name prefix; from your prefix it generates a distinct name, registers the
  72.  * new coroutine and returns the actual name.
  73.  *
  74.  * The name can be used to kill off the coroutine prematurely, if needed. It
  75.  * can also provide diagnostic info: we can look up the name of the
  76.  * currently-running coroutine.
  77.  *
  78.  * Finally, the next frame ("mainloop" event) after the coroutine terminates,
  79.  * LLCoros will notice its demise and destroy it.
  80.  */
  81. class LL_COMMON_API LLCoros: public LLSingleton<LLCoros>
  82. {
  83. public:
  84.     /// Canonical boost::coroutines::coroutine signature we use
  85.     typedef boost::coroutines::coroutine<void()> coro;
  86.     /// Canonical 'self' type
  87.     typedef coro::self self;
  88.     /**
  89.      * Create and start running a new coroutine with specified name. The name
  90.      * string you pass is a suggestion; it will be tweaked for uniqueness. The
  91.      * actual name is returned to you.
  92.      *
  93.      * Usage looks like this, for (e.g.) two coroutine parameters:
  94.      * @code
  95.      * class MyClass
  96.      * {
  97.      * public:
  98.      *     ...
  99.      *     // Do NOT NOT NOT accept reference params other than 'self'!
  100.      *     // Pass by value only!
  101.      *     void myCoroutineMethod(LLCoros::self& self, std::string, LLSD);
  102.      *     ...
  103.      * };
  104.      * ...
  105.      * std::string name = LLCoros::instance().launch(
  106.      *    "mycoro", boost::bind(&MyClass::myCoroutineMethod, this, _1,
  107.      *                          "somestring", LLSD(17));
  108.      * @endcode
  109.      *
  110.      * Your function/method must accept LLCoros::self& as its first parameter.
  111.      * It can accept any other parameters you want -- but ONLY BY VALUE!
  112.      * Other reference parameters are a BAD IDEA! You Have Been Warned. See
  113.      * DEV-32777 comments for an explanation.
  114.      *
  115.      * Pass a callable that accepts the single LLCoros::self& parameter. It
  116.      * may work to pass a free function whose only parameter is 'self'; for
  117.      * all other cases use boost::bind(). Of course, for a non-static class
  118.      * method, the first parameter must be the class instance. Use the
  119.      * placeholder _1 for the 'self' parameter. Any other parameters should be
  120.      * passed via the bind() expression.
  121.      *
  122.      * launch() tweaks the suggested name so it won't collide with any
  123.      * existing coroutine instance, creates the coroutine instance, registers
  124.      * it with the tweaked name and runs it until its first wait. At that
  125.      * point it returns the tweaked name.
  126.      */
  127.     template <typename CALLABLE>
  128.     std::string launch(const std::string& prefix, const CALLABLE& callable)
  129.     {
  130.         return launchImpl(prefix, new coro(callable));
  131.     }
  132.     /**
  133.      * Abort a running coroutine by name. Normally, when a coroutine either
  134.      * runs to completion or terminates with an exception, LLCoros quietly
  135.      * cleans it up. This is for use only when you must explicitly interrupt
  136.      * one prematurely. Returns @c true if the specified name was found and
  137.      * still running at the time.
  138.      */
  139.     bool kill(const std::string& name);
  140.     /**
  141.      * From within a coroutine, pass its @c self object to look up the
  142.      * (tweaked) name string by which this coroutine is registered. Returns
  143.      * the empty string if not found (e.g. if the coroutine was launched by
  144.      * hand rather than using LLCoros::launch()).
  145.      */
  146.     template <typename COROUTINE_SELF>
  147.     std::string getName(const COROUTINE_SELF& self) const
  148.     {
  149.         return getNameByID(self.get_id());
  150.     }
  151.     /// getName() by self.get_id()
  152.     std::string getNameByID(const void* self_id) const;
  153. private:
  154.     friend class LLSingleton<LLCoros>;
  155.     LLCoros();
  156.     std::string launchImpl(const std::string& prefix, coro* newCoro);
  157.     std::string generateDistinctName(const std::string& prefix) const;
  158.     bool cleanup(const LLSD&);
  159.     typedef boost::ptr_map<std::string, coro> CoroMap;
  160.     CoroMap mCoros;
  161. };
  162. #endif /* ! defined(LL_LLCOROS_H) */