@@ -471,14 +471,14 @@ namespace Jrd {
471471 template <class Object , unsigned SUBARRAY_SHIFT = 8 >
472472 class HazardArray : public Firebird ::PermanentStorage
473473 {
474- private :
474+ public :
475475 static const unsigned SUBARRAY_SIZE = 1 << SUBARRAY_SHIFT;
476476 static const unsigned SUBARRAY_MASK = SUBARRAY_SIZE - 1 ;
477477
478478 typedef std::atomic<Object*> SubArrayElement;
479479 typedef std::atomic<SubArrayElement*> ArrayElement;
480+ typedef SharedReadVector<ArrayElement, 4 > Storage;
480481
481- public:
482482 explicit HazardArray (MemoryPool& pool)
483483 : Firebird::PermanentStorage(pool),
484484 m_objects(getPool())
@@ -533,6 +533,11 @@ namespace Jrd {
533533 return m_objects.readAccessor (par)->getCount () << SUBARRAY_SHIFT;
534534 }
535535
536+ static FB_SIZE_T getCount (const HazardPtr<typename Storage::Generation>& v)
537+ {
538+ return v->getCount () << SUBARRAY_SHIFT;
539+ }
540+
536541 void grow (thread_db* tdbb, FB_SIZE_T reqSize)
537542 {
538543 fb_assert (reqSize > 0 );
@@ -594,9 +599,9 @@ namespace Jrd {
594599 template <class DDS >
595600 bool load (DDS* par, FB_SIZE_T id, HazardPtr<Object>& val) const
596601 {
597- if (id < getCount (par))
602+ auto a = m_objects.readAccessor (par);
603+ if (id < getCount (a))
598604 {
599- auto a = m_objects.readAccessor (par);
600605 SubArrayElement* sub = a->value (id >> SUBARRAY_SHIFT).load (std::memory_order_acquire);
601606 if (sub)
602607 {
@@ -613,11 +618,20 @@ namespace Jrd {
613618 HazardPtr<Object> load (DDS* par, FB_SIZE_T id) const
614619 {
615620 HazardPtr<Object> val;
616- load (par, id, val);
621+ if (!load (par, id, val))
622+ val.clear ();
617623 return val;
618624 }
619625
620- class iterator
626+ template <class DDS >
627+ HazardPtr<typename Storage::Generation> readAccessor (DDS* par) const
628+ {
629+ return m_objects.readAccessor (par);
630+ }
631+
632+ class Snapshot ;
633+
634+ class Iterator
621635 {
622636 public:
623637 HazardPtr<Object> operator *()
@@ -630,27 +644,21 @@ namespace Jrd {
630644 return get ();
631645 }
632646
633- iterator& operator ++()
634- {
635- ++index;
636- return *this ;
637- }
638-
639- iterator& operator --()
647+ Iterator& operator ++()
640648 {
641- -- index;
649+ index = snap-> locateData ( index + 1 ) ;
642650 return *this ;
643651 }
644652
645- bool operator ==(const iterator & itr) const
653+ bool operator ==(const Iterator & itr) const
646654 {
647- fb_assert (array == itr.array );
655+ fb_assert (snap == itr.snap );
648656 return index == itr.index ;
649657 }
650658
651- bool operator !=(const iterator & itr) const
659+ bool operator !=(const Iterator & itr) const
652660 {
653- fb_assert (array == itr.array );
661+ fb_assert (snap == itr.snap );
654662 return index != itr.index ;
655663 }
656664
@@ -660,33 +668,90 @@ namespace Jrd {
660668
661669 public:
662670 enum class Location {Begin, End};
663- iterator (const HazardArray* a , Location loc = Location::Begin )
664- : array(a ),
671+ Iterator (const Snapshot* s , Location loc)
672+ : snap(s ),
665673 hd (HazardPtr<Object>::getHazardDelayed()),
666- index(loc == Location::Begin ? 0 : array->getCount (hd))
674+ index(loc == Location::Begin ? snap->locateData (0 ) :
675+ snap->data->getCount() << SUBARRAY_SHIFT)
667676 { }
668677
669678 HazardPtr<Object> get ()
670679 {
671680 HazardPtr<Object> rc (hd);
672- array->load (hd, index, rc);
681+ if (!snap->load (index, rc))
682+ rc.clear ();
673683 return rc;
674684 }
675685
676686 private:
677- const HazardArray* array ;
687+ const Snapshot* snap ;
678688 HazardDelayedDelete* hd;
679689 FB_SIZE_T index;
680690 };
681691
682- iterator begin () const
692+ class Snapshot
683693 {
684- return iterator (this );
685- }
694+ private:
695+ void * operator new (size_t );
696+ void * operator new [](size_t );
697+
698+ public:
699+ Snapshot (const HazardArray* array)
700+ : hd(HazardPtr<Object>::getHazardDelayed()),
701+ data (array->readAccessor (hd))
702+ { }
703+
704+ Iterator begin () const
705+ {
706+ return Iterator (this , Iterator::Location::Begin);
707+ }
708+
709+ Iterator end () const
710+ {
711+ return Iterator (this , Iterator::Location::End);
712+ }
713+
714+ FB_SIZE_T locateData (FB_SIZE_T index) const
715+ {
716+ for (FB_SIZE_T i = index >> SUBARRAY_SHIFT; i < data->getCount (); ++i, index = 0 )
717+ {
718+ SubArrayElement* const sub = data->value (i).load (std::memory_order_acquire);
719+ if (!sub)
720+ continue ;
721+
722+ for (FB_SIZE_T j = index & SUBARRAY_MASK; j < SUBARRAY_SIZE; ++j)
723+ {
724+ auto p = sub[j].load (std::memory_order_acquire);
725+ if (p && p->hasData ())
726+ return (i << SUBARRAY_SHIFT) + j;
727+ }
728+ }
729+ return data->getCount () << SUBARRAY_SHIFT;
730+ }
731+
732+ bool load (FB_SIZE_T id, HazardPtr<Object>& val) const
733+ {
734+ if (id < (data->getCount () << SUBARRAY_SHIFT))
735+ {
736+ SubArrayElement* sub = data->value (id >> SUBARRAY_SHIFT).load (std::memory_order_acquire);
737+ if (sub)
738+ {
739+ val.set (sub[id & SUBARRAY_MASK]);
740+ if (val && val->hasData ())
741+ return true ;
742+ }
743+ }
744+
745+ return false ;
746+ }
747+
748+ HazardDelayedDelete* hd;
749+ HazardPtr<typename Storage::Generation> data;
750+ };
686751
687- iterator end () const
752+ Snapshot snapshot () const
688753 {
689- return iterator (this , iterator::Location::End );
754+ return Snapshot (this );
690755 }
691756
692757 private:
0 commit comments