How to deal with racing threads (C++; TinyThread++)? - c++

Here is a sample of the main code ("Library/stack.h" doesn't really matter, but in any case, it is the last source included in this previous question of mine):
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include <tinythread.h>
#include "Library/stack.h"
using namespace std;
using namespace tthread;
#define BOULDERspd 100
// ========================================================================= //
struct Coord {
int x, y;
};
int randOneIn (float n) {
return ((int) (n * (rand() / (RAND_MAX + 1.0))));
}
int randOneIn (int n) {
return ((int) ((float) n * (rand() / (RAND_MAX + 1.0))));
}
// ========================================================================= //
#include <windows.h>
void gotoxy (int column, int line) {
if ((column >= 0) && (line >= 0)) {
COORD coord;
coord.X = column;
coord.Y = line;
SetConsoleCursorPosition(
GetStdHandle( STD_OUTPUT_HANDLE ),
coord
);
}
}
void gotoxy (Coord pos) {
gotoxy(pos.x, pos.y);
}
// ========================================================================= //
void render (char image, Coord pos) {
gotoxy(pos);
cout << image;
}
void unrender (Coord pos) {
gotoxy(pos);
cout << ' ';
}
// ========================================================================= //
char randimage (void) {
return (rand() % 132) + 123;
}
mutex xylock;
class Boulder {
char avatar;
Coord pos;
public:
Boulder (int inix) {
pos.x = inix;
pos.y = 0;
avatar = randimage();
};
void fall (void) {
unrender(pos);
pos.y++;
render(avatar, pos);
Sleep(BOULDERspd);
};
void live (void) {
do {
fall();
} while (y() < 20);
die();
};
void die (void) {
unrender(pos);
pos.y = 0;
};
int x (void) { return pos.x; };
int y (void) { return pos.y; };
};
// ========================================================================= //
class thrStack: public Stack<thread*> {
public:
thrStack (): Stack<thread*> () { };
void pushNrun (thread* elem) {
push(elem);
top->core->joinable();
}
};
void randBoulder (void* arg) {
srand(time(NULL));
Boulder boulder(rand() % 40);
boulder.live();
}
void Boulders (void* arg) {
srand(time(NULL));
thrStack stack;
do {
stack.pushNrun(new thread (randBoulder, 0));
Sleep(rand() % 300);
} while(1);
}
// ========================================================================= //
// ========================================================================= //
int main() {
thread raining (Boulders, 0);
raining.join();
}
I'm new to multi-threading so, to fiddle around with it, I'm trying to make a program that makes random characters constantly fall from the top of the screen, as if it were raining ASCII symbols.
I've noticed, however, a little (big) error in my coding:
bool xylock = false;
class Boulder {
char avatar;
Coord pos;
public:
Boulder (int inix) {
pos.x = inix;
pos.y = 0;
avatar = randimage();
};
void fall (void) {
unrender(pos);
pos.y++;
render(avatar, pos);
Sleep(BOULDERspd);
};
void live (void) {
do {
fall();
} while (y() < 20);
die();
};
void die (void) {
unrender(pos);
pos.y = 0;
};
int x (void) { return pos.x; };
int y (void) { return pos.y; };
};
Because the fall() function uses gotoxy, which changes the 'global cursor', multiple calls to gotoxy would mess up the intended execution of the program. If you try to compile the code as-is, you'd get falling letters that constantly switch position and leave garbage of themselves behind.
Is there any way to use or implement a lock for this and future situations alike with just TinyThread? What is the logic of locks implementing in C++, in general?
EDIT: Modified fall(); is it okay, Caribou?
void fall (void) {
lock_guard<mutex> guard(xylock);
unrender(pos);
pos.y++;
render(avatar, pos);
xylock.unlock();
Sleep(BOULDERspd);
};

You can use the tinythread lib:
http://tinythreadpp.bitsnbites.eu/doc/
Look specifically at lock_guard and mutex
multiple calls to gotoxy would mess up the intended execution of the
program. If you try to compile the code as-is, you'd get falling
letters that constantly switch position and leave garbage of
themselves behind.
create a mutex object to synchronise on, and then in the function you want to be thread safe you create a local lock_guard using it. This mutex can be used in multiple places as well using the lock_guard.

Here I created a very basic threading example without a framework or classes. As you can see, threading and syncronisation isn't C++ work, it's OS work! ;-)
Here I created a simple threadfunction, which I call two times. The threads writing the same variable, but can't do that the same time, so have to protect it. In this sample I use a CRITICAL_SECTION object to lock the variable by one thread. If the one thread lock it, the other can't access it and have to wait until it's free.
Have a closer look and see, I also protected the printf operations. What would happen if you don't do this? You will get a very funny outprint! Find out why and you know how threads and locks work. :-)
#include <windows.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#include <process.h>
//a global variable (just do do someting):
int g_ThreadCounter = 0;
//global variable to end the threads:
bool g_Run = true;
//do not use global variables, there are better solutions! I just did it here to
//keep it simple and focus on the issue!
//a critical section object - something like a "soft-version" of a mutex to synchronize
//write access on variables
CRITICAL_SECTION critical;
//a thread function
unsigned __stdcall threadFunc(void *pThreadNum)
{
unsigned int iThreadNum = reinterpret_cast<unsigned int>(pThreadNum);
do{
//you need the critical section only when you change values:
EnterCriticalSection(&critical);
g_ThreadCounter++;
printf("from thread: ");
printf("%d", iThreadNum);
printf(" counter = ");
printf("%d", g_ThreadCounter);
printf("\n");
LeaveCriticalSection(&critical);
//sleep a secound
Sleep (1000);
}while(g_Run);
_endthreadex(0);
return 0;
}
int main()
{
unsigned int ThreadID1 = 1;
unsigned int ThreadID2 = 2;
//initialize the critical section with spin count (can be very effective in case
//of short operation times, see msdn for more information)
if(!InitializeCriticalSectionAndSpinCount(&critical, 1000))
{
//DO NOT START THE THREADS, YOU DON'T HAVE SYNCHRONISATION!!!
printf("someting went wrong, press any key to exit");
//do some error handling
getchar();
exit(-1);
}
//start the threads
HANDLE thHandle1 = (HANDLE)_beginthreadex(NULL, 0, &threadFunc, (void*) ThreadID1, 0, NULL);
HANDLE thHandle2 = (HANDLE)_beginthreadex(NULL, 0, &threadFunc, (void*) ThreadID2, 0, NULL);
if(thHandle1 == INVALID_HANDLE_VALUE || thHandle2 == INVALID_HANDLE_VALUE)
{
printf("something went wrong, press any key to exit");
//do some error handling
getchar();
exit(-1);
}
//the main thread sleeps while the other threads are working
Sleep(5000);
//set the stop variable
EnterCriticalSection(&critical);
g_Run = false;
LeaveCriticalSection(&critical);
//wait for the thread; infinite means, you wait as long as the
//thread takes to finish
WaitForSingleObject(thHandle1, INFINITE);
CloseHandle(thHandle1);
WaitForSingleObject(thHandle2, INFINITE);
CloseHandle(thHandle2);
DeleteCriticalSection(&critical);
printf("press any key to exit");
getchar();
return 0;
}
Study the OS on which you are working! It's sometimes better than pay too much attention on Frameworks and foreign classes. This can solve a lot of questions!

