llworkqueue.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /**
  2. * @file llworkqueue.cpp
  3. * @brief Queue used for inter-thread work passing.
  4. * @author Nat Goodspeed
  5. * @date 2021-09-30
  6. *
  7. * $LicenseInfo:firstyear=2021&license=viewergpl$
  8. *
  9. * Copyright (c) 2021, Linden Research, Inc. (c) 2022 Henri Beauchamp.
  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. #include "linden_common.h"
  35. #include "llworkqueue.h"
  36. #include "llatomic.h"
  37. void LLWorkQueue::runUntilClose()
  38. {
  39. try
  40. {
  41. while (true)
  42. {
  43. callWork(mQueue.pop());
  44. if (mQueue.empty())
  45. {
  46. LLThread::yield();
  47. }
  48. }
  49. }
  50. catch (const Closed&)
  51. {
  52. }
  53. }
  54. bool LLWorkQueue::runPending()
  55. {
  56. try
  57. {
  58. for (Work work; mQueue.tryPop(work); )
  59. {
  60. callWork(work);
  61. }
  62. }
  63. catch (const Closed&)
  64. {
  65. }
  66. return !mQueue.done();
  67. }
  68. bool LLWorkQueue::runOne()
  69. {
  70. try
  71. {
  72. Work work;
  73. if (mQueue.tryPop(work))
  74. {
  75. callWork(work);
  76. }
  77. }
  78. catch (const Closed&)
  79. {
  80. }
  81. return !mQueue.done();
  82. }
  83. bool LLWorkQueue::runUntil(const TimePoint& until, size_t* work_remaining)
  84. {
  85. try
  86. {
  87. // Should we subtract some slop to allow for typical Work execution
  88. // time and how much slop ?
  89. for (Work work; TimePoint::clock::now() < until && mQueue.tryPop(work); )
  90. {
  91. callWork(work);
  92. }
  93. }
  94. catch (const Closed&)
  95. {
  96. }
  97. return !mQueue.done(work_remaining);
  98. }
  99. void LLWorkQueue::callWork(const Work& work)
  100. {
  101. try
  102. {
  103. work();
  104. }
  105. catch (...)
  106. {
  107. // No matter what goes wrong with any individual work item, the worker
  108. // thread must go on !... Log our own instance name with the exception.
  109. llwarns << "Work failed for: " << getKey() << llendl;
  110. }
  111. }
  112. //static
  113. std::string LLWorkQueue::makeName(const std::string& name)
  114. {
  115. if (!name.empty())
  116. {
  117. return name;
  118. }
  119. // We use an atomic static variable to avoid bothering with mutex and
  120. // locks. HB
  121. static LLAtomicU32 discriminator(0);
  122. U32 num = discriminator++;
  123. return llformat("WorkQueue%d", num);
  124. }
  125. //static
  126. void LLWorkQueue::error(const std::string& msg)
  127. {
  128. llerrs << msg << llendl;
  129. }
  130. #if LL_WAIT_FOR_RESULT
  131. //static
  132. void LLWorkQueue::checkCoroutine(const std::string& method)
  133. {
  134. // By convention, the default coroutine on each thread has an empty name
  135. // string.
  136. if (LLCoros::getName().empty())
  137. {
  138. throw(Error("Do not call " + method +
  139. " from a thread's default coroutine"));
  140. }
  141. }
  142. #endif