aboutsummaryrefslogtreecommitdiff
path: root/sandbox/multithreading-tests/stress-test/thread.h
blob: 44cbf7c8b22518367898f11cc0a2b847c2951cbf (plain)
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
#ifndef STRESS_H
#define STRESS_H

#include <contextproperty.h>

#include <time.h>
#include <QThread>
#include <QDebug>

#define NUM_TESTS 9

/*
 * A thread doing something with a ContextProperty.
 *
 * First creates  a ContextProperty tracking \c propertyName, then does some simple thing 
 * with it based on the \c task number, then  finally the ContextProperty is deleted.
 */
class Thread : public QThread
{
    Q_OBJECT

public:
    Thread(const int task, const QString& propertyName) : task(task), propertyName(propertyName) {};

protected:
    void run() {
        // create property do something and delete it
        ContextProperty* cp = new ContextProperty(propertyName);
        int value, realValue;

        switch (task) {
            case 1: // check value
            cp->waitForSubscription();
            value =  cp->value().toInt();
            realValue = time(0);
            if (value != realValue && value != 0) {
                msleep(100); // give it 0.1 sec to arrive
                value =  cp->value().toInt();
                if (value != realValue && value != 0) 
                    qDebug() << "*** value mismatch:" << propertyName << value << realValue;
            }
            break;

            case 2: // wait 0-2000 msec before deleting
            msleep(qrand()%2000);
            break;

            case 3: // unsubscribe
            cp->unsubscribe();
            break;

            case 4: // unsubscribe and wait a bit
            cp->unsubscribe();
            msleep(qrand()%2000);
            break;

            case 5: // unsubscribe and subscribe
            cp->unsubscribe();
            cp->subscribe();
            break;

            case 6: // unsubscribe, wait a bit then subscribe and wait some more
            cp->unsubscribe();
            msleep(qrand()%2000);
            cp->subscribe();
            msleep(qrand()%2000);
            break;

            case 7: // subscribe
            cp->subscribe();
            break;

            case 8: // subscribe
            msleep(qrand()%100);
            cp->subscribe();
            msleep(qrand()%100);
            break;

            default:; // just create and delete
        }

        delete(cp);
        exit();
    }

private:
    int task;
    QString propertyName;

};


/*
 * Starts \c maxThreads number of threads doing simple tests wit ContextProperty \c propertyName
 * until stopped. The tasks are choosen randomly with equal weight. Whenever a thread stops
 * an other one will start, ad infinitum.
 */
class TestRunner : public QObject
{
    Q_OBJECT

private:
   int maxThreads;
   QSet<Thread*> threads;
   QString propertyName;
   int count;
   int defaultTask;

public:
    TestRunner(const int maxThreads, const QString& propertyName, int task = -1) :
        maxThreads(maxThreads), propertyName(propertyName), count(0), defaultTask(task) {
        for (int i = 0; i < maxThreads; i++)
            addThread();
    }

    void addThread() {
        int task = defaultTask != -1 ? defaultTask : qrand() % NUM_TESTS ;
        qDebug() << "** starting" << propertyName << task << "/" << ++count;
        Thread* t = new Thread(task, propertyName);
        QObject::connect(t, SIGNAL(finished()), this, SLOT(onThreadFinished()));
        threads.insert(t);
        t->start();
    }

public slots:
    void onThreadFinished() {
        Thread* t = (Thread*) QObject::sender();
        if (threads.remove(t)) {
            delete t;
            addThread();
        }
    }
};

#endif