Related

Atomically incrementing an integer in shared memory for multiple processes on linux x86-64 with gcc

The Question
What's a good way to increment a counter and signal once that counter reaches a given value (i.e., signaling a function waiting on blocks until full, below)? It's a lot like asking for a semaphore. The involved processes are communicating via shared memory (/dev/shm), and I'm currently trying to avoid using a library (like Boost).
Initial Solution
Declare a struct that contains a SignalingIncrementingCounter. This struct is allocated in shared memory, and a single process sets up the shared memory with this struct before the other processes begin. The SignalingIncrementingCounter contains the following three fields:
A plain old int to represent the counter's value.
Note: Due to the MESI caching protocol, we are guaranteed that if one cpu core modifies the value, that the updated value will be reflected in other caches once the value is read from those other caches.
A pthread mutex to guard the reading and incrementing of the integer counter
A pthread condition variable to signal when the integer has reached a desirable value
Other Solutions
Instead of using an int, I also tried using std::atomic<int>. I've tried just defining this field as a member of the SignalingIncrementingCounter class, and I've also tried allocating it into the struct at run time with placement new. It seems that neither worked better than the int.
The following should work.
The Implementation
I include most of the code, but I leave out parts of it for the sake of brevity.
signaling_incrementing_counter.h
#include <atomic>
struct SignalingIncrementingCounter {
public:
void init(const int upper_limit_);
void reset_to_empty();
void increment(); // only valid when counting up
void block_until_full(const char * comment = {""});
private:
int upper_limit;
volatile int value;
pthread_mutex_t mutex;
pthread_cond_t cv;
};
signaling_incrementing_counter.cpp
#include <pthread.h>
#include <stdexcept>
#include "signaling_incrementing_counter.h"
void SignalingIncrementingCounter::init(const int upper_limit_) {
upper_limit = upper_limit_;
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
int retval = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
if (retval) {
throw std::runtime_error("Error while setting sharedp field for mutex");
}
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
{
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&cv, &attr);
pthread_condattr_destroy(&attr);
}
value = 0;
}
void SignalingIncrementingCounter::reset_to_empty() {
pthread_mutex_lock(&mutex);
value = 0;
// No need to signal, because in my use-case, there is no function that unblocks when the value changes to 0
pthread_mutex_unlock(&mutex);
}
void SignalingIncrementingCounter::increment() {
pthread_mutex_lock(&mutex);
fprintf(stderr, "incrementing\n");
++value;
if (value >= upper_limit) {
pthread_cond_broadcast(&cv);
}
pthread_mutex_unlock(&mutex);
}
void SignalingIncrementingCounter::block_until_full(const char * comment) {
struct timespec max_wait = {0, 0};
pthread_mutex_lock(&mutex);
while (value < upper_limit) {
int val = value;
printf("blocking until full, value is %i, for %s\n", val, comment);
clock_gettime(CLOCK_REALTIME, &max_wait);
max_wait.tv_sec += 5; // wait 5 seconds
const int timed_wait_rv = pthread_cond_timedwait(&cv, &mutex, &max_wait);
if (timed_wait_rv)
{
switch(timed_wait_rv) {
case ETIMEDOUT:
break;
default:
throw std::runtime_error("Unexpected error encountered. Investigate.");
}
}
}
pthread_mutex_unlock(&mutex);
}
Using either an int or std::atomic works.
One of the great things about the std::atomic interface is that it plays quite nicely with the int "interface". So, the code is almost exactly the same. One can switch between each implementation below by adding a #define USE_INT_IN_SHARED_MEMORY_FOR_SIGNALING_COUNTER true.
I'm not so sure about statically creating the std::atomic in shared memory, so I use placement new to allocate it. My guess is that relying on the static allocation would work, but it may technically be undefined behavior. Figuring that out is beyond the scope of my question, but a comment on that topic would be quite welcome.
signaling_incrementing_counter.h
#include <atomic>
#include "gpu_base_constants.h"
struct SignalingIncrementingCounter {
public:
/**
* We will either count up or count down to the given limit. Once the limit is reached, whatever is waiting on this counter will be signaled and allowed to proceed.
*/
void init(const int upper_limit_);
void reset_to_empty();
void increment(); // only valid when counting up
void block_until_full(const char * comment = {""});
// We don't have a use-case for the block_until_non_full
private:
int upper_limit;
#if USE_INT_IN_SHARED_MEMORY_FOR_SIGNALING_COUNTER
volatile int value;
#else // USE_INT_IN_SHARED_MEMORY_FOR_SIGNALING_COUNTER
std::atomic<int> value;
std::atomic<int> * value_ptr;
#endif // USE_INT_IN_SHARED_MEMORY_FOR_SIGNALING_COUNTER
pthread_mutex_t mutex;
pthread_cond_t cv;
};
signaling_incrementing_counter.cpp
#include <pthread.h>
#include <stdexcept>
#include "signaling_incrementing_counter.h"
void SignalingIncrementingCounter::init(const int upper_limit_) {
upper_limit = upper_limit_;
#if !GPU_USE_INT_IN_SHARED_MEMORY_FOR_SIGNALING_COUNTER
value_ptr = new(&value) std::atomic<int>(0);
#endif // GPU_USE_INT_IN_SHARED_MEMORY_FOR_SIGNALING_COUNTER
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
int retval = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
if (retval) {
throw std::runtime_error("Error while setting sharedp field for mutex");
}
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutex_init(&mutex, &attr);
pthread_mutexattr_destroy(&attr);
}
{
pthread_condattr_t attr;
pthread_condattr_init(&attr);
pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
pthread_cond_init(&cv, &attr);
pthread_condattr_destroy(&attr);
}
reset_to_empty(); // should be done at end, since mutex functions are called
}
void SignalingIncrementingCounter::reset_to_empty() {
int mutex_rv = pthread_mutex_lock(&mutex);
if (mutex_rv) {
throw std::runtime_error("Unexpected error encountered while grabbing lock. Investigate.");
}
value = 0;
// No need to signal, because there is no function that unblocks when the value changes to 0
pthread_mutex_unlock(&mutex);
}
void SignalingIncrementingCounter::increment() {
fprintf(stderr, "incrementing\n");
int mutex_rv = pthread_mutex_lock(&mutex);
if (mutex_rv) {
throw std::runtime_error("Unexpected error encountered while grabbing lock. Investigate.");
}
++value;
fprintf(stderr, "incremented\n");
if (value >= upper_limit) {
pthread_cond_broadcast(&cv);
}
pthread_mutex_unlock(&mutex);
}
void SignalingIncrementingCounter::block_until_full(const char * comment) {
struct timespec max_wait = {0, 0};
int mutex_rv = pthread_mutex_lock(&mutex);
if (mutex_rv) {
throw std::runtime_error("Unexpected error encountered while grabbing lock. Investigate.");
}
while (value < upper_limit) {
int val = value;
printf("blocking during increment until full, value is %i, for %s\n", val, comment);
/*const int gettime_rv =*/ clock_gettime(CLOCK_REALTIME, &max_wait);
max_wait.tv_sec += 5;
const int timed_wait_rv = pthread_cond_timedwait(&cv, &mutex, &max_wait);
if (timed_wait_rv)
{
switch(timed_wait_rv) {
case ETIMEDOUT:
break;
default:
pthread_mutex_unlock(&mutex);
throw std::runtime_error("Unexpected error encountered. Investigate.");
}
}
}
pthread_mutex_unlock(&mutex);
}

