123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /**
- * @file llworkqueue.cpp
- * @brief Queue used for inter-thread work passing.
- * @author Nat Goodspeed
- * @date 2021-09-30
- *
- * $LicenseInfo:firstyear=2021&license=viewergpl$
- *
- * Copyright (c) 2021, Linden Research, Inc. (c) 2022 Henri Beauchamp.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "linden_common.h"
- #include "llworkqueue.h"
- #include "llatomic.h"
- void LLWorkQueue::runUntilClose()
- {
- try
- {
- while (true)
- {
- callWork(mQueue.pop());
- if (mQueue.empty())
- {
- LLThread::yield();
- }
- }
- }
- catch (const Closed&)
- {
- }
- }
- bool LLWorkQueue::runPending()
- {
- try
- {
- for (Work work; mQueue.tryPop(work); )
- {
- callWork(work);
- }
- }
- catch (const Closed&)
- {
- }
- return !mQueue.done();
- }
- bool LLWorkQueue::runOne()
- {
- try
- {
- Work work;
- if (mQueue.tryPop(work))
- {
- callWork(work);
- }
- }
- catch (const Closed&)
- {
- }
- return !mQueue.done();
- }
- bool LLWorkQueue::runUntil(const TimePoint& until, size_t* work_remaining)
- {
- try
- {
- // Should we subtract some slop to allow for typical Work execution
- // time and how much slop ?
- for (Work work; TimePoint::clock::now() < until && mQueue.tryPop(work); )
- {
- callWork(work);
- }
- }
- catch (const Closed&)
- {
- }
- return !mQueue.done(work_remaining);
- }
- void LLWorkQueue::callWork(const Work& work)
- {
- try
- {
- work();
- }
- catch (...)
- {
- // No matter what goes wrong with any individual work item, the worker
- // thread must go on !... Log our own instance name with the exception.
- llwarns << "Work failed for: " << getKey() << llendl;
- }
- }
- //static
- std::string LLWorkQueue::makeName(const std::string& name)
- {
- if (!name.empty())
- {
- return name;
- }
- // We use an atomic static variable to avoid bothering with mutex and
- // locks. HB
- static LLAtomicU32 discriminator(0);
- U32 num = discriminator++;
- return llformat("WorkQueue%d", num);
- }
- //static
- void LLWorkQueue::error(const std::string& msg)
- {
- llerrs << msg << llendl;
- }
- #if LL_WAIT_FOR_RESULT
- //static
- void LLWorkQueue::checkCoroutine(const std::string& method)
- {
- // By convention, the default coroutine on each thread has an empty name
- // string.
- if (LLCoros::getName().empty())
- {
- throw(Error("Do not call " + method +
- " from a thread's default coroutine"));
- }
- }
- #endif
|