8#if !defined(ALIB_C20_MODULES) || ((ALIB_C20_MODULES != 0) && (ALIB_C20_MODULES != 1))
9# error "Symbol ALIB_C20_MODULES has to be given to the compiler as either 0 or 1"
19 module ALib.ALox.Impl;
23 import ALib.EnumRecords;
24 import ALib.EnumRecords.Bootstrap;
25 import ALib.Variables;
27 import ALib.Camp.Base;
48#if !ALIB_SINGLE_THREADED
57template<
typename T,
bool TStackedThreadValues>
64 #if ALIB_DEBUG_CRITICAL_SECTIONS
70template<
typename T,
bool TStackedThreadValues>
77template<
typename T,
bool TStackedThreadValues>
92 case Scope::ThreadInner:
97 #if !ALIB_SINGLE_THREADED
123 case Scope::Filename:
132 if( actValue !=
nullptr )
141 case Scope::ThreadOuter:
145 #if !ALIB_SINGLE_THREADED
174 default:
ALIB_ERROR(
"ALOX",
"Illegal switch state.") break;
185 if( self.actScope == Scope::Global ) {
186 oldValue= self.globalStore;
187 if ( cmd == CMD_INSERT )
188 self.globalStore= value;
189 else if ( cmd == CMD_REMOVE )
190 self.globalStore= nullptr;
197 if( self.actScope == Scope::ThreadOuter
198 || self.actScope == Scope::ThreadInner )
201 bool isInner= self.actScope == Scope::ThreadInner;
204 if ( cmd != CMD_INSERT && self.threadStore.Size() == 0 )
208 if ( self.actThreadID == threads::UNDEFINED )
209 self.actThreadID= self.scopeInfo.GetThreadID();
212 ALIB_ASSERT( cmd != CMD_REMOVE,
"ALOX" )
215 auto key = typename ScopeStore<T, true>::ThreadMapKey(isInner, self.actThreadID);
216 auto hash= typename decltype(self.threadStore)::HashType ()( key );
217 if ( cmd == CMD_GET ) {
218 auto it= self.threadStore.Find( key, hash );
219 if ( it != self.threadStore.end() )
227 self.threadStore.InsertUnique( std::make_pair( key, value), hash );
236 if ( cmd == CMD_INSERT && value ==
nullptr )
239 if ( self.lazyLanguageNode
240 || ( self.actStringTreeNode.IsInvalid() && cmd == CMD_INSERT ) )
241 self.initCursor(
true );
243 oldValue= *self.actStringTreeNode;
244 if ( cmd == CMD_INSERT ) *self.actStringTreeNode= value;
245 else if ( cmd == CMD_REMOVE ) *self.actStringTreeNode=
nullptr;
251 while ( self.walking )
switch( self.actScope ) {
252 case Scope::ThreadInner:
255 if ( self.walkNextThreadIdx == -2 ) {
256 self.walkNextThreadIdx= -1;
257 #if !ALIB_SINGLE_THREADED
258 if ( self.threadStore.Size() != 0 ) {
260 if ( it != self.threadStore.end() ) {
261 self.walkThreadValues= &it.Mapped();
262 self.walkNextThreadIdx= int( self.walkThreadValues->size() );
268 if ( self.walkNextThreadIdx > 0 ) {
269 --self.walkNextThreadIdx;
270 return (*self.walkThreadValues)[size_t(self.walkNextThreadIdx)];
274 self.actScope= Scope::Method;
277 if ( self.walkLocalObject !=
nullptr )
278 return self.walkLocalObject;
283 case Scope::Filename:
286 if( self.lazyLanguageNode )
287 self.initCursor(
false );
289 while( self.actStringTreeNode.IsValid() ) {
290 T actValue= *self.actStringTreeNode;
291 self.actStringTreeNode.GoToParent();
292 if( actValue !=
nullptr )
296 self.actScope= Scope::ThreadOuter;
297 self.walkNextThreadIdx= -2;
301 case Scope::ThreadOuter:
304 if ( self.walkNextThreadIdx == -2 ) {
305 #if !ALIB_SINGLE_THREADED
306 if ( self.threadStore.Size() != 0 ) {
308 if ( it != self.threadStore.end() ) {
309 self.walkThreadValues= &it.Mapped();
310 self.walkNextThreadIdx= int( self.walkThreadValues->size() );
316 if ( self.walkNextThreadIdx > 0 ) {
317 --self.walkNextThreadIdx;
318 return (*self.walkThreadValues)[size_t(self.walkNextThreadIdx)];
322 self.actScope= Scope::Global;
329 return self.globalStore;
333 default:
ALIB_ERROR(
"ALOX",
"Illegal switch state.") break;
342 int cmd , T value ) {
347 if( self.actScope == Scope::Global ) {
348 oldValue= self.globalStore;
349 if ( cmd == CMD_INSERT ) self.globalStore= value;
350 else if ( cmd == CMD_REMOVE ) self.globalStore= nullptr;
357 if( self.actScope == Scope::ThreadOuter
358 || self.actScope == Scope::ThreadInner )
361 bool isInner= self.actScope == Scope::ThreadInner;
364 if ( cmd != CMD_INSERT && self.threadStore.Size() == 0 )
368 if ( self.actThreadID == threads::UNDEFINED )
369 self.actThreadID= self.scopeInfo.GetThreadID();
373 StdVectorMA<T>* values;
375 values= &self.threadStore.EmplaceIfNotExistent(
376 typename ScopeStore<T, true>::ThreadMapKey(isInner, self.actThreadID),
377 self.threadStore.GetAllocator() ).first.Mapped();
381 if ( cmd == CMD_GET )
382 return ( values->size() > 0) ? (*values)[ values->size() -1 ] :
nullptr;
385 if ( cmd == CMD_INSERT ) {
386 values->emplace_back( value );
391 if ( cmd == CMD_REMOVE && values->size() > 0) {
393 if ( value == nullptr ) {
394 oldValue= values->back();
400 for (
auto rem= values->begin() ; rem != values->end(); ++rem )
401 if ( (*rem) == value ) {
404 values->erase( rem );
414 if ( cmd == CMD_INSERT && value ==
nullptr )
417 if ( self.lazyLanguageNode
418 || ( self.actStringTreeNode.IsInvalid() && cmd == CMD_INSERT ) )
419 self.initCursor(
true );
421 oldValue= *self.actStringTreeNode;
422 if ( cmd == CMD_INSERT ) *self.actStringTreeNode= value;
423 else if ( cmd == CMD_REMOVE ) *self.actStringTreeNode=
nullptr;
436template<
typename T,
bool TStackedThreadValues>
444 #if defined( _WIN32 )
455 if ( remainingPath.IsNotEmpty() )
488template<
typename T,
bool TStackedThreadValues>
493#if !ALIB_SINGLE_THREADED
510template class ScopeStore <NString , true>;
513template class ScopeStore <PrefixLogable* , true>;
516template class ScopeStore <SSMap<int>*,
false>;
519template class ScopeStore <SSMap<Box>*,
false>;
threads::ThreadID GetThreadID()
threads::ThreadID actThreadID
Actual thread ID.
Scope actScope
The actual scope of a walk.
TLanguageStore languageStore
StringTree to store data for language-related scopes (path,source,method).
T globalStore
The value of the global scope.
void initCursor(bool create)
ALIB_DLL ScopeStore(ScopeInfo &scopeInfo, MonoAllocator &monoAllocator)
bool lazyLanguageNode
Flag used to lazily create the key to language-related scope values.
HashMap< MonoAllocator, ThreadMapKey, TThreadMapValue, BoolThreadIDHash > threadStore
std::pair< bool, threads::ThreadID > ThreadMapKey
Key type for the thread store.
TLanguageStore::Cursor actStringTreeNode
The actual language related scope's map node.
int walkNextThreadIdx
The next value of a walk during Scope::ThreadInner/Outer.
T walkLocalObject
The 'local object' returned by a walk after Scope::ThreadInner and before Scope::Method.
ALIB_DLL ~ScopeStore()
Destructor.
ALIB_DLL void InitWalk(Scope startScope, const T localObject)
ALIB_DLL void InitAccess(Scope scope, int pathLevel, threads::ThreadID threadID)
bool walking
Indicates if currently a scope walk is active.
int actPathLevel
The path level when using access methods.
ScopeInfo & scopeInfo
ScopeInfo of 'our' lox.
TThreadMapValue * walkThreadValues
The list of values of Scope::ThreadOuter/Inner during a walk.
ALIB_DLL integer SearchAndReplace(TChar needle, TChar replacement, integer startIdx=0, integer endIdx=strings::MAX_LEN)
TAString & _(const TAppendable &src)
#define IF_ALIB_THREADS(...)
#define ALIB_ASSERT(cond, domain)
#define ALIB_WARNINGS_RESTORE
#define ALIB_ERROR(domain,...)
#define ALIB_WARNINGS_IGNORE_NOT_ELIDING_COPY_ON_RETURN
#define ALIB_SINGLE_THREADED
integer ThreadID
The ALib thread identifier type.
LocalString< 512 > String512
Type alias name for TLocalString<character,512>.
monomem::TMonoAllocator< lang::HeapAllocator > MonoAllocator
T doWalk(ScopeStore< T, TStackedThreadValues > &self)