Multithreading having terrible times on linux.

Hello everyone!

I managed to get this mutlithread working on windows just fine.
I'm not sure how well is my code but in linux however...
I can only create thread and thats all.
Can't pause it.
Code:
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
#pragma once
#ifndef SPARKLYTHREAD_H
#define SPARKLYTHREAD_H
#include <SparklyCore.h>

// thread for windows
#if defined SPwindows
#define spThreadBegin DWORD WINAPI
#define spThreadHandle HANDLE
#define spThreadEnd return 1
typedef DWORD (WINAPI *spThreadFunction)( LPVOID lpThreadParameter );

class spThread
{
	public:
		HANDLE id;
		bool visrunning;

		spThread(spThreadFunction func, void *data)
		{
			id = CreateThread(0,0, func, data, CREATE_SUSPENDED,0);
			visrunning = 0;
		}

		void start()
		{
			if(!id) return;
			ResumeThread(id);
			visrunning = 1;
		}

		void destroy()
		{
			if(!id) return;
			TerminateThread( id, 0 );
			visrunning = 0;
			CloseHandle(id);
		}

		void pause()
		{
			if(!id) return;
			SuspendThread(id);
			visrunning = 0;
		}

		bool exists()
		{
			if(!id ) return false;
			DWORD result = WaitForSingleObject( id, 0);
			if (result == WAIT_OBJECT_0) return false;
			return true;
		}

		bool isrunning()
		{
			if(!id ) return false;
			if(!visrunning ) return false;
			if( !exists() ) return false;
			return true;
		}

		void waituntildone()
		{
			if(!isrunning()) return;
			WaitForSingleObject(id, INFINITE);
		}

		void waintuntildonemutli( int count, spThread **in )
		{
			HANDLE *p = new HANDLE[count];
			for( int a = 0; a < count; a++ ) p[a] = in[a]->id;
			WaitForMultipleObjects( count, p, true, INFINITE);
		}

		void waituntildone( unsigned int time )
		{
			if(!isrunning()) return;
			WaitForSingleObject(id, time);
		}

		void waintuntildonemutli( int count, spThread **in, unsigned int time )
		{
			HANDLE *p = new HANDLE[count];
			for( int a = 0; a < count; a++ ) p[a] = in[a]->id;
			WaitForMultipleObjects( count, p, true, time);
		}

		void SetPriorityLevel( int level )
		{
			if(!id ) return;
		}

		int GetPriorityLevel( char level )
		{
			if(!id ) return 0;
			return GetThreadPriority( id );
		}

		~spThread()
		{
			if( exists() ) destroy();
			if(id) CloseHandle(id);
		}
};
#endif

// thread for linux
#if defined SPlinux
#include <pthread.h>

#define spThreadBegin void *
#define spThreadHandle pthread_t
#define spThreadEnd pthread_exit(0)
typedef void *( *spThreadFunction)( void *lpThreadParameter );

class spThread
{
	public:
		spThreadHandle id;
		bool visrunning;
		pthread_mutex_t m_SuspendMutex;
		pthread_cond_t m_ResumeCond;

		spThread(spThreadFunction func, void *data)
		{
			pthread_create(&id,0, func, data);
		}

		void start()
		{
			pthread_mutex_lock(&m_SuspendMutex);
			visrunning = true;
			pthread_cond_signal(&m_ResumeCond);
			pthread_mutex_unlock(&m_SuspendMutex);
		}

		void destroy()
		{
		}

		void pause()
		{
			pthread_mutex_lock(&m_SuspendMutex);
			pthread_join(id, NULL);
			visrunning = false;
			do 
			{
				pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
			} 
			while (!visrunning); 
			pthread_mutex_unlock(&m_SuspendMutex);
		}

		bool exists()
		{
		}

		bool isrunning()
		{
		}

		void waituntildone()
		{
		}

		void waintuntildonemutli( int count, spThread **in )
		{
		}

		void waituntildone( unsigned int time )
		{
		}

		void waintuntildonemutli( int count, spThread **in, unsigned int time )
		{
		}

		void SetPriorityLevel( int level )
		{
		}

		int GetPriorityLevel( char level )
		{
		}

		~spThread()
		{
		}
};
#endif
#endif 


I heard that there are libraries for linux what support pause and resume
yet I'm searching very fundamental ways to do it so i would not have problems
running my code in different types of linux ( 64/32 bit, Ubuntu/Debian etc.. )

Multithreading should be the one fundamental thing like for example
stdio.h