c++ - problem with memory in multithreading

I am currently learning about threads in c++ at uni and I have this small project involving ncurses - bouncing balls. I want the balls to spawn untill I press 'x'. After I press the button, it quits but it also shows something about memory protection violation.
When I use gdb, after pressing 'x', it says:
Thread 1 "p" received signal SIGSEGV, Segmentation fault.
0x00007ffff6e6b3c1 in _int_malloc (av=av#entry=0x7ffff71c2c40 ,
bytes=bytes#entry=28) at malloc.c:3612
The problem may be in the for loop but I am not sure.
There is the code I've written:
#include "window.h"
#include <stdlib.h>
#include <time.h>
#include <thread>
#include <unistd.h>
#include <ncurses.h>
#include <atomic>
Window *window;
std::atomic<bool> run(true);
void exit() {
while(run) {
char z = getch();
if(z == 'q') run = false;
}
}
void ballFunction(int a) {
int nr = a;
while (run && window->balls[nr]->counter < 5) {
usleep(50000);
window->balls[nr]->updateBall();
}
window->balls[nr]->x = -1;
window->balls[nr]->y = -1;
}
void updateWindow2() {
while(run) {
usleep(50000);
window->updateWindow();
}
delete window;
}
int main() {
srand(time(NULL));
window = new Window();
int i = 0;
std::vector<std::thread> threads;
std::thread threadWindow(updateWindow2);
std::thread threadExit(exit);
while(run = true) {
window->addBall();
threads.push_back(std::thread(ballFunction, i));
i++;
sleep(1);
}
threadWindow.join();
threadExit.join();
for(int j=2; j<i+2; j++) {
threads[j].join();
}
return 0;
}
#include "window.h"
#include <ncurses.h>
#include <unistd.h>
Window::Window()
{
initWindow();
}
Window::~Window()
{
endwin();
}
void Window::initWindow()
{
initscr();
noecho();
curs_set(FALSE);
clear();
refresh();
}
void Window::addBall()
{
Ball *ball = new Ball(this->ballCounter++);
this->balls.push_back(ball);
}
void Window::updateWindow()
{
for(int i = 0; i<ballCounter; i++)
{
if(balls[i]->update())
{
clear(balls[i]->yy,
balls[i]->xx);
drawBall(balls[i]->y,
balls[i]->x);
}
}
refresh();
}
void Window::clear(int y, int x)
{
mvprintw(y, x, " ");
}
void Window::drawBall(int y, int x)
{
mvprintw(y, x, "o");
}
The problem is that you have one thread adding to the balls vector while other threads are reading from it.
When addBall calls push_back, if the vector capacity is not large enough new memory will be allocated, the existing objects moved or copied to the new block, and the old memory freed. When this happens, the threads running ballFunction can write to memory that is no longer allocated. This results in Undefined Behavior, including the segmentation fault you encounter.
You need to use some form of mutex, or ensure the balls vector has sufficient space allocated (using balls.reserve(more_elements_than_youll_ever_create)).
On an unrelated note, your main while loop will never terminate, because you have an assignment rather than a comparison as the condition (use while (run) or while (run == true)).

Call join child pthread in main function

I have the test code:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
pthread_t th_worker, th_worker2;
void * worker2(void *data) {
for(int i = 0; i< 1000000; i++){
printf("thread for worker2----%d\n", i);
usleep(500);
}
}
void * worker(void *data){
pthread_create(&th_worker2, NULL, worker2, data);
for(int i = 0; i< 100; i++){
printf("thread for worker-----%d\n", i);
usleep(500);
}
}
void join(pthread_t _th){
pthread_join(_th, NULL);
}
In main() function, If I call join(the_worker2):
int main() {
char* str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void*) str);
/* problem in here */
join(th_worker2);
return 1;
}
--> Segment Fault error
Else, i call:
join(the_worker);
join(th_worker2);
---> OK
Why have segment fault error in above case?
Thanks for help !!!
If you posted all your code, you have a race condition.
main is synchronized with the start of worker but not worker2.
That is, main is trying to join th_worker2 before worker has had a chance to invoke pthread_create and set up th_worker2 with a valid [non-null] value.
So, th_worker2 will be invalid until the second pthread_create completes, but that's already too late for main. It has already fetched th_worker2, which has a NULL value and main will segfault.
When you add the join for th_worker, it works because it guarantees synchronization and no race condition.
To achieve this guarantee without the join, have main do:
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
while (! th_worker2)
usleep(100);
/* problem in here */
join(th_worker2);
return 1;
}
An even better way to do this is to add an extra variable. With this, the first loop is not needed [but I've left it in]:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
int worker_running;
pthread_t th_worker;
int worker2_running;
pthread_t th_worker2;
void *
worker2(void *data)
{
// tell main we're fully functional
worker2_running = 1;
for (int i = 0; i < 1000000; i++) {
printf("thread for worker2----%d\n", i);
usleep(500);
}
return NULL;
}
void *
worker(void *data)
{
// tell main we're fully functional
worker_running = 1;
pthread_create(&th_worker2, NULL, worker2, data);
for (int i = 0; i < 100; i++) {
printf("thread for worker-----%d\n", i);
usleep(500);
}
return NULL;
}
void
join(pthread_t _th)
{
pthread_join(_th, NULL);
}
int
main()
{
char *str = "hello thread";
pthread_create(&th_worker, NULL, worker, (void *) str);
// give worker enough time to properly start worker2
// NOTE: this not necessarily needed as loop below is better
while (! th_worker2)
usleep(100);
// give worker2 enough time to completely start
while (! worker2_running)
usleep(100);
/* problem in here (not anymore!) */
join(th_worker2);
return 1;
}

Running multiple objects each on their own thread appears to run the same object multiple times

I'm trying to create 12 new instances of a class and run each of them it's a own thread, but they seam to share the same data.
all 12 instances are on the same X and Y position, but they each should move on a random direction.
as you can see in the code, i tried various apraoches and i can't find out why.
what am i doing wrong here?
p.s. yes ... i know there are still some unused variables.
p.s.s i have looked at many places and also here before i posted the question
enemy.cpp
#include "enemy.h"
#include <time.h>
#include <windows.h>
FILE* pEnemyFile = fopen ("enemylog.txt","w");
Enemy::Enemy(const MouseServer& mServer, int& lastMousePosX, int& lastMousePosY, int& winSizeX, int& winSizeY )
:mouseServer(mServer),
lastMouseX( ( lastMousePosX ) ? lastMousePosX : 0 ), // evaluate if we get the reference
lastMouseY( ( lastMousePosY ) ? lastMousePosY : 0 ),
myPositionX(0),
myPositionY(0),
winSizeX(winSizeX),
winSizeY(winSizeY),
x(0),
y(0)
{
// original source:
// http://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx
// Allocate memory for thread data.
EDATA threadEnemyData = (EDATA) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,sizeof(enemyData));
// http://www.codeproject.com/Articles/14746/Multithreading-Tutorial
// http://www.codeguru.com/cpp/w-d/dislog/win32/article.php/c9823/Win32-Thread-Synchronization-Part-I-Overview.htm
// usefull information
// http://msdn.microsoft.com/en-us/library/z3x8b09y(v=vs.100).aspx
if( threadEnemyData == NULL )
{
//If the array allocation fails, the system is out of memory
//so there is no point in trying to print an error message.
//Just terminate execution.
ExitProcess(2);
}
threadEnemyData->X = 0;
threadEnemyData->Y = 0;
this->hThread = CreateThread(
NULL,
0,
this->MyThreadFunction,
this,
/*threadEnemyData,*/
0,
&this->dwThreadID
);
// Check the return value for success.
// If CreateThread fails, terminate execution.
// This will automatically clean up threads and memory.
if (this->hThread== NULL)
{
ErrorHandler(TEXT("CreateThread"));
ExitProcess(3);
}
//End of main thread creation loop.
}
Enemy::~Enemy()
{
// Wait until all threads have terminated.
WaitForSingleObject(this->hThread,INFINITE);
// Close all thread handles and free memory allocations.
this->hDefaultProcessHeap = GetProcessHeap();
if (this->hDefaultProcessHeap == NULL) {
}
CloseHandle(this->hThread);
//if(threadEnemyData != NULL)
//{
// HeapFree(GetProcessHeap(), 0, threadEnemyData);
// hThread = NULL; // Ensure address is not reused.
//}
// close debug file
fclose (pEnemyFile);
}
void Enemy::Draw(D3DGraphics& gfx)
{
gfx.PutPixel(this->x + 0,this->y,255,255,255);
gfx.PutPixel(this->x + 1,this->y,255,255,255);
gfx.PutPixel(this->x + 2,this->y,255,255,255);
gfx.PutPixel(this->x + 3,this->y,255,255,255);
gfx.PutPixel(this->x + 4,this->y,255,255,255);
gfx.PutPixel(this->x + 5,this->y,255,255,255);
gfx.PutPixel(this->x + 6,this->y,255,255,255);
gfx.PutPixel(this->x + 7,this->y,255,255,255);
}
// read
// http://www.tek-tips.com/viewthread.cfm?qid=1068278
DWORD WINAPI Enemy::MyThreadFunction( void* param )
{
Enemy* self = (Enemy*) param;
////self-> // <-- "this"
return self->NewThread();
}
/* initialize random seed: */
// the itelligence loop of your enemy/object
DWORD Enemy::NewThread()
{
do
{
srand ( time(NULL) );
/* generate random number: */
//self->x += rand() % 4;
//self->y += rand() % 4;
this->x += rand() % 4;
this->y += rand() % 4;
// debug stuff
char buffer[ 64 ];
sprintf_s(buffer, "enemy: x: %d Y: %d id: %d\n", (char)this->x, (char)this->y, (char)this->dwThreadID);
fputs (buffer,pEnemyFile);
// allow processor time to other threads
Sleep(100);
}while(true); // endles loop
}
void Enemy::ErrorHandler(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code.
this->dw = GetLastError();
// todo
}
enemy.h
#pragma once
#include "timer.h"
#include "D3DGraphics.h"
#include "D3DGraphics.h"
#include "Mouse.h"
/////// thread stuf
#include <tchar.h>
#include <strsafe.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
class Enemy
{
public:
Enemy();
Enemy(const MouseServer& mServer, int& lastMousePos, int& lastMousePosY, int& winSizeX, int& winSizeY);
~Enemy();
static DWORD WINAPI MyThreadFunction( LPVOID lpParam );
DWORD Enemy::NewThread();
void ErrorHandler(LPTSTR lpszFunction);
void lookingForFood();
void Draw(D3DGraphics& gfx);
int Enemy::correctX(int xParam);
int Enemy::correctY(int yParam);
private:
int myPositionX;
int myPositionY;
int lastMouseX;
int lastMouseY;
int winSizeX;
int winSizeY;
//int moveToX; // todo
//int moveToY;
int x;
int y;
// threading stuff
typedef struct ENEMYDATA // don't forget "typedef "
{
int X;
int Y; // test
} enemyData, *EDATA;
// Cast the parameter to the correct data type.
// The pointer is known to be valid because
// it was checked for NULL before the thread was created.
static Enemy* self;
HANDLE hThread;
DWORD dwThreadID;
HANDLE hDefaultProcessHeap;
DWORD dw; // error message
EDATA* threadEnemyData;
MouseClient mouseServer;
//D3DGraphics& grafix;
Timer timer;
};
It's commented out in your thread proc, but looks like you were on the right track:
srand ( time(NULL) );
It didn't work for you because all the threads start so fast that they end up with time(NULL) returning the same value for each thread. This means they're all using the same random sequence. Try seeding rand with the thread ID (or some other source that's unique per thread) and you should see unique pseudorandom number sequences.

Embedding matplotlib in C++

I am reading a message from a socket with C++ code and am trying to plot it interactively with matplotlib, but it seems Python code will block the main thread, no matter I use show() or ion() and draw(). ion() and draw() won't block in Python.
Any idea how to plot interactively with matplotlib in C++ code?
An example would be really good.
Thanks a lot.
You may also try creating a new thread that does the call to the
blocking function, so that it does not block IO in your main program
loop. Use an array of thread objects and loop through to find an unused
one, create a thread to do the blocking calls, and have another thread
that joins them when they are completed.
This code is a quick slap-together I did to demonstrate what I mean about
using threads to get pseudo asynchronous behavior for blocking functions...
I have not compiled it or combed over it very well, it is simply to show
you how to accomplish this.
#include <pthread.h>
#include <sys/types.h>
#include <string>
#include <memory.h>
#include <malloc.h>
#define MAX_THREADS 256 // Make this as low as possible!
using namespace std;
pthread_t PTHREAD_NULL;
typedef string someTypeOrStruct;
class MyClass
{
typedef struct
{
int id;
MyClass *obj;
someTypeOrStruct input;
} thread_data;
void draw(); //Undefined in this example
bool getInput(someTypeOrStruct *); //Undefined in this example
int AsyncDraw(MyClass * obj, someTypeOrStruct &input);
static void * Joiner(MyClass * obj);
static void * DoDraw(thread_data *arg);
pthread_t thread[MAX_THREADS], JoinThread;
bool threadRunning[MAX_THREADS], StopJoinThread;
bool exitRequested;
public:
void Main();
};
bool MyClass::getInput(someTypeOrStruct *input)
{
}
void MyClass::Main()
{
exitRequested = false;
pthread_create( &JoinThread, NULL, (void *(*)(void *))MyClass::Joiner, this);
while(!exitRequested)
{
someTypeOrStruct tmpinput;
if(getInput(&tmpinput))
AsyncDraw(this, tmpinput);
}
if(JoinThread != PTHREAD_NULL)
{
StopJoinThread = true;
pthread_join(JoinThread, NULL);
}
}
void *MyClass::DoDraw(thread_data *arg)
{
if(arg == NULL) return NULL;
thread_data *data = (thread_data *) arg;
data->obj->threadRunning[data->id] = true;
// -> Do your draw here <- //
free(arg);
data->obj->threadRunning[data->id] = false; // Let the joinThread know we are done with this handle...
}
int MyClass::AsyncDraw(MyClass *obj, someTypeOrStruct &input)
{
int timeout = 10; // Adjust higher to make it try harder...
while(timeout)
{
for(int i = 0; i < MAX_THREADS; i++)
{
if(thread[i] == PTHREAD_NULL)
{
thread_data *data = (thread_data *)malloc(sizeof(thread_data));
if(data)
{
data->id = i;
data->obj = this;
data->input = input;
pthread_create( &(thread[i]), NULL,(void* (*)(void*))MyClass::DoDraw, (void *)&data);
return 1;
}
return 0;
}
}
timeout--;
}
}
void *MyClass::Joiner(MyClass * obj)
{
obj->StopJoinThread = false;
while(!obj->StopJoinThread)
{
for(int i = 0; i < MAX_THREADS; i++)
if(!obj->threadRunning[i] && obj->thread[i] != PTHREAD_NULL)
{
pthread_join(obj->thread[i], NULL);
obj->thread[i] = PTHREAD_NULL;
}
}
}
int main(int argc, char **argv)
{
MyClass base;
base.Main();
return 0;
}
This way you can continue accepting input while the draw is occurring.
~~Fixed so the above code actually compiles, make sure to add -lpthread