Skip to content

Examples Multithread

Eduard Mishkurov edited this page May 13, 2026 · 7 revisions

Multithread example

Multithread

This example shows how logme can be used from multiple threads.

What it demonstrates

  • Creating a dedicated channel per worker thread
  • Using LogmeThreadChannel(...) to route channel-less logs
  • Logging with ChannelPtr in a multi-threaded program
  • A simple throughput-style loop

Notes

  • ChannelPtr avoids channel lookup and is usually preferable on hot paths.
  • A per-thread default channel is convenient when library code does not receive a channel explicitly.

Console output

2026-05-13 10:54:24:230   Worker(): worker=0 msg=0
2026-05-13 10:54:24:230   Worker(): worker=0 msg=1
2026-05-13 10:54:24:230   Worker(): worker=0 msg=2
2026-05-13 10:54:24:230   Worker(): worker=0 msg=3
2026-05-13 10:54:24:230   Worker(): worker=0 msg=4
2026-05-13 10:54:24:230   Worker(): worker=0 msg=5
2026-05-13 10:54:24:230   Worker(): worker=0 msg=6
2026-05-13 10:54:24:230   Worker(): worker=0 msg=7
2026-05-13 10:54:24:230   Worker(): worker=0 msg=8
2026-05-13 10:54:24:230   Worker(): worker=0 msg=9
2026-05-13 10:54:24:230   Worker(): worker=0 msg=10
2026-05-13 10:54:24:230   Worker(): worker=0 msg=11
2026-05-13 10:54:24:230   Worker(): worker=0 msg=12
2026-05-13 10:54:24:230   Worker(): worker=0 msg=13
2026-05-13 10:54:24:230   Worker(): worker=0 msg=14
2026-05-13 10:54:24:230   Worker(): worker=0 msg=15
2026-05-13 10:54:24:230   Worker(): worker=0 msg=16
2026-05-13 10:54:24:230   Worker(): worker=0 msg=17
2026-05-13 10:54:24:230   Worker(): worker=0 msg=18
2026-05-13 10:54:24:230   Worker(): worker=0 msg=19
2026-05-13 10:54:24:230   Worker(): worker=0 msg=20
2026-05-13 10:54:24:230   Worker(): worker=0 msg=21
2026-05-13 10:54:24:230   Worker(): worker=0 msg=22
2026-05-13 10:54:24:230   Worker(): worker=0 msg=23
2026-05-13 10:54:24:230   Worker(): worker=0 msg=24
2026-05-13 10:54:24:230   Worker(): worker=0 msg=25
2026-05-13 10:54:24:230   Worker(): worker=0 msg=26
2026-05-13 10:54:24:230   Worker(): worker=0 msg=27
2026-05-13 10:54:24:230   Worker(): worker=0 msg=28
2026-05-13 10:54:24:230   Worker(): worker=0 msg=29
... output truncated, 3971 lines omitted ...

Source code

Sources

Repository folder: examples/Multithread

Multithread.cpp

Open in repository

#include <Logme/Logme.h>

#include <atomic>
#include <chrono>
#include <thread>
#include <vector>

#if defined(_MSC_VER)
#pragma warning(disable: 4840)
#endif

static void Worker(Logme::ChannelPtr ch, int workerId, int messages, std::atomic<int>& counter)
{
  // Set default thread channel so channel-less logs in this thread go to 'ch'.
  LogmeThreadChannel(ch->GetID());

  for (int i = 0; i < messages; i++)
  {
    // ChannelPtr is slightly faster than ID in multithreaded systems.
    LogmeI(ch, "worker=%d msg=%d", workerId, i);

    // This call does not specify a channel, but will still go to 'ch' because of LogmeThreadChannel above.
    LogmeD("worker=%d (default thread channel)", workerId);

    counter.fetch_add(1, std::memory_order_relaxed);
  }
}

int main()
{
  const int threads = 4;
  const int messagesPerThread = 1000;

  std::atomic<int> counter{0};

  auto t0 = std::chrono::steady_clock::now();

  std::vector<std::thread> workers;
  workers.reserve(threads);

  for (int i = 0; i < threads; i++)
  {
    // Create a dedicated channel for each thread.
    // Using separate channels reduces contention because no name lookup is required.
    auto ch = Logme::Instance->CreateChannel();
    ch->AddLink(::CH);

    workers.emplace_back(Worker, ch, i, messagesPerThread, std::ref(counter));
  }

  for (auto& t : workers)
  {
    t.join();
  }

  auto t1 = std::chrono::steady_clock::now();
  auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count();

  LogmeI("threads=%d messages=%d time_ms=%lld",
    threads,
    counter.load(std::memory_order_relaxed),
    (long long)ms
  );

  return 0;
}

Previous: FormatApi | Next: OnceEvery

Clone this wiki locally