Senior linux coders, can you please tell me how do you do these things?
I need:
*create/*start/*pause thread,
*change priority level of thread.
*check if thread have done its doings ( is thread still alive/running ).
*destroy thread so it will be deleted and can't be resumed or do something else with it.
*wait until thread is done:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void *threadfunc(void *data) {
sleep(10);
cout << "hello world!" << endl;

}

int main() {
pthread_t a;
long index = 0;
pthread_create(&a, 0, threadfunc, (void *)infex);

waituntilthreaddone(&a);
cout << "will printed after hello world" << endl; 
return 0
}

Thank you!
Multithreading should be the one fundamental thing like for example
stdio.h


They are. See <thread>.

Multithreading has been standardized and part of the standard library for 4 years now.

I did an example where I created a thread pool that you can use:

http://www.cplusplus.com/forum/general/159379/#msg813869

It illustrates how to do all those things you mentioned.
Now i have even more freedom than in windows multithreading.
Thanks!

Anyways still.
What went wrong with my code:
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
#include <pthread.h>

#define spThreadBegin void *
#define spThreadHandle pthread_t
#define spThreadEnd pthread_exit(0)
typedef void *( *spThreadFunction)( void *lpThreadParameter );

class spThread
{
	public:
		spThreadHandle id;
		bool visrunning;
		pthread_mutex_t m_SuspendMutex;
		pthread_cond_t m_ResumeCond;

		spThread(spThreadFunction func, void *data)
		{
			pthread_create(&id,0, func, data);
		}

		void start()
		{
			pthread_mutex_lock(&m_SuspendMutex);
			visrunning = true;
			pthread_cond_signal(&m_ResumeCond);
			pthread_mutex_unlock(&m_SuspendMutex);
		}

		void pause()
		{
			pthread_mutex_lock(&m_SuspendMutex);
			pthread_join(id, NULL);
			visrunning = false;
			do 
			{
				pthread_cond_wait(&m_ResumeCond, &m_SuspendMutex);
			} 
			while (!visrunning); 
			pthread_mutex_unlock(&m_SuspendMutex);
		}

};

The question is not why my pause function doesn't work.
My code just doesn't make any sense.

when im starting the thread in main() and then pausing it in main()
it wont pause my started thread, it will pause the main()'s thread.

The question is however, how to make the code so, it would make sense?
So i could pause my thread on main().

PS: one reason why i dont like my current pause system is that it uses loop to freeze
the thread instead of pausing.
It will stop doing what thread wanted yet it will still use cpu.
However, i remember that there was function something called nanosleep, i think.
I can play with those sleep functions.
or perhaps there is another way.


'pause' is a bit of a misnomer and is throwing me off.

You can't pause an existing thread. A thread can be:

1) Running code
2) Waiting for a shared resource (like waiting for a mutex to lock)
3) Done/Joined. Note that once a thread joins it is effectively terminated and you can't use it any more (you'd have to create a new thread).

If you have a thread that is running code, there is no way to interrupt that thread from another thread and make it wait. To my knowledge it simply can't be done.

So what exactly is your 'pause' function hoping to accomplish?
My pause idea was like this code here:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void *threadfunc(void *data) {
cout << "tpiip1" << endl;
for( new a  = 0; a < 9000; a++ ) // just a random loop to show that thread is busy
{
    // some code here...
}
cout << "tpiip2" << endl;
}

int main() {
pthread_t a;
long index = 0;
pthread_create(&a, 0, threadfunc, (void *)infex);
cout << "piip1" << endl;
pausethread(&a); // pausing thread
cout << "piip2" << endl;
sleep(100);
cout << "piip3" << endl;
resumethread(&a) // thread is running again 
sleep(100);
cout << "piip4" << endl;
return 0


and results should be:
tpiip1
piip1
piip2
piip3
tpiip2
piip4

That was my idea and now i understand that it can not be done that how i first planned.
Well, at least in your code it seems possible:
http://www.cplusplus.com/forum/general/159379/#msg813869

However there are few puzzles for me what i won't be getting probably right.
What i want is that my mutlithreading functions, i created, work exactly same on linux and windows but 'change priority level of thread' on windows works weird way so
i think i now must find the fundamental level of threading on windows ( if that exists. )
to force that priority level system work the same way on both platforms.






_beginthread / _beginthreadex may be what you want in windows.
That was my idea and now i understand that it can not be done that how i first planned.
Well, at least in your code it seems possible:


Yeah I'm not sure how being able to pause a thread would be of value. If you want a thread A to wait for thread B to finish something before continuing, then use a condition variable. That's what they're for.


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
typedef std::mutex              mutex;
typedef std::unique_lock<mutex> lock;


mutex                           mx;
std::condition_variable         cv;
bool                            continueThreadB = false;

void threadb()
{
    cout << "tpiip1" << endl;
    
    // ...
    
    // wait for thread A to tell us to continue
    {
        lock lk(mx);
        
        cv.wait(lk, []{ return continueThreadB; }       // wait for continueThreadB to be true
    }
    
    cout << "tpiip2" << endl;
}


int main()
{
    std::thread b(threadb);
    
    //...
    
    // tell threadB it can resume
    {
        lock lk(mx);
        continueThreadB = true;
    }
    cv.notify_all();
    
    
    //...
    
    b.join();
}





The key difference here is that the thread will have to actively poll the condition var to know if it should pause itself or not.
Topic archived. No new replies allowed.