Class: Nanoc::Core::ItemRepSelector::ItemRepPriorityQueue

Inherits:
Object
  • Object
show all
Defined in:
lib/nanoc/core/item_rep_selector.rb

Overview

A priority queue that tracks dependencies and can detect circular dependencies.

Instance Method Summary collapse

Constructor Details

#initialize(outdated_reps:, reps:, dependency_store:) ⇒ ItemRepPriorityQueue

Returns a new instance of ItemRepPriorityQueue.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/nanoc/core/item_rep_selector.rb', line 16

def initialize(outdated_reps:, reps:, dependency_store:)
  @reps = reps
  @dependency_store = dependency_store

  # Prio A: most important; prio C: least important.
  @prio_a = nil
  @prio_b = outdated_reps.dup
  @prio_c = []

  # List of reps that we’ve already seen. Reps from `reps` will end up
  # in here. Reps can end up in here even *before* they come from
  # `reps`, when they are part of a dependency.
  @seen = Set.new

  # List of reps that have already been completed (yielded followed by
  # `#mark_ok`).
  @completed = Set.new

  # Record (hard) dependencies. Used for detecting cycles.
  @dependencies = Hash.new { |hash, key| hash[key] = Set.new }
end

Instance Method Details

#mark_failed(needed_rep:) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
# File 'lib/nanoc/core/item_rep_selector.rb', line 67

def mark_failed(needed_rep:)
  record_dependency(needed_rep)

  # `@this` depends on `needed_rep`, so `needed_rep` has to be compiled
  # first. Thus, move `@this` into priority C, and `needed_rep` into
  # priority A.

  # Put `@this` (item rep that needs `needed_rep` to be compiled first)
  # into priority C (lowest prio).
  @prio_c.push(@this) unless @prio_c.include?(@this)

  # Put `needed_rep` (item rep that needs to be compiled first, before
  # `@this`) into priority A (highest prio).
  @prio_a = needed_rep

  # Remember that we’ve prioritised `needed_rep`. This particular
  # element will come from @prio_b at some point in the future, so we’ll
  # have to skip it then.
  @seen << needed_rep

  # Add everything else that `@this` depends on to the queue. It is OK
  # if there are duplicates; `#next` will filter them out.
  @dependency_store.objects_causing_outdatedness_of(@this.item).each do |obj|
    if obj.is_a?(Nanoc::Core::Item)
      item = obj

      @reps[item].each do |rep|
        @prio_b.unshift(rep)
      end
    end
  end
end

#mark_okObject



63
64
65
# File 'lib/nanoc/core/item_rep_selector.rb', line 63

def mark_ok
  @completed << @this
end

#nextObject



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/nanoc/core/item_rep_selector.rb', line 38

def next
  # Read prio A
  @this = @prio_a
  if @this
    @prio_a = nil
    return @this
  end

  # Read prio B
  @this = @prio_b.shift
  @this = @prio_b.shift while @seen.include?(@this) || @completed.include?(@this)
  if @this
    return @this
  end

  # Read prio C
  @this = @prio_c.pop
  @this = @prio_c.pop while @completed.include?(@this)
  if @this
    return @this
  end

  nil
end