36 private $activeUpdate;
40 private $queueByStage;
47 private function __construct(
52 $this->activeStage = $activeStage;
53 $this->activeUpdate = $update;
54 $this->parentScope = $parentScope;
55 $this->queueByStage = array_fill_keys( DeferredUpdates::STAGES, [] );
62 return new self(
null,
null, null );
76 return new self( $activeStage, $update, $parentScope );
85 return $this->activeUpdate;
96 $stageEffective = max( $stage, $this->activeStage );
98 $queue =& $this->queueByStage[$stageEffective];
101 $class = get_class( $update );
102 if ( isset( $queue[$class] ) ) {
104 $existingUpdate = $queue[$class];
105 '@phan-var MergeableUpdate $existingUpdate';
106 $existingUpdate->merge( $update );
109 unset( $queue[$class] );
110 $queue[$class] = $existingUpdate;
112 $queue[$class] = $update;
125 return array_sum( array_map(
'count', $this->queueByStage ) );
135 $matchingQueues = [];
136 foreach ( $this->queueByStage as $queueStage => $queue ) {
137 if ( $stage === DeferredUpdates::ALL || $stage === $queueStage ) {
138 $matchingQueues[] = $queue;
142 return array_merge( ...$matchingQueues );
149 $this->queueByStage = array_fill_keys( array_keys( $this->queueByStage ), [] );
161 $claimedUpdates = [];
162 foreach ( $this->queueByStage as $queueStage => $queue ) {
163 if ( $stage === DeferredUpdates::ALL || $stage === $queueStage ) {
164 foreach ( $queue as $k => $update ) {
165 if ( $update instanceof $class ) {
166 $claimedUpdates[] = $update;
167 unset( $this->queueByStage[$queueStage][$k] );
173 foreach ( $claimedUpdates as $update ) {
174 $callback( $update );
187 if ( $stage === DeferredUpdates::ALL ) {
189 $activeStage = DeferredUpdates::STAGES[count( DeferredUpdates::STAGES ) - 1];
192 $activeStage = max( $stage, $this->activeStage );
196 $processed = $this->upmergeUnreadyUpdates( $activeStage );
197 foreach ( range( DeferredUpdates::STAGES[0], $activeStage ) as $queueStage ) {
198 $processed += $this->processStageQueue( $queueStage, $activeStage, $callback );
200 }
while ( $processed > 0 );
213 private function upmergeUnreadyUpdates( $activeStage ) {
216 if ( !$this->parentScope ) {
220 foreach ( $this->queueByStage as $queueStage => $queue ) {
221 foreach ( $queue as $k => $update ) {
222 if ( $update instanceof MergeableUpdate || $queueStage > $activeStage ) {
223 unset( $this->queueByStage[$queueStage][$k] );
224 $this->parentScope->addUpdate( $update, $queueStage );
239 private function processStageQueue( $stage, $activeStage, callable $callback ) {
243 $claimedUpdates = $this->queueByStage[$stage];
244 $this->queueByStage[$stage] = [];
247 while ( $claimedUpdates ) {
253 $claimedDataUpdates = [];
254 $claimedGenericUpdates = [];
255 foreach ( $claimedUpdates as $claimedUpdate ) {
256 if ( $claimedUpdate instanceof DataUpdate ) {
257 $claimedDataUpdates[] = $claimedUpdate;
259 $claimedGenericUpdates[] = $claimedUpdate;
265 foreach ( $claimedDataUpdates as $claimedDataUpdate ) {
266 $callback( $claimedDataUpdate, $activeStage );
268 foreach ( $claimedGenericUpdates as $claimedGenericUpdate ) {
269 $callback( $claimedGenericUpdate, $activeStage );
273 $claimedUpdates = $this->queueByStage[$stage];
274 $this->queueByStage[$stage] = [];