libbio
Loading...
Searching...
No Matches
UnorderedStructureDetail.h
Go to the documentation of this file.
1/*
2 * This file is a part of the Biology project by eons LLC.
3 * Biology (aka Develop Biology) is a framework for approaching software
4 * development from a natural sciences perspective.
5 *
6 * Copyright (C) 2024 Séon O'Shannon & eons LLC
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as
10 * published by the Free Software Foundation, either version 3 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 */
21
22#pragma once
23
34
35#include <cstddef>
36#include <vector>
37
38namespace bio {
39namespace chemical {
40
41class UnorderedStructureInterface;
42
43namespace structure {
44
45template < typename T >
56
94inline void TryAddWaveCollectVisitor(const Bond& bond, void* ctx)
95{
96 std::vector< Pointer< physical::Wave > >* candidates =
97 static_cast< std::vector< Pointer< physical::Wave > >* >(ctx);
98 Pointer< physical::Wave > bonded = const_cast< Bond& >(bond).GetBonded();
99 if (!bonded)
100 {
101 return;
102 }
103 candidates->push_back(bonded);
104}
105
109)
110{
111 if (!host || !payload)
112 {
113 return false;
114 }
115 Pointer< Atom > hostAtom = host->AsAtom();
116 if (!hostAtom)
117 {
118 return false;
119 }
120 // RFC §5 step 3: snapshot bonded Wave* under hostAtom's shared lock,
121 // then do the motif-accept dance outside the lock. The motif accept
122 // calls back into add-implementation paths that may acquire other
123 // Atom locks (the target's mBonds), so we must NOT be holding
124 // hostAtom's lock during that call.
125 std::vector< Pointer< physical::Wave > > candidates;
127
128 for (std::size_t i = 0; i < candidates.size(); ++i)
129 {
131 // No-RTTI Wave* -> AbstractMotif* cross-cast. The codebase forbids
132 // dynamic_cast (PeriodicTable is the type-info substitute); the
133 // canonical alternative is the Atom bond mechanism — every
134 // UnorderedMotif registers a Quantum<AbstractMotif> bond on its
135 // own Atom that exposes its AbstractMotif subobject with the
136 // correct multi-inheritance offset (see
137 // UnorderedMotif::RegisterAsAbstractMotifBond). Atom::As<>'s
138 // AsBondedQuantum path returns NULL when no such bond exists,
139 // so this safely yields NULL for non-motif bonded waves.
140 Pointer< Atom > bondedAtom = bonded->AsAtom();
141 if (!bondedAtom)
142 {
143 continue;
144 }
146 if (!motif)
147 {
148 continue;
149 }
151 if (!clone)
152 {
153 continue;
154 }
155 if (motif->AddWaveByContentType(clone))
156 {
157 return true;
158 }
159 Delete(clone);
160 }
161 return false;
162}
163
195)
196{
197 if (!host || !payload)
198 {
199 return false;
200 }
201 Pointer< Atom > hostAtom = host->AsAtom();
202 if (!hostAtom)
203 {
204 return false;
205 }
206 // RFC §5 step 3: snapshot under shared, share-add outside the lock.
207 // See TryAddWaveToAnyMotif for the lock-discipline rationale.
208 std::vector< Pointer< physical::Wave > > candidates;
210
211 for (std::size_t i = 0; i < candidates.size(); ++i)
212 {
214 Pointer< Atom > bondedAtom = bonded->AsAtom();
215 if (!bondedAtom)
216 {
217 continue;
218 }
220 if (!motif)
221 {
222 continue;
223 }
224 if (motif->AddSharedWaveByContentType(payload))
225 {
226 return true;
227 }
228 }
229 return false;
230}
231
232template < typename MOTIF >
234{
235 BIO_SANITIZE(bonded, , return false)
236 // Fast path: cached typeId on Wave matches MOTIF's. Lock-free,
237 // O(1), and crucially avoids the bonded->Spin() recursion loop
238 // where Molecule::Spin -> GetAll<Surface> -> ResolveLinearMotif ->
239 // IsBondedMotifType → bonded->Spin() (back into Molecule::Spin).
240 if (WaveHasExactTypeId< MOTIF >(bonded))
241 {
242 return true;
243 }
244 // Slow path: legacy Symmetry-name comparison. Required when (a)
245 // BIO_MEMORY_OPTIMIZE_LEVEL > 0 disables the typeId cache, or (b)
246 // bonded is a subclass of MOTIF rather than an exact match.
247 Pointer< const physical::Symmetry > symmetry = bonded->GetSymmetry();
248 if (!symmetry)
249 {
250 // Deferred Symmetry: explicitly skip Spin() here — same recursion
251 // concern as above. The exact-match case was covered by the
252 // typeId fast-path; subclass-match for never-Spun objects would
253 // have to materialise via Spin first if a caller depends on it.
254 return false;
255 }
256 static const Name expected(type::TypeName< MOTIF >());
260}
261
275
276inline void MotifCandidateCollectVisitor(const Bond& bond, void* ctx)
277{
278 std::vector< MotifCandidate >* out =
279 static_cast< std::vector< MotifCandidate >* >(ctx);
280 Pointer< physical::Wave > bonded = const_cast< Bond& >(bond).GetBonded();
281 if (!bonded)
282 {
283 return;
284 }
285 out->push_back(MotifCandidate(bond.GetId(), bonded));
286}
287
288template < typename T >
290{
291 if (!self)
292 {
293 return NULL;
294 }
295 const AtomicNumber expectedBondId = Atom::GetBondId< UnorderedMotif< T > >();
296
297 // Fast path: GetBondPosition + GetBonded each take a shared lock
298 // internally; we don't nest. GetBonded(position) returns NULL on
299 // !IsAllocated or empty bond, replacing the legacy explicit checks.
300 // Because GetBondPosition< UnorderedMotif<T> >() resolves through
301 // the slot whose Id equals expectedBondId, the legacy
302 // "bond->GetId() == expectedBondId || IsBondedMotifType(...)"
303 // short-circuit is always satisfied on this path.
304 // RFC §5 step 3.
306 if (position)
307 {
308 Pointer< physical::Wave > bonded = self->GetBonded(position);
309 if (bonded)
310 {
313 if (bondedClass)
314 {
315 return bondedClass->GetWaveObject();
316 }
317 }
318 }
319
320 // Slow path: snapshot all (id, bonded) pairs under shared, then
321 // scan in reverse order to match the legacy End->Begin walk.
322 std::vector< MotifCandidate > candidates;
324 for (std::size_t i = candidates.size(); i; --i)
325 {
326 const MotifCandidate& cand = candidates[i - 1];
327 if (cand.id != expectedBondId)
328 {
329 continue;
330 }
333 if (!bondedClass)
334 {
335 continue;
336 }
337 return bondedClass->GetWaveObject();
338 }
339 return NULL;
340}
341
342template < typename T >
344{
345 if (!self)
346 {
347 return NULL;
348 }
349 const AtomicNumber expectedBondId = Atom::GetBondId< UnorderedMotif< T > >();
350
351 // Fast path — see non-const sibling for RFC §5 step 3 notes.
353 if (position)
354 {
355 Pointer< const physical::Wave > bonded = self->GetBonded(position);
356 if (bonded)
357 {
360 if (bondedClass)
361 {
362 return bondedClass->GetWaveObject();
363 }
364 }
365 }
366
367 // Slow path — snapshot then walk reverse for End->Begin parity.
368 std::vector< MotifCandidate > candidates;
370 for (std::size_t i = candidates.size(); i; --i)
371 {
372 const MotifCandidate& cand = candidates[i - 1];
373 if (cand.id != expectedBondId)
374 {
375 continue;
376 }
379 if (!bondedClass)
380 {
381 continue;
382 }
383 return bondedClass->GetWaveObject();
384 }
385 return NULL;
386}
387
388template < typename T >
390{
391 if (!self)
392 {
393 return NULL;
394 }
395 const AtomicNumber expectedBondId = Atom::GetBondId< LinearMotif< T > >();
397
398 // Fast path — see ResolveUnorderedMotif for RFC §5 step 3 notes.
400 if (position)
401 {
402 Pointer< physical::Wave > bonded = self->GetBonded(position);
403 if (bonded && IsBondedMotifType< LinearMotif< T > >(bonded))
404 {
407 if (bondedClass)
408 {
409 Pointer< LinearMotif< T > > motif = bondedClass->GetWaveObject();
410 if (motif && motif->mContentId == expectedId)
411 {
412 return motif;
413 }
414 }
415 }
416 }
417
418 // Slow path — snapshot then walk reverse for End->Begin parity.
419 std::vector< MotifCandidate > candidates;
421 for (std::size_t i = candidates.size(); i; --i)
422 {
423 const MotifCandidate& cand = candidates[i - 1];
424 if (cand.id != expectedBondId)
425 {
426 continue;
427 }
430 if (!bondedClass)
431 {
432 continue;
433 }
434 Pointer< LinearMotif< T > > motif = bondedClass->GetWaveObject();
435 if (motif && motif->mContentId == expectedId)
436 {
437 return motif;
438 }
439 }
440 return NULL;
441}
442
443template < typename T >
445{
446 if (!self)
447 {
448 return NULL;
449 }
450 const AtomicNumber expectedBondId = Atom::GetBondId< LinearMotif< T > >();
452
453 // Fast path — see ResolveUnorderedMotif for RFC §5 step 3 notes.
455 if (position)
456 {
457 Pointer< const physical::Wave > bonded = self->GetBonded(position);
458 if (bonded && IsBondedMotifType< LinearMotif< T > >(bonded))
459 {
462 if (bondedClass)
463 {
465 if (motif && motif->mContentId == expectedId)
466 {
467 return motif;
468 }
469 }
470 }
471 }
472
473 // Slow path — snapshot then walk reverse for End->Begin parity.
474 std::vector< MotifCandidate > candidates;
476 for (std::size_t i = candidates.size(); i; --i)
477 {
478 const MotifCandidate& cand = candidates[i - 1];
479 if (cand.id != expectedBondId)
480 {
481 continue;
482 }
485 if (!bondedClass)
486 {
487 continue;
488 }
490 if (motif && motif->mContentId == expectedId)
491 {
492 return motif;
493 }
494 }
495 return NULL;
496}
497
498template < typename T, bool kIsPointer >
500{
509
518
520 {
522 if (linear)
523 {
524 return linear->GetCountImplementation();
525 }
528 return implementer->GetCountImplementation(),
529 return 0
530 )
531 }
532
546
560
562 {
565 return implementer->HasImplementation(content),
566 return false
567 )
568 }
569};
570
571template < typename T, bool kUseWrappedMotif >
573{
575 {
576 return 0;
577 }
578
583
588
593
598
600 {
601 return false;
602 }
603};
604
605template < typename T >
607{
610
612 {
614 if (implementer)
615 {
616 Wrapped added = implementer->AddImplementation(t);
617 return added.Get();
618 }
619 return 0;
620 }
621
623 {
625 if (implementer)
626 {
627 return implementer->RemoveImplementation(t);
628 }
629 return code::BadArgument1();
630 }
631
633 {
635 if (implementer)
636 {
637 return implementer->GetCountImplementation();
638 }
639 return 0;
640 }
641
651
661
663 {
665 if (implementer)
666 {
667 return implementer->HasImplementation(content);
668 }
669 return false;
670 }
671};
672
673template < typename T >
675{
677
695
713
731
749
767
769 {
771 if (implementer)
772 {
773 return implementer->HasImplementation(content);
774 }
776 T,
778 >::Has(self, content);
779 if (wrapped)
780 {
781 return true;
782 }
784 }
785};
786
787} //structure namespace
788} //chemical namespace
789} //bio namespace
#define BIO_SANITIZE_AT_SAFETY_LEVEL_1(test, success, failure)
Definition SanitizeMacros.h:55
#define BIO_SANITIZE(test, success, failure)
Definition SanitizeMacros.h:94
Definition Pointer.h:115
T * Get() const
Definition Pointer.h:271
Definition String.h:55
Definition AbstractMotif.h:46
Definition Bond.h:46
bool IsBondedMotifType(Pointer< const physical::Wave > bonded)
Definition UnorderedStructureDetail.h:233
bool TryAddWaveToAnyMotif(Pointer< physical::Wave > host, Pointer< physical::Wave > payload)
Definition UnorderedStructureDetail.h:106
void TryAddWaveCollectVisitor(const Bond &bond, void *ctx)
Definition UnorderedStructureDetail.h:94
bool TryShareWaveWithAnyMotif(Pointer< physical::Wave > host, Pointer< physical::Wave > payload)
Definition UnorderedStructureDetail.h:192
Pointer< UnorderedMotif< T > > ResolveUnorderedMotif(Pointer< UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:289
Pointer< LinearMotif< T > > ResolveLinearMotif(Pointer< UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:389
void MotifCandidateCollectVisitor(const Bond &bond, void *ctx)
Definition UnorderedStructureDetail.h:276
Code BadArgument1()
String NormalizeTypeName(const String &name)
Definition NormalizeTypeName.h:41
Definition FinalCell.h:29
void Delete(Pointer< T > wrapped)
Definition Pointer.h:412
Definition UnorderedStructureDetail.h:47
type::RemovePointer< T >::Type Pointee
Definition UnorderedStructureDetail.h:48
Pointer< Pointee > WrappedPointer
Definition UnorderedStructureDetail.h:49
static AtomicNumber Get()
Definition UnorderedStructureDetail.h:51
static Pointer< const Container > GetAll(Pointer< const UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:750
type::RemovePointer< T >::Type Pointee
Definition UnorderedStructureDetail.h:676
static Index GetCount(Pointer< const UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:714
static T Add(Pointer< UnorderedStructureInterface > self, const T t)
Definition UnorderedStructureDetail.h:678
static bool Has(Pointer< const UnorderedStructureInterface > self, T content)
Definition UnorderedStructureDetail.h:768
static Code Remove(Pointer< UnorderedStructureInterface > self, const T t)
Definition UnorderedStructureDetail.h:696
static Pointer< Container > GetAll(Pointer< UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:732
Definition UnorderedStructureDetail.h:500
static Index GetCount(Pointer< const UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:519
static Pointer< Container > GetAll(Pointer< UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:533
static T Add(Pointer< UnorderedStructureInterface > self, const T t)
Definition UnorderedStructureDetail.h:501
static Pointer< const Container > GetAll(Pointer< const UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:547
static Code Remove(Pointer< UnorderedStructureInterface > self, const T t)
Definition UnorderedStructureDetail.h:510
static bool Has(Pointer< const UnorderedStructureInterface > self, T content)
Definition UnorderedStructureDetail.h:561
Definition UnorderedStructureDetail.h:269
MotifCandidate(AtomicNumber i, Pointer< physical::Wave > b)
Definition UnorderedStructureDetail.h:273
AtomicNumber id
Definition UnorderedStructureDetail.h:270
Pointer< physical::Wave > bonded
Definition UnorderedStructureDetail.h:271
MotifCandidate()
Definition UnorderedStructureDetail.h:272
type::RemovePointer< T >::Type Pointee
Definition UnorderedStructureDetail.h:608
static bool Has(Pointer< const UnorderedStructureInterface > self, T content)
Definition UnorderedStructureDetail.h:662
static Pointer< Container > GetAll(Pointer< UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:642
static T Add(Pointer< UnorderedStructureInterface > self, const T t)
Definition UnorderedStructureDetail.h:611
Pointer< Pointee > Wrapped
Definition UnorderedStructureDetail.h:609
static Code Remove(Pointer< UnorderedStructureInterface > self, const T t)
Definition UnorderedStructureDetail.h:622
static Pointer< const Container > GetAll(Pointer< const UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:652
static Index GetCount(Pointer< const UnorderedStructureInterface > self)
Definition UnorderedStructureDetail.h:632
Definition UnorderedStructureDetail.h:573
static Code Remove(Pointer< UnorderedStructureInterface >, const T)
Definition UnorderedStructureDetail.h:579
static Pointer< Container > GetAll(Pointer< UnorderedStructureInterface >)
Definition UnorderedStructureDetail.h:589
static Pointer< const Container > GetAll(Pointer< const UnorderedStructureInterface >)
Definition UnorderedStructureDetail.h:594
static T Add(Pointer< UnorderedStructureInterface >, const T)
Definition UnorderedStructureDetail.h:574
static bool Has(Pointer< const UnorderedStructureInterface >, T)
Definition UnorderedStructureDetail.h:599
static Index GetCount(Pointer< const UnorderedStructureInterface >)
Definition UnorderedStructureDetail.h:584
Definition IsPointer.h:79