Combinational Logic Simulation using QThreads

Hello! I'm trying to create program that reads in commands from an input file, and accordingly creates, connects or destroys logic gate primitives (and gates, or gates). Additionally, I'm trying to modify a previous program that I wrote to do this using QThreads, where each gate is placed in its own QThread. I'm trying to avoid using invokemethod, and I'm sure this method can work. My specific issue that I'm having trouble debugging is in my connect code block in main.cpp. Whenever I try to reference a gate specified by the input file that is NOT the true or false gate (I have one of each and they are attached to any gate that needs a true or false input), I get only a NULL reference. This includes attempting to reference the gate in my gatelist QMap. Calling gatelist.value(newCommand.at(1)) causes the program to hang, and the connect statements referencing said gate return errors about connecting a signal or slot of a NULL pointer. However, I'm not sure why my gate isn't being constructed correctly, as I haven't really changed anything beyond moving the newly constructed gate to its own thread. I'd also appreciate any critiques on style or code structure. Thanks for any comments!

Here is main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <QPointer>
#include <QMap>
#include <QDebug>
#include <QString>
#include <QFile>
#include <QTextStream>
#include "andgate.h"
#include "orgate.h"
#include "truegate.h"
#include "falsegate.h"
#include "gate.h"



int main(int argc, char * argv[])
{
QApplication* myApp =  new QApplication(argc, argv);

    //open file
    QFile file("circuit.txt");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        qDebug() << "file not found" << endl;
          return 1;
    }
    QTextStream in(&file);

    QMap<QString, gatePtrType> gatelist;
    QMap<QString, QThread*> threadlist;
    qRegisterMetaType<gatePtrType>("gatePtrType");
    gatePtrType inputTrue;
    gatePtrType inputFalse;
    falseGate False(0);
    False.init("False");
    inputFalse = &False;
    gatelist.insert(False.getName(), inputFalse);
    trueGate True(0);
    True.init("True");
    inputTrue = &True;
    gatelist.insert(True.getName(), inputTrue);

    QThread* truethread = new QThread;
    True.moveToThread(truethread);
    truethread->start();
    QThread* falsethread = new QThread;
    False.moveToThread(falsethread);
    falsethread->start();


    while(!in.atEnd()){
        QList<QString> newCommand;
        QString temp;
        newCommand.clear();
        in >> temp;
        newCommand << temp;
        if(newCommand.at(0).startsWith("CREATE", Qt::CaseInsensitive)){
            in >> temp;
            newCommand << temp;
            qDebug() << "Read in command:     CREATE     " << newCommand.at(1);
            if(newCommand.at(1).startsWith("AND", Qt::CaseInsensitive)){
                andGate newAndGate(0);
                newAndGate.init(newCommand.at(1));
                gatelist.insert(newAndGate.getName(), &newAndGate);
                QThread* newthread = new QThread;
                newAndGate.moveToThread(newthread);
                threadlist.insert(newAndGate.getName(), newthread);
                newthread->start();
                myApp->processEvents();
                qDebug() << "created gate " << newAndGate.getName();
                qDebug() << "gate created has value" << newAndGate.getGateOutput();
            }
            else if(newCommand.at(1).startsWith("OR", Qt::CaseInsensitive)){
                orGate newOrGate(0);
                newOrGate.init(newCommand.at(1));
                gatelist.insert(newOrGate.getName(), &newOrGate);
                QThread* newthread = new QThread;
                newOrGate.moveToThread(newthread);
                threadlist.insert(newOrGate.getName(), newthread);
                newthread->start();
                myApp->processEvents();
                qDebug() << "created gate " << newOrGate.getName();
            }
            else{
                qDebug() << "ERROR: Invalid Argument to command 'CREATE' ";
            }

        }
        else if(newCommand.at(0).startsWith("CONNECT", Qt::CaseInsensitive)){
            for(int i = 0; i < 2; i++){
                in >> temp;
                newCommand << temp;
            }

            qDebug() << "Read in command:     CONNECT    " << newCommand.at(1) << "    " << newCommand.at(2) << "     ";
            if(!gatelist.contains(newCommand.at(1)) || !gatelist.contains(newCommand.at(2))){
                qDebug() << "ERROR: Invalid CONNECT argument";
                return 1;
            }

//My main problem is here. Any reference to gatelist.value(newCommand.at(1))
//is a reference to a NULL pointer, and I have no idea why my gates aren't being
//created
            else{
                //gatelist.value(newCommand.at(1))->setInput(gatelist.value(newCommand.at(2)));
                //gatelist.value(newCommand.at(1))->connectToGate(gatelist.value(newCommand.at(2)));
                //qDebug() << "should be connecting here";
                qDebug() << "else statement reached";
                gatelist.value(newCommand.at(1))->setInput(gatelist.value(newCommand.at(2)));
                qDebug() << "Inputs set";
                qDebug() << "Attempting to connect" << gatelist.value(newCommand.at(1))->getName() << " to " << gatelist.value(newCommand.at(2))->getName();
                QObject::connect(gatelist.value(newCommand.at(2)), SIGNAL(outputChanged()), gatelist.value(newCommand.at(1)), SLOT(receiveInputChanged()));
                QObject::connect(gatelist.value(newCommand.at(2)), SIGNAL(destroyed()), gatelist.value(newCommand.at(1)), SLOT(inputDestroyed()));
                QObject::connect(gatelist.value(newCommand.at(2)), SIGNAL(sendGateOutput(QString,LogicLevel)), gatelist.value(newCommand.at(1)), SLOT(receiveGateOutput(QString,LogicLevel)));
                QObject::connect(gatelist.value(newCommand.at(1)), SIGNAL(getGateOutputSignal()), gatelist.value(newCommand.at(2)), SLOT(receiveOutputRequest()));
                qDebug()<<gatelist.value(newCommand.at(1))->getName() << " connected to " << gatelist.value(newCommand.at(2))->getName() << endl;
                myApp->processEvents();

            }

        }
        else if(newCommand.at(0).startsWith("DESTROY", Qt::CaseInsensitive)){
            in >> temp;
            newCommand << temp;
            qDebug() << "Read in command:     DESTROY     " << newCommand.at(1);
            delete gatelist.take(newCommand.at(1));
            delete threadlist.take(newCommand.at(1));
        }

    }

//planning to clean up by iterating through the gatelist and threadlist and deleting all entries



    myApp->processEvents();
}





My accompanying class declarations can be found here:
https://dl.dropboxusercontent.com/u/61637432/threaded_gate_logic.zip

What are the threads doing? Why do you need threads at all?
[EDIT]
What does moveToThread() do?

Ok, I read a bit about that subject.
You need signal/slots for the processing and the end of the thread object.
[\EDIT]
Last edited on
So, the idea is that I need to have the gates within their own threads solely as a learning exercise. With regards to the processing and end of the thread object, I was hoping to avoid worrying about that and simply deleting the gates AND threads (gates first) via pointers from outside the thread. If I can't simply delete a thread and wait for it to finish, maybe I could attach isFinished() of each thread to its own deleteLater() slot.

Maybe I'm misunderstanding what you mean by the processing of the thread object. Assuming I can figure out why my pointers to gates I've moved to threads are turning up NULL, what other slots/signals do I need?
Assuming you insist to use QThread for this program, you'will get useful answers if you post on Qt forums, I don't think many people around here uses Qt on a regular basis.
Ah ok, I'll do that, thanks.
Looks to me like you have a scope problem. You create objects on the stack within if/else blocks. Try creating them on the heap.
Oh wow, you're right. And now I feel silly. Thanks a ton to everyone!
Topic archived. No new replies allowed.