Stroika Library
3.0d16
Help-Home
Loading...
Searching...
No Matches
Activity.h
1
/*
2
* Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3
*/
4
#ifndef _Stroika_Foundation_Execution_Activity_h_
5
#define _Stroika_Foundation_Execution_Activity_h_ 1
6
7
#include "Stroika/Foundation/StroikaPreComp.h"
8
9
#include "
Stroika/Foundation/Characters/String.h
"
10
#include "
Stroika/Foundation/Containers/Stack.h
"
11
12
/*
13
*
14
* \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
15
*
16
*
17
* Notes:
18
*
19
*
20
*
21
*/
22
23
namespace
Stroika::Foundation::Execution
{
24
25
namespace
Private_ {
26
namespace
Activities_ {
27
/**
28
* \note intentionally omit virtual DTOR because then the subclasses cannot be constexpr (at least it appears so in c++17).
29
* And they are never destroyed by ptr to a base class type, so this isn't needed.
30
*/
31
struct
AsStringObj_
{
32
constexpr
AsStringObj_
()
noexcept
=
default
;
33
virtual
Characters::String
AsString ()
const
= 0;
34
};
35
struct
StackElt_ {
36
const
AsStringObj_
* fActivity{};
37
const
StackElt_* fPrev{};
38
};
39
thread_local
inline
const
StackElt_* sTop_;
40
}
41
}
42
43
/**
44
* An Activity is typically a static const or sometimes even constexpr object which contains a description of
45
* an ongoing activity. They are generally not meant to be stored or copied, but REFERENCED with DeclareActivity
46
* to form a 'current activity stack'.
47
*
48
* \par Example Usage
49
* \code
50
* static constexpr Activity kBuildingThingy_{ "building thingy"sv };
51
* static const auto kOtherActivity = Activity<String>{ "abc" };
52
* // automatic variable activity OK as long as it's lifetime longer than reference in DeclareActivity
53
* auto otherActivity = Activity<String> { "abc" + argument }; // activities can be stack based, but these cost more to define
54
* auto lazyEvalActivity = LazyEvalActivity ([&] () -> String { return argument.Repeat (5) + "x"; });
55
* // then for how to use activity object - see DeclareActivity
56
* \endcode
57
*
58
* \note the intended purpose of this is to provide better 'context' for default exception messages, when exceptions are
59
* created/thrown. @see CaptureCurrentActivities
60
*
61
* \note for now, constexpr Activity<wstring_view> kActivity; // FAILS
62
* This is because AsStringObj_ has a virtual destructor (necessary for other types). That's crazy
63
* because constexpr objects are never destroyed, so its crazy to care that they have a virtual DTOR.
64
* Still, g++ and msvc both agree on this; I think this MAYBE fixed in C++20 (not yet tested) - because
65
* there they at least allow virtual constexpr methods. That might impact (indirectly) whether an object
66
* can be constexpr (having a virtual dtor).
67
*/
68
template
<
typename
STRINGISH_T = Characters::String>
69
class
Activity
final :
public
Private_::Activities_::AsStringObj_
{
70
public
:
71
constexpr
Activity
(
const
STRINGISH_T& arg);
72
Activity
(
const
Activity
& src) =
default
;
73
74
public
:
75
virtual
Characters::String
AsString ()
const override
;
76
77
private
:
78
STRINGISH_T fArg_;
79
};
80
81
/**
82
*/
83
template
<
typename
CTOR_ARG>
84
Activity
(
const
CTOR_ARG& b) ->
Activity<CTOR_ARG>
;
85
86
/**
87
* When creating the activity would be expensive, just capture it in a lambda, and only convert that lambda to
88
* an actual string if/when CaptureCurrentActivities is called.
89
*
90
* \note would LIKE to know how to do this as a template specialization of Activity, but haven't figured that out yet.
91
*
92
* \par Example Usage
93
* \code
94
* auto scanningThisAddress = LazyEvalActivity ([&] () -> String { return "scanning ports on {}"_f (ia); });
95
* DeclareActivity da{&scanningThisAddress};
96
* \endcode
97
*/
98
template
<
typename
CTOR_ARG>
99
class
LazyEvalActivity
final :
public
Private_::Activities_::AsStringObj_
{
100
public
:
101
constexpr
LazyEvalActivity
(
const
CTOR_ARG& arg)
102
requires
(is_invocable_r_v<Characters::String, CTOR_ARG>);
103
104
public
:
105
virtual
Characters::String
AsString ()
const override
;
106
107
private
:
108
[[no_unique_address]] CTOR_ARG fArg_;
109
};
110
111
/**
112
* \brief Returns a copyable preservable version of the current activities stack.
113
*
114
* 'render' each current activity on the current threads activity stack as a Activity<> (so String based), and return the full
115
* list as a copyable stack of activities.
116
*
117
* \note the intended purpose of this is to provide better 'context' for default exception messages, when exceptions are
118
* created/thrown.
119
*
120
* \note the TOP of the static is the most specific activity, and the bottom of the stack is the initial, outermost task.
121
*/
122
Containers::Stack<Activity<>
>
CaptureCurrentActivities
();
123
124
/**
125
* Push the argument Activity onto the current thread's Activity stack in the constructor, and pop it off in the destructor.
126
*
127
* \par Example Usage
128
* \code
129
* static constexpr Activity kBuildingThingy_ {"building thingy"sv };
130
* try {
131
* DeclareActivity declareActivity { &kBuildingThingy_ };
132
* doBuildThing (); // throw any exception (that inherits from Exception<>)
133
* }
134
* catch (...) {
135
* String exceptionMsg = Characters::ToString (current_exception ());
136
* Assert (exceptionMsg.Contains (kBuildingThingy_.AsString ()); // exception e while building thingy...
137
* }
138
* \endcode
139
*/
140
template
<
typename
ACTIVITY>
141
class
DeclareActivity
{
142
public
:
143
/**
144
* The caller must always declare an Activity object whose address can be taken,
145
* and whose lifetime exceeds that of the DeclareActivity object.
146
*
147
* \note the Activity* argument MAY be nullptr, in which case this does nothing.
148
*
149
* This is allowed to facilitate examples like:
150
* \code
151
* DeclareActivity declareActivity { flag? &kSomeActivity_? nullptr }; // so we only conditionally declare the activity
152
* \endcode
153
*
154
* I considered using optional<ACTIVITY> - but tricky since we pass in pointer - and really not much point. This has practically zero
155
* overhead, and is easy enough to understand and use.
156
*/
157
DeclareActivity
() =
delete
;
158
DeclareActivity
(
const
DeclareActivity
&) =
delete
;
159
DeclareActivity
(
const
ACTIVITY* activity)
noexcept
;
160
~DeclareActivity
();
161
162
private
:
163
Private_::Activities_::StackElt_ fNewTopOfStackElt_;
164
};
165
166
}
167
168
/*
169
********************************************************************************
170
***************************** Implementation Details ***************************
171
********************************************************************************
172
*/
173
#include "Activity.inl"
174
175
#endif
/*_Stroika_Foundation_Execution_Activity_h_*/
Stack.h
String.h
Stroika::Foundation::Characters::String
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition
String.h:201
Stroika::Foundation::Containers::Stack
Definition
Stack.h:71
Stroika::Foundation::Execution::Activity
Definition
Activity.h:69
Stroika::Foundation::Execution::DeclareActivity
Definition
Activity.h:141
Stroika::Foundation::Execution::DeclareActivity::DeclareActivity
DeclareActivity()=delete
Stroika::Foundation::Execution::LazyEvalActivity
Definition
Activity.h:99
Stroika::Foundation::Execution
Definition
SDKString.inl:7
Stroika::Foundation::Execution::CaptureCurrentActivities
Containers::Stack< Activity<> > CaptureCurrentActivities()
Returns a copyable preservable version of the current activities stack.
Definition
Activity.cpp:19
Stroika::Foundation::Execution::Private_::Activities_::AsStringObj_
Definition
Activity.h:31
Library
Sources
Stroika
Foundation
Execution
Activity.h
Generated by
1.9.8