cartographer/common/thread_pool.h

Overview

ThreadPool provides a simple task-based thread pool for parallel execution. Used by MapBuilder for background scan matching and optimization tasks.

Class: cartographer::common::ThreadPool

Construction

explicit ThreadPool(int num_threads);
~ThreadPool();
  • num_threads — Number of worker threads (0 = no background threads, tasks run synchronously)

Task Submission

// Submit a task with no return value
void Schedule(std::function<void()> task);

// Submit a task with return value
template <typename T>
std::future<T> Schedule(std::function<T()> task);

Synchronization

// Wait for all scheduled tasks to complete
void WaitForAllTasks();

Queries

int num_threads() const;

Usage in Cartographer

MapBuilder Integration

// In MapBuilder constructor
MapBuilder::MapBuilder(const proto::MapBuilderOptions& options)
    : options_(options),
      thread_pool_(options.num_background_threads()) {
  // ...
}

// Scheduling scan matching
thread_pool_.Schedule([this, trajectory_id, ...]() {
  // Run scan matching in background
  auto result = scan_matcher_->Match(...);
  // Post result back to main thread
  task_queue_.Push([this, result]() { ... });
});

Typical Workflow

Main Thread                          Background Threads
     |                                     |
     |--- Schedule(scan matching) -------->|
     |                                     |--- Match()
     |                                     |--- Optimize()
     |<-- Schedule(callback) --------------|
     |--- callback(result) --------------->|
     |                                     |

Task Queue

Cartographer uses a custom TaskQueue (in internal/task_queue.h) for thread-safe task passing between background threads and the main thread.

class TaskQueue {
 public:
  void Push(std::function<void()> task);
  std::function<void()> Pop();  // Blocks until task available
};

Thread Safety

  • Schedule() is thread-safe

  • WaitForAllTasks() blocks until all scheduled tasks complete

  • Tasks should not block indefinitely (use timeouts for external calls)

Configuration

From map_builder.lua:

MAP_BUILDER = {
  num_background_threads = 4,  -- Typical: num CPU cores - 1
}

Best Practices

  1. Keep tasks short — Long-running tasks block threads

  2. Avoid locks in tasks — Use task queue for main-thread communication

  3. Handle exceptions — Uncaught exceptions in tasks terminate the program

  4. Limit queue depth — Too many pending tasks = memory pressure

See Also