34 private $activeUpdate;
38 private $queueByStage;
45 private function __construct(
50 $this->activeStage = $activeStage;
51 $this->activeUpdate = $update;
52 $this->parentScope = $parentScope;
53 $this->queueByStage = array_fill_keys( DeferredUpdates::STAGES, [] );
60 return new self(
null,
null, null );
74 return new self( $activeStage, $update, $parentScope );
83 return $this->activeUpdate;
94 $stageEffective = max( $stage, $this->activeStage );
96 $queue =& $this->queueByStage[$stageEffective];
99 $class = get_class( $update );
100 if ( isset(
$queue[$class] ) ) {
102 $existingUpdate =
$queue[$class];
103 '@phan-var MergeableUpdate $existingUpdate';
104 $existingUpdate->merge( $update );
108 $queue[$class] = $existingUpdate;
123 return array_sum( array_map(
'count', $this->queueByStage ) );
133 $matchingQueues = [];
134 foreach ( $this->queueByStage as $queueStage =>
$queue ) {
135 if ( $stage === DeferredUpdates::ALL || $stage === $queueStage ) {
136 $matchingQueues[] =
$queue;
140 return array_merge( ...$matchingQueues );
147 $this->queueByStage = array_fill_keys( array_keys( $this->queueByStage ), [] );
159 $claimedUpdates = [];
160 foreach ( $this->queueByStage as $queueStage =>
$queue ) {
161 if ( $stage === DeferredUpdates::ALL || $stage === $queueStage ) {
162 foreach (
$queue as $k => $update ) {
163 if ( $update instanceof $class ) {
164 $claimedUpdates[] = $update;
165 unset( $this->queueByStage[$queueStage][$k] );
171 foreach ( $claimedUpdates as $update ) {
172 $callback( $update );
185 if ( $stage === DeferredUpdates::ALL ) {
187 $activeStage = DeferredUpdates::STAGES[count( DeferredUpdates::STAGES ) - 1];
190 $activeStage = max( $stage, $this->activeStage );
194 $processed = $this->upmergeUnreadyUpdates( $activeStage );
195 foreach ( range( DeferredUpdates::STAGES[0], $activeStage ) as $queueStage ) {
196 $processed += $this->processStageQueue( $queueStage, $activeStage, $callback );
198 }
while ( $processed > 0 );
211 private function upmergeUnreadyUpdates( $activeStage ) {
214 if ( !$this->parentScope ) {
218 foreach ( $this->queueByStage as $queueStage =>
$queue ) {
219 foreach (
$queue as $k => $update ) {
220 if ( $update instanceof
MergeableUpdate || $queueStage > $activeStage ) {
221 unset( $this->queueByStage[$queueStage][$k] );
222 $this->parentScope->addUpdate( $update, $queueStage );
237 private function processStageQueue( $stage, $activeStage, callable $callback ) {
241 $claimedUpdates = $this->queueByStage[$stage];
242 $this->queueByStage[$stage] = [];
245 while ( $claimedUpdates ) {
251 $claimedDataUpdates = [];
252 $claimedGenericUpdates = [];
253 foreach ( $claimedUpdates as $claimedUpdate ) {
255 $claimedDataUpdates[] = $claimedUpdate;
257 $claimedGenericUpdates[] = $claimedUpdate;
263 foreach ( $claimedDataUpdates as $claimedDataUpdate ) {
264 $callback( $claimedDataUpdate, $activeStage );
266 foreach ( $claimedGenericUpdates as $claimedGenericUpdate ) {
267 $callback( $claimedGenericUpdate, $activeStage );
271 $claimedUpdates = $this->queueByStage[$stage];
272 $this->queueByStage[$stage] = [];