- if (work_queue_.try_pop(task))
- {
- task();
- }
- else
- {
- std::this_thread::yield();
- }
I am pasting the whole project here.
My threadsafe queue:
- #pragma once
- #include <memory>
- #include <mutex>
- #include <queue>
- #include <condition_variable>
- template <typename T>
- class tsqueue
- {
- mutable std::mutex mutex_;
- std::queue<std::shared_ptr<T>> queue_;
- std::condition_variable data_cond_;
- public:
- tsqueue()
- {
- }
- void push(T new_value)
- {
- std::shared_ptr<T> data(std::make_shared<T>(std::move(new_value)));
- std::lock_guard<std::mutex> lk(mutex_);
- queue_.push(data);
- data_cond_.notify_one();
- }
- std::shared_ptr<T> wait_and_pop(T& value)
- {
- std::unique_lock<std::mutex> lock_(mutex_);
- data_cond_.wait(lock_, [this] {return !queue_.empty(); });
- std::shared_ptr<T> res(std::make_shared<T>(std::move(queue_.front())));
- queue_.pop();
- return res;
- }
- bool try_pop(T& value)
- {
- std::lock_guard<std::mutex> lk(mutex_);
- if (queue_.empty())
- return false;
- value = std::move(*queue_.front());
- queue_.pop();
- return true;
- }
- std::shared_ptr<T> try_pop()
- {
- std::lock_guard<std::mutex> lk(mutex_);
- if (queue_.empty())
- {
- return std::shared_ptr<T>();
- }
- std::shared_ptr<T> res(std::make_shared<T>(std::move(queue_.front())));
- queue_.pop();
- return res;
- }
- bool empty() const
- {
- std::lock_guard<std::mutex> lk(mutex_);
- return queue_.empty();
- }
- };
My threadpool:
- #pragma once
- #include <atomic>
- #include <vector>
- #include <functional>
- #include <thread>
- #include "tsqueue.h"
- class join_threads
- {
- std::vector<std::thread>& threads_;
- public:
- explicit join_threads(std::vector<std::thread>& threads)
- : threads_(threads) {}
- ~join_threads()
- {
- for (auto& thread : threads_)
- {
- if (thread.joinable())
- {
- thread.join();
- }
- }
- }
- };
- class threadpool
- {
- std::atomic_bool done_;
- tsqueue<std::function<void()>> work_queue_;
- std::vector<std::thread> threads_;
- join_threads joiner_;
- void worker_thread()
- {
- while (!done_)
- {
- std::function<void()> task;
- if (work_queue_.try_pop(task))
- {
- task();
- }
- else
- {
- std::this_thread::yield();
- }
- }
- }
- public:
- threadpool()
- : done_(false)
- , joiner_(threads_)
- {
- unsigned const thread_count = 2;
- try
- {
- for (unsigned i = 0; i < thread_count; i++)
- {
- threads_.emplace_back(&threadpool::worker_thread, this);
- }
- }
- catch (...)
- {
- done_ = true;
- throw;
- }
- }
- ~threadpool()
- {
- done_ = true;
- }
- template<typename FunctionType>
- void submit(FunctionType f)
- {
- work_queue_.push(std::function<void()>(f));
- }
- };
My main.cpp:
- #include <chrono>
- #include <sstream>
- #include <esp_log.h>
- #include <freertos/FreeRTOS.h>
- #include <freertos/task.h>
- #include "ThreadPool.h"
- const auto sleep_time = std::chrono::seconds { 5 };
- void print_thread_info(const char *extra = nullptr)
- {
- std::stringstream ss;
- if (extra) {
- ss << extra;
- }
- ss << "Core id: " << xPortGetCoreID()
- << ", prio: " << uxTaskPriorityGet(nullptr)
- << ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes.";
- ESP_LOGI(pcTaskGetTaskName(nullptr), "%s", ss.str().c_str());
- }
- extern "C" void app_main(void)
- {
- threadpool pool;
- for (int i = 0; i < 2; i++)
- {
- pool.submit([=]
- {
- print_thread_info();
- });
- }
- while (true)
- {
- std::this_thread::sleep_for(sleep_time);
- }
- }
The error:
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:6612
load:0x40078000,len:14788
load:0x40080400,len:3792
entry 0x40080694
I (27) boot: ESP-IDF v4.4.1-dirty 2nd stage bootloader
I (27) boot: compile time 01:55:03
I (27) boot: chip revision: 1
I (30) boot_comm: chip revision: 1, min. bootloader chip revision: 0
I (37) boot.esp32: SPI Speed : 40MHz
I (42) boot.esp32: SPI Mode : DIO
I (47) boot.esp32: SPI Flash Size : 4MB
I (51) boot: Enabling RNG early entropy source...
I (57) boot: Partition Table:
I (60) boot: ## Label Usage Type ST Offset Length
I (67) boot: 0 nvs WiFi data 01 02 00009000 00006000
I (75) boot: 1 phy_init RF data 01 01 0000f000 00001000
I (82) boot: 2 factory factory app 00 00 00010000 00100000
I (90) boot: End of partition table
I (94) boot_comm: chip revision: 1, min. application chip revision: 0
I (101) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=16104h ( 90372) map
I (142) esp_image: segment 1: paddr=0002612c vaddr=3ffb0000 size=02364h ( 9060) load
I (146) esp_image: segment 2: paddr=00028498 vaddr=40080000 size=07b80h ( 31616) load
I (161) esp_image: segment 3: paddr=00030020 vaddr=400d0020 size=18e90h (102032) map
I (198) esp_image: segment 4: paddr=00048eb8 vaddr=40087b80 size=03c4ch ( 15436) load
I (205) esp_image: segment 5: paddr=0004cb0c vaddr=50000000 size=00010h ( 16) load
I (211) boot: Loaded app from partition at offset 0x10000
I (211) boot: Disabling RNG early entropy source...
I (227) cpu_start: Pro cpu up.
I (227) cpu_start: Starting app cpu, entry point is 0x400810fc
I (0) cpu_start: App cpu up.
I (241) cpu_start: Pro cpu start user code
I (241) cpu_start: cpu freq: 160000000
I (242) cpu_start: Application information:
I (246) cpu_start: Project name: ThreadPool
I (251) cpu_start: App version: 1
I (256) cpu_start: Compile time: Jan 4 2023 01:54:37
I (262) cpu_start: ELF file SHA256: a5e0f37c0d142cc5...
I (268) cpu_start: ESP-IDF: v4.4.1-dirty
I (273) heap_init: Initializing. RAM available for dynamic allocation:
I (280) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (286) heap_init: At 3FFB2DF8 len 0002D208 (180 KiB): DRAM
I (293) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (299) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (305) heap_init: At 4008B7CC len 00014834 (82 KiB): IRAM
I (313) spi_flash: detected chip: generic
I (316) spi_flash: flash io: dio
I (322) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
E (10331) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (10331) task_wdt: - IDLE (CPU 0)
E (10331) task_wdt: Tasks currently running:
E (10331) task_wdt: CPU 0: pthread
E (10331) task_wdt: CPU 1: pthread
E (10331) task_wdt: Print CPU 0 (current core) backtrace
Backtrace:0x400D7957:0x3FFB0B900x400827F9:0x3FFB0BB0 0x40084229:0x3FFB79F0 0x400873B5:0x3FFB7A10 0x400D132D:0x3FFB7A30 0x400D5A9F:0x3FFB7A50 0x400E8299:0x3FFB7AA0 0x400D90BD:0x3FFB7AC0 0x400D1300:0x3FFB7AE0 0x40087F51:0x3FFB7B00
E (10331) task_wdt: Print CPU 1 backtrace
Backtrace:0x400841BD:0x3FFB11900x400827F9:0x3FFB11B0 0x4000BFED:0x3FFB8760 0x40087271:0x3FFB8770 0x40085DD9:0x3FFB8790 0x40081058:0x3FFB87D0 0x4008108A:0x3FFB87F0 0x400D59AE:0x3FFB8810 0x400E8299:0x3FFB8860 0x400D90BD:0x3FFB8880 0x400D1300:0x3FFB88A0 0x40087F51:0x3FFB88C0
E (15331) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time:
E (15331) task_wdt: - IDLE (CPU 0)
E (15331) task_wdt: Tasks currently running:
E (15331) task_wdt: CPU 0: pthread
E (15331) task_wdt: CPU 1: pthread
E (15331) task_wdt: Print CPU 0 (current core) backtrace