jeudi 21 mars 2019

queue of different class objects

I need to create a queue of different class objects (These classes are not related). I found a solution as follows:

Create a base class and use polymorphism. Here is how I implemented it,

class Task {
    public:
    virtual void operator()() {
        printf("should not be called\n");    
    } 
};

class TaskRPCB : public Task {
    private:
        int x;
        // other varibles
        std::function<void(int)> func;
    public:
        TaskRPCB(std::function<void(int)>&f , int x) {
            this->func = f;
            this->x = x;
        }
        void operator()() {
            printf("TaskRPCB function is executing...\n");
            func(x);
        }
};

class TaskECB : public Task {
    private:
        // other varibles
        std::function<void(void)> func;
    public:
        TaskECB(std::function<void(void)>&f) : func(f) {}
        void operator()() {
            printf("TaskECB function is executing...\n");
            func();
        }
};

void F1() { // dummy function for example
    cout <<"no x"<<endl;
}
void F2(int x) { // dummy function for example
    cout <<"x : "<<x<<endl;
}

int main() {

    queue<unique_ptr<Task>> Q;

    function<void()>    func1   = F1;
    function<void(int)> func2   = F2;

    TaskECB task1(func1);
    TaskRPCB task2(func2,4);


    Q.emplace(new TaskECB(func1));
    Q.emplace(new TaskRPCB(func2,4));

    (*Q.front())();
    Q.pop();

    (*Q.front())();
    Q.pop();

}

The problem is, I can not push the objects directly as shown above. I have to create an object of an inherited class and pass it to another function to do the push action. It is because ( in my case ) the queue is a part of a thread-safe queue and it has separate Push() method.

template<typename T>
void threadSafeQueue<T>::Push(T newData) { /* TODO: size check before pushing */
    std::shared_ptr<T> data(std::make_shared<T>(std::move(newData)));
                                           /* construct the object before lock*/
    std::lock_guard<std::mutex> lk(mut);
    taskQueue.push(data);
    dataCond.notify_one();
}

Earlier I did not have multiple tasks to execute ( or push ) into the queue, therefore threadSafeQueue<TaskRPCB> workQ declaration worked fine for me.

Creating a base Task class like above is not working because of object slicing

Can you suggest other ways to store objects in the queue ( so that I can still use the lock guarded Push() method )

Thanks !

Aucun commentaire:

Enregistrer un commentaire