Home > Software design >  Why I can not create a thread with class object as parameter
Why I can not create a thread with class object as parameter

Time:10-24

I tried to implement a multithreading cache in C 11. I tried to create threads in the main function and passed the putcache function and getcache function as parameter. And I passed class object c1 to the two functions as parameters. However, I found that the complier gave me a error like this: In template: no matching constructor for initialization of '_Gp' (aka 'tuple<unique_ptr<std::__thread_struct>, void (*)(LRUCache), LRUCache>') Here is my code:

#include <iostream>
#include <unordered_map>
#include <thread>
#include <chrono>
#include <mutex>
using namespace std;
class LRUCache {
public:
    class Node {
    public:
        int key,val;
        Node* left,*right;
        Node(int _key,int _val):key(_key),val(_val),left(NULL),right(NULL) {}
    }*L,*R;
    unordered_map<int,Node*> m;
    int n;
    mutex mtx;
    condition_variable cv;
    void insert(Node* node)
    {
        Node* next=L->right;
        L->right=node;
        node->right=next;
        node->left=L;
        next->left=node;
    }
    void erase(Node* node) {
        node->left->right=node->right;
        node->right->left=node->left;
    }
    LRUCache(int capacity) {
        n=capacity;
        L=new Node(-1,-1),R=new Node(-1,-1);
        L->right=R;
        R->left=L;
    }

    int get(int key) {
        if(m.count(key)==0) return -1;
        mtx.lock();
        Node* node=m[key];
        erase(node);
        insert(node);
        return node->val;
        mtx.unlock();
    }

    void put(int key, int value) {
        mtx.lock();
        if(m.count(key)) {
            m[key]->val=value;
            erase(m[key]);
            insert(m[key]);
        } else {
            Node* node=new Node(key,value);
            if(m.size()==n) {
                Node* tmp=R->left;
                erase(tmp);
                m.erase(tmp->key);
            }
            insert(node);
            m[key]=node;
        }
        mtx.unlock();
    }
};
void putcache(LRUCache c) {
    for(int i=1;i<=10;i  ) {
        c.put(i,i 10);
        this_thread::sleep_for(std::chrono::seconds(1));
    }
}
void getcache(LRUCache c) {
    for(int i=1;i<=10;i  ) {
        c.get(i);
        this_thread::sleep_for(std::chrono::seconds(1));
    }
}

int main() {
    LRUCache c1(100);
    std::thread t1(putcache,c1);
    std::thread t2(getcache,c1);
}

CodePudding user response:

As @Nelfeal said:

LRUCache contains two non-copyable members (mutex and condition variable) so its copy constructor is deleted.

You could not copy LRUCache, by passing the c1 to the thread, you're copying it. Take a reference instead:

void putcache(LRUCache& c);
void getcache(LRUCache& c);


LRUCache c1(100);
std::thread t1(putcache, std::ref(c1));
std::thread t2(getcache, std::ref(c1));

And I think making the thread a class member would better fit your needs:

class LRUCache 
{
    void getcache();
    void putcache();
}

LRUCache c1(100);
std::thread t1(&LRUCache::putcache, &c1);
std::thread t2(&LRUCache::getcache, &c1);

CodePudding user response:

std::thread makes a copy of its parameters to ensure they live long enough for the new thread to start up. Also your putcache and getcache functions accept their parameters by value. Your LRUCache class doesn't have a valid copy constructor though, so neither of those things can work.

If you want to pass a reference to c1 to both threads, then you'll need to wrap the parameters in a std::reference_wrapper and make your putcache and getcache functions accept their parameters by value:

void putcache(LRUCache& c) { // <-------- NOTE: added &
    for(int i=1;i<=10;i  ) {
        c.put(i,i 10);
        this_thread::sleep_for(std::chrono::seconds(1));
    }
}
void getcache(LRUCache& c) { // <-------- NOTE: added &
    for(int i=1;i<=10;i  ) {
        c.get(i);
        this_thread::sleep_for(std::chrono::seconds(1));
    }
}

int main() {
    LRUCache c1(100);
    std::thread t1(putcache, std::ref(c1)); // <-------- NOTE: added std::ref
    std::thread t2(getcache, std::ref(c1)); // <-------- NOTE: added std::ref
    t1.join();
    t2.join();
}

Keep in mind that it's up to you to ensure that c1 stays alive for the entire duration of your two threads. In this case, I've joined the two threads in main to ensure it doesn't end before they're finished.

  • Related