summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorRye <rye@alchemyviewer.org>2025-08-20 18:04:55 -0400
committerRye <rye@alchemyviewer.org>2025-08-20 18:04:55 -0400
commitba30737d8f4add8ddd8c77d18df6497b46583fe9 (patch)
tree81e5412a364ff80b5250fe6db9e653d35621c20e /indra/llcommon
parentf0db568bf8d313a00e10c1c4ee4dd7f716a9d987 (diff)
parentd5f748c91c650a2ec534c497b9e098ccb317d70b (diff)
Merge branch 'develop' of github.com:secondlife/viewer into rye/infinitemac
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/indra_constants.h408
-rw-r--r--indra/llcommon/llassettype.cpp17
-rw-r--r--indra/llcommon/llassettype.h2
-rw-r--r--indra/llcommon/lldefs.h14
-rw-r--r--indra/llcommon/llsdutil.h39
-rw-r--r--indra/llcommon/llthread.cpp105
-rw-r--r--indra/llcommon/llthread.h7
-rw-r--r--indra/llcommon/stdtypes.h6
-rw-r--r--indra/llcommon/threadpool.h4
-rw-r--r--indra/llcommon/workqueue.cpp68
-rw-r--r--indra/llcommon/workqueue.h11
11 files changed, 431 insertions, 250 deletions
diff --git a/indra/llcommon/indra_constants.h b/indra/llcommon/indra_constants.h
index c6bdab007f..a0394da281 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -31,15 +31,15 @@
class LLUUID;
-static const F32 REGION_WIDTH_METERS = 256.f;
-static const S32 REGION_WIDTH_UNITS = 256;
-static const U32 REGION_WIDTH_U32 = 256;
+static constexpr F32 REGION_WIDTH_METERS = 256.f;
+static constexpr S32 REGION_WIDTH_UNITS = 256;
+static constexpr U32 REGION_WIDTH_U32 = 256;
-const F32 REGION_HEIGHT_METERS = 4096.f;
+constexpr F32 REGION_HEIGHT_METERS = 4096.f;
-const F32 DEFAULT_AGENT_DEPTH = 0.45f;
-const F32 DEFAULT_AGENT_WIDTH = 0.60f;
-const F32 DEFAULT_AGENT_HEIGHT = 1.9f;
+constexpr F32 DEFAULT_AGENT_DEPTH = 0.45f;
+constexpr F32 DEFAULT_AGENT_WIDTH = 0.60f;
+constexpr F32 DEFAULT_AGENT_HEIGHT = 1.9f;
enum ETerrainBrushType
{
@@ -67,112 +67,112 @@ enum EMouseClickType{
// keys
// Bit masks for various keyboard modifier keys.
-const MASK MASK_NONE = 0x0000;
-const MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
-const MASK MASK_ALT = 0x0002;
-const MASK MASK_SHIFT = 0x0004;
-const MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
-const MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
-const MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
+constexpr MASK MASK_NONE = 0x0000;
+constexpr MASK MASK_CONTROL = 0x0001; // Mapped to cmd on Macs
+constexpr MASK MASK_ALT = 0x0002;
+constexpr MASK MASK_SHIFT = 0x0004;
+constexpr MASK MASK_NORMALKEYS = 0x0007; // A real mask - only get the bits for normal modifier keys
+constexpr MASK MASK_MAC_CONTROL = 0x0008; // Un-mapped Ctrl key on Macs, not used on Windows
+constexpr MASK MASK_MODIFIERS = MASK_CONTROL|MASK_ALT|MASK_SHIFT|MASK_MAC_CONTROL;
// Special keys go into >128
-const KEY KEY_SPECIAL = 0x80; // special keys start here
-const KEY KEY_RETURN = 0x81;
-const KEY KEY_LEFT = 0x82;
-const KEY KEY_RIGHT = 0x83;
-const KEY KEY_UP = 0x84;
-const KEY KEY_DOWN = 0x85;
-const KEY KEY_ESCAPE = 0x86;
-const KEY KEY_BACKSPACE =0x87;
-const KEY KEY_DELETE = 0x88;
-const KEY KEY_SHIFT = 0x89;
-const KEY KEY_CONTROL = 0x8A;
-const KEY KEY_ALT = 0x8B;
-const KEY KEY_HOME = 0x8C;
-const KEY KEY_END = 0x8D;
-const KEY KEY_PAGE_UP = 0x8E;
-const KEY KEY_PAGE_DOWN = 0x8F;
-const KEY KEY_HYPHEN = 0x90;
-const KEY KEY_EQUALS = 0x91;
-const KEY KEY_INSERT = 0x92;
-const KEY KEY_CAPSLOCK = 0x93;
-const KEY KEY_TAB = 0x94;
-const KEY KEY_ADD = 0x95;
-const KEY KEY_SUBTRACT =0x96;
-const KEY KEY_MULTIPLY =0x97;
-const KEY KEY_DIVIDE = 0x98;
-const KEY KEY_F1 = 0xA1;
-const KEY KEY_F2 = 0xA2;
-const KEY KEY_F3 = 0xA3;
-const KEY KEY_F4 = 0xA4;
-const KEY KEY_F5 = 0xA5;
-const KEY KEY_F6 = 0xA6;
-const KEY KEY_F7 = 0xA7;
-const KEY KEY_F8 = 0xA8;
-const KEY KEY_F9 = 0xA9;
-const KEY KEY_F10 = 0xAA;
-const KEY KEY_F11 = 0xAB;
-const KEY KEY_F12 = 0xAC;
-
-const KEY KEY_PAD_UP = 0xC0;
-const KEY KEY_PAD_DOWN = 0xC1;
-const KEY KEY_PAD_LEFT = 0xC2;
-const KEY KEY_PAD_RIGHT = 0xC3;
-const KEY KEY_PAD_HOME = 0xC4;
-const KEY KEY_PAD_END = 0xC5;
-const KEY KEY_PAD_PGUP = 0xC6;
-const KEY KEY_PAD_PGDN = 0xC7;
-const KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
-const KEY KEY_PAD_INS = 0xC9;
-const KEY KEY_PAD_DEL = 0xCA;
-const KEY KEY_PAD_RETURN = 0xCB;
-const KEY KEY_PAD_ADD = 0xCC; // not used
-const KEY KEY_PAD_SUBTRACT = 0xCD; // not used
-const KEY KEY_PAD_MULTIPLY = 0xCE; // not used
-const KEY KEY_PAD_DIVIDE = 0xCF; // not used
-
-const KEY KEY_BUTTON0 = 0xD0;
-const KEY KEY_BUTTON1 = 0xD1;
-const KEY KEY_BUTTON2 = 0xD2;
-const KEY KEY_BUTTON3 = 0xD3;
-const KEY KEY_BUTTON4 = 0xD4;
-const KEY KEY_BUTTON5 = 0xD5;
-const KEY KEY_BUTTON6 = 0xD6;
-const KEY KEY_BUTTON7 = 0xD7;
-const KEY KEY_BUTTON8 = 0xD8;
-const KEY KEY_BUTTON9 = 0xD9;
-const KEY KEY_BUTTON10 = 0xDA;
-const KEY KEY_BUTTON11 = 0xDB;
-const KEY KEY_BUTTON12 = 0xDC;
-const KEY KEY_BUTTON13 = 0xDD;
-const KEY KEY_BUTTON14 = 0xDE;
-const KEY KEY_BUTTON15 = 0xDF;
-
-const KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
-
-const S32 KEY_COUNT = 256;
-
-
-const F32 DEFAULT_WATER_HEIGHT = 20.0f;
+constexpr KEY KEY_SPECIAL = 0x80; // special keys start here
+constexpr KEY KEY_RETURN = 0x81;
+constexpr KEY KEY_LEFT = 0x82;
+constexpr KEY KEY_RIGHT = 0x83;
+constexpr KEY KEY_UP = 0x84;
+constexpr KEY KEY_DOWN = 0x85;
+constexpr KEY KEY_ESCAPE = 0x86;
+constexpr KEY KEY_BACKSPACE =0x87;
+constexpr KEY KEY_DELETE = 0x88;
+constexpr KEY KEY_SHIFT = 0x89;
+constexpr KEY KEY_CONTROL = 0x8A;
+constexpr KEY KEY_ALT = 0x8B;
+constexpr KEY KEY_HOME = 0x8C;
+constexpr KEY KEY_END = 0x8D;
+constexpr KEY KEY_PAGE_UP = 0x8E;
+constexpr KEY KEY_PAGE_DOWN = 0x8F;
+constexpr KEY KEY_HYPHEN = 0x90;
+constexpr KEY KEY_EQUALS = 0x91;
+constexpr KEY KEY_INSERT = 0x92;
+constexpr KEY KEY_CAPSLOCK = 0x93;
+constexpr KEY KEY_TAB = 0x94;
+constexpr KEY KEY_ADD = 0x95;
+constexpr KEY KEY_SUBTRACT =0x96;
+constexpr KEY KEY_MULTIPLY =0x97;
+constexpr KEY KEY_DIVIDE = 0x98;
+constexpr KEY KEY_F1 = 0xA1;
+constexpr KEY KEY_F2 = 0xA2;
+constexpr KEY KEY_F3 = 0xA3;
+constexpr KEY KEY_F4 = 0xA4;
+constexpr KEY KEY_F5 = 0xA5;
+constexpr KEY KEY_F6 = 0xA6;
+constexpr KEY KEY_F7 = 0xA7;
+constexpr KEY KEY_F8 = 0xA8;
+constexpr KEY KEY_F9 = 0xA9;
+constexpr KEY KEY_F10 = 0xAA;
+constexpr KEY KEY_F11 = 0xAB;
+constexpr KEY KEY_F12 = 0xAC;
+
+constexpr KEY KEY_PAD_UP = 0xC0;
+constexpr KEY KEY_PAD_DOWN = 0xC1;
+constexpr KEY KEY_PAD_LEFT = 0xC2;
+constexpr KEY KEY_PAD_RIGHT = 0xC3;
+constexpr KEY KEY_PAD_HOME = 0xC4;
+constexpr KEY KEY_PAD_END = 0xC5;
+constexpr KEY KEY_PAD_PGUP = 0xC6;
+constexpr KEY KEY_PAD_PGDN = 0xC7;
+constexpr KEY KEY_PAD_CENTER = 0xC8; // the 5 in the middle
+constexpr KEY KEY_PAD_INS = 0xC9;
+constexpr KEY KEY_PAD_DEL = 0xCA;
+constexpr KEY KEY_PAD_RETURN = 0xCB;
+constexpr KEY KEY_PAD_ADD = 0xCC; // not used
+constexpr KEY KEY_PAD_SUBTRACT = 0xCD; // not used
+constexpr KEY KEY_PAD_MULTIPLY = 0xCE; // not used
+constexpr KEY KEY_PAD_DIVIDE = 0xCF; // not used
+
+constexpr KEY KEY_BUTTON0 = 0xD0;
+constexpr KEY KEY_BUTTON1 = 0xD1;
+constexpr KEY KEY_BUTTON2 = 0xD2;
+constexpr KEY KEY_BUTTON3 = 0xD3;
+constexpr KEY KEY_BUTTON4 = 0xD4;
+constexpr KEY KEY_BUTTON5 = 0xD5;
+constexpr KEY KEY_BUTTON6 = 0xD6;
+constexpr KEY KEY_BUTTON7 = 0xD7;
+constexpr KEY KEY_BUTTON8 = 0xD8;
+constexpr KEY KEY_BUTTON9 = 0xD9;
+constexpr KEY KEY_BUTTON10 = 0xDA;
+constexpr KEY KEY_BUTTON11 = 0xDB;
+constexpr KEY KEY_BUTTON12 = 0xDC;
+constexpr KEY KEY_BUTTON13 = 0xDD;
+constexpr KEY KEY_BUTTON14 = 0xDE;
+constexpr KEY KEY_BUTTON15 = 0xDF;
+
+constexpr KEY KEY_NONE = 0xFF; // not sent from keyboard. For internal use only.
+
+constexpr S32 KEY_COUNT = 256;
+
+
+constexpr F32 DEFAULT_WATER_HEIGHT = 20.0f;
// Maturity ratings for simulators
-const U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
-const U8 SIM_ACCESS_PG = 13;
-const U8 SIM_ACCESS_MATURE = 21;
-const U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
-const U8 SIM_ACCESS_DOWN = 254;
-const U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
+constexpr U8 SIM_ACCESS_MIN = 0; // Treated as 'unknown', usually ends up being SIM_ACCESS_PG
+constexpr U8 SIM_ACCESS_PG = 13;
+constexpr U8 SIM_ACCESS_MATURE = 21;
+constexpr U8 SIM_ACCESS_ADULT = 42; // Seriously Adult Only
+constexpr U8 SIM_ACCESS_DOWN = 254;
+constexpr U8 SIM_ACCESS_MAX = SIM_ACCESS_ADULT;
// attachment constants
-const U8 ATTACHMENT_ADD = 0x80;
+constexpr U8 ATTACHMENT_ADD = 0x80;
// god levels
-const U8 GOD_MAINTENANCE = 250;
-const U8 GOD_FULL = 200;
-const U8 GOD_LIAISON = 150;
-const U8 GOD_CUSTOMER_SERVICE = 100;
-const U8 GOD_LIKE = 1;
-const U8 GOD_NOT = 0;
+constexpr U8 GOD_MAINTENANCE = 250;
+constexpr U8 GOD_FULL = 200;
+constexpr U8 GOD_LIAISON = 150;
+constexpr U8 GOD_CUSTOMER_SERVICE = 100;
+constexpr U8 GOD_LIKE = 1;
+constexpr U8 GOD_NOT = 0;
// "agent id" for things that should be done to ALL agents
LL_COMMON_API extern const LLUUID LL_UUID_ALL_AGENTS;
@@ -239,120 +239,120 @@ LL_COMMON_API extern const LLUUID BLANK_OBJECT_NORMAL;
LL_COMMON_API extern const LLUUID BLANK_MATERIAL_ASSET_ID;
// radius within which a chat message is fully audible
-const F32 CHAT_NORMAL_RADIUS = 20.f;
+constexpr F32 CHAT_NORMAL_RADIUS = 20.f;
// media commands
-const U32 PARCEL_MEDIA_COMMAND_STOP = 0;
-const U32 PARCEL_MEDIA_COMMAND_PAUSE = 1;
-const U32 PARCEL_MEDIA_COMMAND_PLAY = 2;
-const U32 PARCEL_MEDIA_COMMAND_LOOP = 3;
-const U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4;
-const U32 PARCEL_MEDIA_COMMAND_URL = 5;
-const U32 PARCEL_MEDIA_COMMAND_TIME = 6;
-const U32 PARCEL_MEDIA_COMMAND_AGENT = 7;
-const U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8;
-const U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
-const U32 PARCEL_MEDIA_COMMAND_TYPE = 10;
-const U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
-const U32 PARCEL_MEDIA_COMMAND_DESC = 12;
-const U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
+constexpr U32 PARCEL_MEDIA_COMMAND_STOP = 0;
+constexpr U32 PARCEL_MEDIA_COMMAND_PAUSE = 1;
+constexpr U32 PARCEL_MEDIA_COMMAND_PLAY = 2;
+constexpr U32 PARCEL_MEDIA_COMMAND_LOOP = 3;
+constexpr U32 PARCEL_MEDIA_COMMAND_TEXTURE = 4;
+constexpr U32 PARCEL_MEDIA_COMMAND_URL = 5;
+constexpr U32 PARCEL_MEDIA_COMMAND_TIME = 6;
+constexpr U32 PARCEL_MEDIA_COMMAND_AGENT = 7;
+constexpr U32 PARCEL_MEDIA_COMMAND_UNLOAD = 8;
+constexpr U32 PARCEL_MEDIA_COMMAND_AUTO_ALIGN = 9;
+constexpr U32 PARCEL_MEDIA_COMMAND_TYPE = 10;
+constexpr U32 PARCEL_MEDIA_COMMAND_SIZE = 11;
+constexpr U32 PARCEL_MEDIA_COMMAND_DESC = 12;
+constexpr U32 PARCEL_MEDIA_COMMAND_LOOP_SET = 13;
const S32 CHAT_CHANNEL_DEBUG = S32_MAX;
// agent constants
-const U32 CONTROL_AT_POS_INDEX = 0;
-const U32 CONTROL_AT_NEG_INDEX = 1;
-const U32 CONTROL_LEFT_POS_INDEX = 2;
-const U32 CONTROL_LEFT_NEG_INDEX = 3;
-const U32 CONTROL_UP_POS_INDEX = 4;
-const U32 CONTROL_UP_NEG_INDEX = 5;
-const U32 CONTROL_PITCH_POS_INDEX = 6;
-const U32 CONTROL_PITCH_NEG_INDEX = 7;
-const U32 CONTROL_YAW_POS_INDEX = 8;
-const U32 CONTROL_YAW_NEG_INDEX = 9;
-const U32 CONTROL_FAST_AT_INDEX = 10;
-const U32 CONTROL_FAST_LEFT_INDEX = 11;
-const U32 CONTROL_FAST_UP_INDEX = 12;
-const U32 CONTROL_FLY_INDEX = 13;
-const U32 CONTROL_STOP_INDEX = 14;
-const U32 CONTROL_FINISH_ANIM_INDEX = 15;
-const U32 CONTROL_STAND_UP_INDEX = 16;
-const U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
-const U32 CONTROL_MOUSELOOK_INDEX = 18;
-const U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
-const U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
-const U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
-const U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
-const U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
-const U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
-const U32 CONTROL_TURN_LEFT_INDEX = 25;
-const U32 CONTROL_TURN_RIGHT_INDEX = 26;
-const U32 CONTROL_AWAY_INDEX = 27;
-const U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
-const U32 CONTROL_LBUTTON_UP_INDEX = 29;
-const U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
-const U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
-const U32 TOTAL_CONTROLS = 32;
-
-const U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
-const U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
-const U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
-const U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
-const U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
-const U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
-const U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
-const U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
-const U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
-const U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
-
-const U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
-const U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
-const U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
-
-const U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
-const U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
-const U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
-const U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
-const U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
-const U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
-
-const U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
-const U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
-const U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
-const U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
-const U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
-const U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
-const U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
-const U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
-
-const U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
-
-const U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
-const U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
-const U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
-const U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
+constexpr U32 CONTROL_AT_POS_INDEX = 0;
+constexpr U32 CONTROL_AT_NEG_INDEX = 1;
+constexpr U32 CONTROL_LEFT_POS_INDEX = 2;
+constexpr U32 CONTROL_LEFT_NEG_INDEX = 3;
+constexpr U32 CONTROL_UP_POS_INDEX = 4;
+constexpr U32 CONTROL_UP_NEG_INDEX = 5;
+constexpr U32 CONTROL_PITCH_POS_INDEX = 6;
+constexpr U32 CONTROL_PITCH_NEG_INDEX = 7;
+constexpr U32 CONTROL_YAW_POS_INDEX = 8;
+constexpr U32 CONTROL_YAW_NEG_INDEX = 9;
+constexpr U32 CONTROL_FAST_AT_INDEX = 10;
+constexpr U32 CONTROL_FAST_LEFT_INDEX = 11;
+constexpr U32 CONTROL_FAST_UP_INDEX = 12;
+constexpr U32 CONTROL_FLY_INDEX = 13;
+constexpr U32 CONTROL_STOP_INDEX = 14;
+constexpr U32 CONTROL_FINISH_ANIM_INDEX = 15;
+constexpr U32 CONTROL_STAND_UP_INDEX = 16;
+constexpr U32 CONTROL_SIT_ON_GROUND_INDEX = 17;
+constexpr U32 CONTROL_MOUSELOOK_INDEX = 18;
+constexpr U32 CONTROL_NUDGE_AT_POS_INDEX = 19;
+constexpr U32 CONTROL_NUDGE_AT_NEG_INDEX = 20;
+constexpr U32 CONTROL_NUDGE_LEFT_POS_INDEX = 21;
+constexpr U32 CONTROL_NUDGE_LEFT_NEG_INDEX = 22;
+constexpr U32 CONTROL_NUDGE_UP_POS_INDEX = 23;
+constexpr U32 CONTROL_NUDGE_UP_NEG_INDEX = 24;
+constexpr U32 CONTROL_TURN_LEFT_INDEX = 25;
+constexpr U32 CONTROL_TURN_RIGHT_INDEX = 26;
+constexpr U32 CONTROL_AWAY_INDEX = 27;
+constexpr U32 CONTROL_LBUTTON_DOWN_INDEX = 28;
+constexpr U32 CONTROL_LBUTTON_UP_INDEX = 29;
+constexpr U32 CONTROL_ML_LBUTTON_DOWN_INDEX = 30;
+constexpr U32 CONTROL_ML_LBUTTON_UP_INDEX = 31;
+constexpr U32 TOTAL_CONTROLS = 32;
+
+constexpr U32 AGENT_CONTROL_AT_POS = 0x1 << CONTROL_AT_POS_INDEX; // 0x00000001
+constexpr U32 AGENT_CONTROL_AT_NEG = 0x1 << CONTROL_AT_NEG_INDEX; // 0x00000002
+constexpr U32 AGENT_CONTROL_LEFT_POS = 0x1 << CONTROL_LEFT_POS_INDEX; // 0x00000004
+constexpr U32 AGENT_CONTROL_LEFT_NEG = 0x1 << CONTROL_LEFT_NEG_INDEX; // 0x00000008
+constexpr U32 AGENT_CONTROL_UP_POS = 0x1 << CONTROL_UP_POS_INDEX; // 0x00000010
+constexpr U32 AGENT_CONTROL_UP_NEG = 0x1 << CONTROL_UP_NEG_INDEX; // 0x00000020
+constexpr U32 AGENT_CONTROL_PITCH_POS = 0x1 << CONTROL_PITCH_POS_INDEX; // 0x00000040
+constexpr U32 AGENT_CONTROL_PITCH_NEG = 0x1 << CONTROL_PITCH_NEG_INDEX; // 0x00000080
+constexpr U32 AGENT_CONTROL_YAW_POS = 0x1 << CONTROL_YAW_POS_INDEX; // 0x00000100
+constexpr U32 AGENT_CONTROL_YAW_NEG = 0x1 << CONTROL_YAW_NEG_INDEX; // 0x00000200
+
+constexpr U32 AGENT_CONTROL_FAST_AT = 0x1 << CONTROL_FAST_AT_INDEX; // 0x00000400
+constexpr U32 AGENT_CONTROL_FAST_LEFT = 0x1 << CONTROL_FAST_LEFT_INDEX; // 0x00000800
+constexpr U32 AGENT_CONTROL_FAST_UP = 0x1 << CONTROL_FAST_UP_INDEX; // 0x00001000
+
+constexpr U32 AGENT_CONTROL_FLY = 0x1 << CONTROL_FLY_INDEX; // 0x00002000
+constexpr U32 AGENT_CONTROL_STOP = 0x1 << CONTROL_STOP_INDEX; // 0x00004000
+constexpr U32 AGENT_CONTROL_FINISH_ANIM = 0x1 << CONTROL_FINISH_ANIM_INDEX; // 0x00008000
+constexpr U32 AGENT_CONTROL_STAND_UP = 0x1 << CONTROL_STAND_UP_INDEX; // 0x00010000
+constexpr U32 AGENT_CONTROL_SIT_ON_GROUND = 0x1 << CONTROL_SIT_ON_GROUND_INDEX; // 0x00020000
+constexpr U32 AGENT_CONTROL_MOUSELOOK = 0x1 << CONTROL_MOUSELOOK_INDEX; // 0x00040000
+
+constexpr U32 AGENT_CONTROL_NUDGE_AT_POS = 0x1 << CONTROL_NUDGE_AT_POS_INDEX; // 0x00080000
+constexpr U32 AGENT_CONTROL_NUDGE_AT_NEG = 0x1 << CONTROL_NUDGE_AT_NEG_INDEX; // 0x00100000
+constexpr U32 AGENT_CONTROL_NUDGE_LEFT_POS = 0x1 << CONTROL_NUDGE_LEFT_POS_INDEX; // 0x00200000
+constexpr U32 AGENT_CONTROL_NUDGE_LEFT_NEG = 0x1 << CONTROL_NUDGE_LEFT_NEG_INDEX; // 0x00400000
+constexpr U32 AGENT_CONTROL_NUDGE_UP_POS = 0x1 << CONTROL_NUDGE_UP_POS_INDEX; // 0x00800000
+constexpr U32 AGENT_CONTROL_NUDGE_UP_NEG = 0x1 << CONTROL_NUDGE_UP_NEG_INDEX; // 0x01000000
+constexpr U32 AGENT_CONTROL_TURN_LEFT = 0x1 << CONTROL_TURN_LEFT_INDEX; // 0x02000000
+constexpr U32 AGENT_CONTROL_TURN_RIGHT = 0x1 << CONTROL_TURN_RIGHT_INDEX; // 0x04000000
+
+constexpr U32 AGENT_CONTROL_AWAY = 0x1 << CONTROL_AWAY_INDEX; // 0x08000000
+
+constexpr U32 AGENT_CONTROL_LBUTTON_DOWN = 0x1 << CONTROL_LBUTTON_DOWN_INDEX; // 0x10000000
+constexpr U32 AGENT_CONTROL_LBUTTON_UP = 0x1 << CONTROL_LBUTTON_UP_INDEX; // 0x20000000
+constexpr U32 AGENT_CONTROL_ML_LBUTTON_DOWN = 0x1 << CONTROL_ML_LBUTTON_DOWN_INDEX; // 0x40000000
+constexpr U32 AGENT_CONTROL_ML_LBUTTON_UP = ((U32)0x1) << CONTROL_ML_LBUTTON_UP_INDEX; // 0x80000000
// move these up so that we can hide them in "State" for object updates
// (for now)
-const U32 AGENT_ATTACH_OFFSET = 4;
-const U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
+constexpr U32 AGENT_ATTACH_OFFSET = 4;
+constexpr U32 AGENT_ATTACH_MASK = 0xf << AGENT_ATTACH_OFFSET;
// RN: this method swaps the upper and lower nibbles to maintain backward
// compatibility with old objects that only used the upper nibble
#define ATTACHMENT_ID_FROM_STATE(state) ((S32)((((U8)state & AGENT_ATTACH_MASK) >> 4) | (((U8)state & ~AGENT_ATTACH_MASK) << 4)))
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
-const U8 CLICK_ACTION_NONE = 0;
-const U8 CLICK_ACTION_TOUCH = 0;
-const U8 CLICK_ACTION_SIT = 1;
-const U8 CLICK_ACTION_BUY = 2;
-const U8 CLICK_ACTION_PAY = 3;
-const U8 CLICK_ACTION_OPEN = 4;
-const U8 CLICK_ACTION_PLAY = 5;
-const U8 CLICK_ACTION_OPEN_MEDIA = 6;
-const U8 CLICK_ACTION_ZOOM = 7;
-const U8 CLICK_ACTION_DISABLED = 8;
-const U8 CLICK_ACTION_IGNORE = 9;
+constexpr U8 CLICK_ACTION_NONE = 0;
+constexpr U8 CLICK_ACTION_TOUCH = 0;
+constexpr U8 CLICK_ACTION_SIT = 1;
+constexpr U8 CLICK_ACTION_BUY = 2;
+constexpr U8 CLICK_ACTION_PAY = 3;
+constexpr U8 CLICK_ACTION_OPEN = 4;
+constexpr U8 CLICK_ACTION_PLAY = 5;
+constexpr U8 CLICK_ACTION_OPEN_MEDIA = 6;
+constexpr U8 CLICK_ACTION_ZOOM = 7;
+constexpr U8 CLICK_ACTION_DISABLED = 8;
+constexpr U8 CLICK_ACTION_IGNORE = 9;
// DO NOT CHANGE THE SEQUENCE OF THIS LIST!!
constexpr U32 BEACON_SHOW_MAP = 0x0001;
diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp
index c09cf7abd2..9672a3262b 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -29,6 +29,7 @@
#include "llassettype.h"
#include "lldictionary.h"
#include "llmemory.h"
+#include "llsd.h"
#include "llsingleton.h"
///----------------------------------------------------------------------------
@@ -246,3 +247,19 @@ bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type)
}
return false;
}
+
+LLSD LLAssetType::getTypeNames()
+{
+ LLSD type_names;
+ const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
+ for (S32 type = AT_TEXTURE; type < AT_COUNT; ++type)
+ {
+ const AssetEntry *entry = dict->lookup((LLAssetType::EType) type);
+ // skip llassettype_bad_lookup
+ if (entry)
+ {
+ type_names.append(entry->mTypeName);
+ }
+ }
+ return type_names;
+}
diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 547c3f4329..17177d81c3 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -165,6 +165,8 @@ public:
static bool lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download
static bool lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer
+ static LLSD getTypeNames();
+
static const std::string BADLOOKUP;
protected:
diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h
index 2fbb26dc1a..232987da14 100644
--- a/indra/llcommon/lldefs.h
+++ b/indra/llcommon/lldefs.h
@@ -171,13 +171,13 @@ constexpr U32 MAXADDRSTR = 17; // 123.567.901.345 = 15 chars + \0 +
// recursion tail
template <typename T>
-inline auto llmax(T data)
+constexpr auto llmax(T data)
{
return data;
}
template <typename T0, typename T1, typename... Ts>
-inline auto llmax(T0 d0, T1 d1, Ts... rest)
+constexpr auto llmax(T0 d0, T1 d1, Ts... rest)
{
auto maxrest = llmax(d1, rest...);
return (d0 > maxrest)? d0 : maxrest;
@@ -185,20 +185,20 @@ inline auto llmax(T0 d0, T1 d1, Ts... rest)
// recursion tail
template <typename T>
-inline auto llmin(T data)
+constexpr auto llmin(T data)
{
return data;
}
template <typename T0, typename T1, typename... Ts>
-inline auto llmin(T0 d0, T1 d1, Ts... rest)
+constexpr auto llmin(T0 d0, T1 d1, Ts... rest)
{
auto minrest = llmin(d1, rest...);
return (d0 < minrest) ? d0 : minrest;
}
template <typename A, typename MIN, typename MAX>
-inline A llclamp(A a, MIN minval, MAX maxval)
+constexpr A llclamp(A a, MIN minval, MAX maxval)
{
A aminval{ static_cast<A>(minval) }, amaxval{ static_cast<A>(maxval) };
if ( a < aminval )
@@ -213,13 +213,13 @@ inline A llclamp(A a, MIN minval, MAX maxval)
}
template <class LLDATATYPE>
-inline LLDATATYPE llclampf(LLDATATYPE a)
+constexpr LLDATATYPE llclampf(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(1));
}
template <class LLDATATYPE>
-inline LLDATATYPE llclampb(LLDATATYPE a)
+constexpr LLDATATYPE llclampb(LLDATATYPE a)
{
return llmin(llmax(a, LLDATATYPE(0)), LLDATATYPE(255));
}
diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h
index c31030c5ea..497c0ad3eb 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -554,6 +554,45 @@ LLSD shallow(LLSD value, LLSD filter=LLSD()) { return llsd_shallow(value, filter
} // namespace llsd
/*****************************************************************************
+* LLSDParam<std::vector<T>>
+*****************************************************************************/
+// Given an LLSD array, return a const std::vector<T>&, where T is a type
+// supported by LLSDParam. Bonus: if the LLSD value is actually a scalar,
+// return a single-element vector containing the converted value.
+template <typename T>
+class LLSDParam<std::vector<T>>: public LLSDParamBase
+{
+public:
+ LLSDParam(const LLSD& array)
+ {
+ // treat undefined "array" as empty vector
+ if (array.isDefined())
+ {
+ // what if it's a scalar?
+ if (! array.isArray())
+ {
+ v.push_back(LLSDParam<T>(array));
+ }
+ else // really is an array
+ {
+ // reserve space for the array entries
+ v.reserve(array.size());
+ for (const auto& item : llsd::inArray(array))
+ {
+ v.push_back(LLSDParam<T>(item));
+ }
+ }
+ }
+ }
+
+ operator const std::vector<T>&() const { return v; }
+
+private:
+ std::vector<T> v;
+};
+
+
+/*****************************************************************************
* toArray(), toMap()
*****************************************************************************/
namespace llsd
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index e5d25b52f0..692941a892 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -28,6 +28,7 @@
#include "apr_portable.h"
+#include "llapp.h"
#include "llthread.h"
#include "llmutex.h"
@@ -35,6 +36,7 @@
#include "lltrace.h"
#include "lltracethreadrecorder.h"
#include "llexception.h"
+#include "workqueue.h"
#if LL_LINUX
#include <sched.h>
@@ -106,6 +108,27 @@ namespace
return s_thread_id;
}
+#if LL_WINDOWS
+
+ static const U32 STATUS_MSC_EXCEPTION = 0xE06D7363; // compiler specific
+
+ U32 exception_filter(U32 code, struct _EXCEPTION_POINTERS* exception_infop)
+ {
+ if (LLApp::instance()->reportCrashToBugsplat((void*)exception_infop))
+ {
+ // Handled
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+ else if (code == STATUS_MSC_EXCEPTION)
+ {
+ // C++ exception, go on
+ return EXCEPTION_CONTINUE_SEARCH;
+ }
+
+ // handle it, convert to std::exception
+ return EXCEPTION_EXECUTE_HANDLER;
+ }
+#endif // LL_WINDOWS
} // anonymous namespace
LL_COMMON_API bool on_main_thread()
@@ -157,20 +180,11 @@ void LLThread::threadRun()
// Run the user supplied function
do
{
- try
- {
- run();
- }
- catch (const LLContinueError &e)
- {
- LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
- "' reentering run(). Error what is: '" << e.what() << "'" << LL_ENDL;
- //output possible call stacks to log file.
- LLError::LLCallStacks::print();
-
- LOG_UNHANDLED_EXCEPTION("LLThread");
- continue;
- }
+#ifdef LL_WINDOWS
+ sehHandle(); // Structured Exception Handling
+#else
+ tryRun();
+#endif
break;
} while (true);
@@ -188,6 +202,69 @@ void LLThread::threadRun()
mStatus = STOPPED;
}
+void LLThread::tryRun()
+{
+ try
+ {
+ run();
+ }
+ catch (const LLContinueError& e)
+ {
+ LL_WARNS("THREAD") << "ContinueException on thread '" << mName <<
+ "'. Error what is: '" << e.what() << "'" << LL_ENDL;
+ LLError::LLCallStacks::print();
+
+ LOG_UNHANDLED_EXCEPTION("LLThread");
+ }
+ catch (std::bad_alloc&)
+ {
+ // Todo: improve this, this is going to have a different callstack
+ // instead of showing where it crashed
+ LL_WARNS("THREAD") << "Out of memory in a thread: " << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ []() {
+ LLError::LLUserWarningMsg::showOutOfMemory();
+ LL_ERRS("THREAD") << "Out of memory in a thread" << LL_ENDL;
+ });
+ }
+#ifndef LL_WINDOWS
+ catch (...)
+ {
+ // Stash any other kind of uncaught exception to be rethrown by main thread.
+ LL_WARNS("THREAD") << "Capturing and rethrowing uncaught exception in LLThread "
+ << mName << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ }
+#endif // else LL_WINDOWS
+}
+
+#ifdef LL_WINDOWS
+void LLThread::sehHandle()
+{
+ __try
+ {
+ // handle stop and continue exceptions first
+ tryRun();
+ }
+ __except (exception_filter(GetExceptionCode(), GetExceptionInformation()))
+ {
+ // convert to C++ styled exception
+ // Note: it might be better to use _se_set_translator
+ // if you want exception to inherit full callstack
+ char integer_string[512];
+ sprintf(integer_string, "SEH, code: %lu\n", GetExceptionCode());
+ throw std::exception(integer_string);
+ }
+}
+#endif
+
LLThread::LLThread(const std::string& name, apr_pool_t *poolp) :
mPaused(false),
mName(name),
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 4194e0014d..8794ac93aa 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -68,7 +68,7 @@ public:
// Called from MAIN THREAD.
void pause();
void unpause();
- bool isPaused() { return isStopped() || mPaused; }
+ bool isPaused() const { return isStopped() || mPaused; }
// Cause the thread to wake up and check its condition
void wake();
@@ -97,6 +97,11 @@ private:
// static function passed to APR thread creation routine
void threadRun();
+ void tryRun();
+
+#ifdef LL_WINDOWS
+ void sehHandle();
+#endif
protected:
std::string mName;
diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h
index 28e50b3d21..f1e4c2bc78 100644
--- a/indra/llcommon/stdtypes.h
+++ b/indra/llcommon/stdtypes.h
@@ -164,14 +164,14 @@ private:
FROM mValue;
public:
- narrow(FROM value): mValue(value) {}
+ constexpr narrow(FROM value): mValue(value) {}
/*---------------------- Narrowing unsigned to signed ----------------------*/
template <typename TO,
typename std::enable_if<std::is_unsigned<FROM>::value &&
std::is_signed<TO>::value,
bool>::type = true>
- inline
+ constexpr
operator TO() const
{
// The reason we skip the
@@ -189,7 +189,7 @@ public:
typename std::enable_if<! (std::is_unsigned<FROM>::value &&
std::is_signed<TO>::value),
bool>::type = true>
- inline
+ constexpr
operator TO() const
{
// two different assert()s so we can tell which condition failed
diff --git a/indra/llcommon/threadpool.h b/indra/llcommon/threadpool.h
index 0eb1891754..ac4f415f3e 100644
--- a/indra/llcommon/threadpool.h
+++ b/indra/llcommon/threadpool.h
@@ -55,7 +55,7 @@ namespace LL
* ThreadPool listens for application shutdown messages on the "LLApp"
* LLEventPump. Call close() to shut down this ThreadPool early.
*/
- virtual void close();
+ void close();
std::string getName() const { return mName; }
size_t getWidth() const { return mThreads.size(); }
@@ -122,7 +122,7 @@ namespace LL
size_t threads=1,
size_t capacity=1024*1024,
bool auto_shutdown = true):
- ThreadPoolBase(name, threads, new queue_t(name, capacity), auto_shutdown)
+ ThreadPoolBase(name, threads, new queue_t(name, capacity, false), auto_shutdown)
{}
~ThreadPoolUsing() override {}
diff --git a/indra/llcommon/workqueue.cpp b/indra/llcommon/workqueue.cpp
index c8ece616b2..7efaebd569 100644
--- a/indra/llcommon/workqueue.cpp
+++ b/indra/llcommon/workqueue.cpp
@@ -21,6 +21,7 @@
#include "llcoros.h"
#include LLCOROS_MUTEX_HEADER
#include "llerror.h"
+#include "llevents.h"
#include "llexception.h"
#include "stringize.h"
@@ -30,11 +31,38 @@ using Lock = LLCoros::LockType;
/*****************************************************************************
* WorkQueueBase
*****************************************************************************/
-LL::WorkQueueBase::WorkQueueBase(const std::string& name):
- super(makeName(name))
+LL::WorkQueueBase::WorkQueueBase(const std::string& name, bool auto_shutdown)
+ : super(makeName(name))
{
- // TODO: register for "LLApp" events so we can implicitly close() on
- // viewer shutdown.
+ if (auto_shutdown)
+ {
+ // Register for "LLApp" events so we can implicitly close() on viewer shutdown
+ std::string listener_name = "WorkQueue:" + getKey();
+ LLEventPumps::instance().obtain("LLApp").listen(
+ listener_name,
+ [this](const LLSD& stat)
+ {
+ std::string status(stat["status"]);
+ if (status != "running")
+ {
+ // Viewer is shutting down, close this queue
+ LL_DEBUGS("WorkQueue") << getKey() << " closing on app shutdown" << LL_ENDL;
+ close();
+ }
+ return false;
+ });
+
+ // Store the listener name so we can unregister in the destructor
+ mListenerName = listener_name;
+ }
+}
+
+LL::WorkQueueBase::~WorkQueueBase()
+{
+ if (!mListenerName.empty() && !LLEventPumps::wasDeleted())
+ {
+ LLEventPumps::instance().obtain("LLApp").stopListening(mListenerName);
+ }
}
void LL::WorkQueueBase::runUntilClose()
@@ -182,14 +210,22 @@ void LL::WorkQueueBase::callWork(const Work& work)
}
catch (...)
{
- // Stash any other kind of uncaught exception to be rethrown by main thread.
- LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
- << getKey() << LL_ENDL;
-
- LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
- main_queue->post(
- // Bind the current exception, rethrow it in main loop.
- [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ if (getKey() != "mainloop")
+ {
+ // Stash any other kind of uncaught exception to be rethrown by main thread.
+ LL_WARNS("LLCoros") << "Capturing and rethrowing uncaught exception in WorkQueueBase "
+ << getKey() << LL_ENDL;
+
+ LL::WorkQueue::ptr_t main_queue = LL::WorkQueue::getInstance("mainloop");
+ main_queue->post(
+ // Bind the current exception, rethrow it in main loop.
+ [exc = std::current_exception()]() { std::rethrow_exception(exc); });
+ }
+ else
+ {
+ // let main loop crash
+ throw;
+ }
}
#endif // else LL_WINDOWS
}
@@ -212,8 +248,8 @@ void LL::WorkQueueBase::checkCoroutine(const std::string& method)
/*****************************************************************************
* WorkQueue
*****************************************************************************/
-LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity):
- super(name),
+LL::WorkQueue::WorkQueue(const std::string& name, size_t capacity, bool auto_shutdown):
+ super(name, auto_shutdown),
mQueue(capacity)
{
}
@@ -261,8 +297,8 @@ bool LL::WorkQueue::tryPop_(Work& work)
/*****************************************************************************
* WorkSchedule
*****************************************************************************/
-LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity):
- super(name),
+LL::WorkSchedule::WorkSchedule(const std::string& name, size_t capacity, bool auto_shutdown):
+ super(name, auto_shutdown),
mQueue(capacity)
{
}
diff --git a/indra/llcommon/workqueue.h b/indra/llcommon/workqueue.h
index 9d7bbfbf7a..735ad38a26 100644
--- a/indra/llcommon/workqueue.h
+++ b/indra/llcommon/workqueue.h
@@ -51,7 +51,9 @@ namespace LL
* You may omit the WorkQueueBase name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueueBase(const std::string& name);
+ WorkQueueBase(const std::string& name, bool auto_shutdown);
+
+ virtual ~WorkQueueBase();
/**
* Since the point of WorkQueue is to pass work to some other worker
@@ -197,6 +199,9 @@ namespace LL
private:
virtual Work pop_() = 0;
virtual bool tryPop_(Work&) = 0;
+
+ // Name used for the LLApp event listener (empty if not registered)
+ std::string mListenerName;
};
/*****************************************************************************
@@ -212,7 +217,7 @@ namespace LL
* You may omit the WorkQueue name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkQueue(const std::string& name = std::string(), size_t capacity=1024);
+ WorkQueue(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/**
* Since the point of WorkQueue is to pass work to some other worker
@@ -282,7 +287,7 @@ namespace LL
* You may omit the WorkSchedule name, in which case a unique name is
* synthesized; for practical purposes that makes it anonymous.
*/
- WorkSchedule(const std::string& name = std::string(), size_t capacity=1024);
+ WorkSchedule(const std::string& name = std::string(), size_t capacity=1024, bool auto_shutdown = true);
/**
* Since the point of WorkSchedule is to pass work to some other worker