jeudi 26 octobre 2023

c++, how can i delete one element of map whin the element itself

i have two classes in differnt source file, class A in a.hpp and a.cpp, class B in b.hpp and b.cpp, A is a singleton class, it create B object, and store b in a map, when B object created, it create a thread, and i want b can remove itself from that map which is A's member when the thread run out, but my program throw a exception.

// main.cpp

#include <iostream>
#include "a.hpp"

int main() {
    A::get_instance().add(1);
    int pause = 0; std::cin >> pause;
    return 0;
}
// a.hpp

#ifndef __A_HPP__
#define __A_HPP__

#include <unordered_map>
#include <memory>
#include "b.hpp"

class A {
public:
    void add(int i);
    void remove(int i);
    static A& get_instance();
private:
    std::unordered_map<int, std::shared_ptr<B>> map_b_;
};


#endif
// a.cpp

#include "a.hpp"

void A::add(int i) {
    std::cout << "add: " << i << std::endl;
    map_b_[i] = std::move(std::make_shared<B>(i));
    std::this_thread::sleep_for(3s);
}
void A::remove(int i) {
    std::cout << "remove: " << i << std::endl;
    if (map_b_.count(i)) {
        map_b_.erase(i);
    }
}
A& A::get_instance() {
    static A instance;
    return instance;
}
// b.hpp

#ifndef __B_HPP__
#define __B_HPP__

#include <thread>
#include <chrono>
#include <atomic>
#include <iostream>
using namespace std::chrono_literals;

class B {
public:
    B(int id);
    ~B();
    void stop();
    void run();
private:
    std::atomic<bool> run_flag_;
    std::thread thr_;
    int id_;
};


#endif
b.cpp

#include "b.hpp"
#include "a.hpp"

B::B(int id) {
    id_ = id;
    run_flag_ = true;
    std::thread t(&B::run, this);
    thr_ = std::move(t);
}
B::~B() {
        std::cout << "~B(): " << id_ << std::endl;
    stop();
}
void B::stop() {
    run_flag_ = false;
    if (thr_.joinable()) {
        thr_.join();
    }
}
void B::run() {
    int count = 0;
    while (count < 3 && run_flag_) {
        std::cout << "processing id: " << id_ << std::endl;
        std::this_thread::sleep_for(1s);
        count ++;
    }
    A::get_instance().remove(id_);
}
# CMakeLists.txt
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)

# 项目信息
project (demo)
SET(CMAKE_BUILD_TYPE "Debug")
# 指定生成目标
add_executable(
    ${PROJECT_NAME} 
    main.cpp
    a.cpp
    b.cpp
)
find_package(Threads REQUIRED) 
target_link_libraries(${PROJECT_NAME} Threads::Threads)

i have run the code in my linux docker, but it throw an error, like this, i want know how can i do it to remove one itself from container.

root@53d8817a43a8:~/test-cpp/build# ./demo
add: 1
processing id: 1
processing id: 1
processing id: 1
remove: 1
~B(): 1
terminate called after throwing an instance of 'std::system_error'
  what():  Resource deadlock avoided
Aborted

Aucun commentaire:

Enregistrer un commentaire