Class: Fontisan::Variation::ParallelGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/fontisan/variation/parallel_generator.rb

Overview

Generates multiple font instances in parallel

Uses thread pool for efficient batch processing with caching. Supports progress tracking and graceful error handling per instance.

Examples:

Basic batch generation

generator = ParallelGenerator.new(font)
coordinates_list = [
  { "wght" => 300 },
  { "wght" => 700 }
]
instances = generator.generate_batch(coordinates_list)

With progress callback

generator.generate_batch(coordinates_list) do |index, total|
  puts "Generated #{index}/#{total}"
end

Custom thread count

generator = ParallelGenerator.new(font, threads: 8)

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(font, options = {}) ⇒ ParallelGenerator

Initialize parallel generator

Parameters:

Options Hash (options):

  • :cache (ThreadSafeCache)

    Cache instance (creates new if not provided)

  • :threads (Integer)

    Thread count (default: max(4, processor_count))



43
44
45
46
47
# File 'lib/fontisan/variation/parallel_generator.rb', line 43

def initialize(font, options = {})
  @font = font
  @cache = options[:cache] || ThreadSafeCache.new
  @thread_count = options[:threads] || [4, Etc.nprocessors].max
end

Instance Attribute Details

#cacheThreadSafeCache (readonly)

Returns Thread-safe cache.

Returns:



32
33
34
# File 'lib/fontisan/variation/parallel_generator.rb', line 32

def cache
  @cache
end

#fontTrueTypeFont, OpenTypeFont (readonly)

Returns Variable font.

Returns:



29
30
31
# File 'lib/fontisan/variation/parallel_generator.rb', line 29

def font
  @font
end

#thread_countInteger (readonly)

Returns Number of threads.

Returns:

  • (Integer)

    Number of threads



35
36
37
# File 'lib/fontisan/variation/parallel_generator.rb', line 35

def thread_count
  @thread_count
end

Instance Method Details

#generate_batch(coordinates_list) {|index, total| ... } ⇒ Array<Hash>

Generate multiple instances in parallel

Processes each coordinate set in parallel using thread pool. Returns results in same order as input coordinates.

Parameters:

  • coordinates_list (Array<Hash>)

    List of coordinate sets

Yields:

  • (index, total)

    Progress callback (optional)

Yield Parameters:

  • index (Integer)

    Current completed count

  • total (Integer)

    Total count

Returns:

  • (Array<Hash>)

    Generated instances with metadata



59
60
61
62
63
64
65
66
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/fontisan/variation/parallel_generator.rb', line 59

def generate_batch(coordinates_list, &progress_callback)
  return [] if coordinates_list.empty?

  total = coordinates_list.length
  results = Array.new(total)
  completed = 0
  mutex = Mutex.new

  # Create thread pool
  pool = Fontisan::Utils::ThreadPool.new(@thread_count)

  # Schedule all jobs
  futures = coordinates_list.map.with_index do |coordinates, index|
    pool.schedule do
      {
        index: index,
        result: generate_with_cache(coordinates),
      }
    end
  end

  # Collect results
  futures.each do |future|
    job_result = future.value
    results[job_result[:index]] = job_result[:result]

    # Update progress
    if progress_callback
      mutex.synchronize do
        completed += 1
        yield(completed, total)
      end
    end
  end

  # Shutdown pool
  pool.shutdown

  results
end

#generate_with_cache(coordinates) ⇒ Hash

Generate instance with caching

Uses cache to avoid regenerating identical instances.

Parameters:

  • coordinates (Hash<String, Float>)

    Design space coordinates

Returns:

  • (Hash)

    Instance data with metadata



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/fontisan/variation/parallel_generator.rb', line 106

def generate_with_cache(coordinates)
  font_checksum = calculate_font_checksum

  begin
    tables = @cache.fetch_instance(font_checksum, coordinates) do
      generator = InstanceGenerator.new(@font, coordinates)
      generator.generate
    end

    {
      success: true,
      coordinates: coordinates,
      tables: tables,
      error: nil,
    }
  rescue StandardError => e
    {
      success: false,
      coordinates: coordinates,
      tables: nil,
      error: {
        message: e.message,
        class: e.class.name,
        backtrace: e.backtrace&.first(5),
      },
    }
  end
end