[RESOLVED] how make a multithread synchronization correctly?
i'm making my own input using the richedit win32 class.
for that i must use a structure for not lose the variable adress...
Code:
struct arg_readmultithread
{
consolewindow *consolewindowpointer=NULL;
string *strreaded=NULL;
char *chrreaded=NULL;
double *dblreaded=NULL;
string txtwrite="";
};
arg_readmultithread arg_multiread;
void APIDoEvents()
{
MSG msg;
BOOL result;
while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE )|| blnread==true)
{
if(blnread==false)
break;
TranslateMessage(&msg);
if(blnread==false)
break;
DispatchMessage(&msg);
if(blnread==false)
break;
}
}
pthread_t some_thread;
pthread_mutex_t myMutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t condition_var = PTHREAD_COND_INITIALIZER;
void multi_read(char *chr, string *str, double *dbl)
{
pthread_mutex_lock(&myMutex);
/*while(blnread==true)
{
if(GetInputState()==TRUE && (GetKeyState(VK_RETURN) & 0x8000) && (blnread==false))
{
break;
}
}*/
blnread=true;
strreaded=str;
dblreaded=dbl;
ostringstream address;
address << strreaded;
std:string name = address.str();
static int i=0;
i=i+1;
DebugText("on function" + to_string(i) + ": "+ name);//getting the actual variable adress(debuging the code)
}
static void *multithreadproc(void *pThisArg)
{
arg_readmultithread *pThis = static_cast<arg_readmultithread*>(pThisArg);
pThis->consolewindowpointer->multi_read(NULL,pThis->strreaded,pThis->dblreaded);
return nullptr;//terminates the thread
}
void read(string &txttext)
{
//change edit control seltext color:
CHARFORMAT2 cf ;
cf.cbSize = sizeof( CHARFORMAT2 ) ;
cf.dwMask = CFM_COLOR | CFM_BACKCOLOR | CFM_EFFECTS2 ;
cf.crTextColor =clrTextColor;
cf.dwEffects =0;
cf.crBackColor = clrTextBackColor;
SendMessage(consoleedit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
//recive the variable adress:
arg_multiread.consolewindowpointer=this;
arg_multiread.strreaded=&txttext;
//create a new thread:
pthread_create(&some_thread, nullptr, &consolewindow::multithreadproc,static_cast<void*>(&arg_multiread));
}
when the return key is pressed the thread will be closed:
Code:
case WM_KEYUP:
{
if((wParam==VK_RETURN) && (richedit->blnread==true))
{
if((is_number(richedit->readstring)==true))
if(richedit->dblreaded!=NULL)
*richedit->dblreaded=stod(richedit->readstring);
else
{
*richedit->dblreaded=0;
}
if(richedit->strreaded!=NULL)
*richedit->strreaded=richedit->readstring;
richedit->readstring="";
//richedit->strreaded=NULL;
richedit->blnread=false;
pthread_mutex_unlock(&richedit->myMutex);
//pthread_cond_signal( &richedit->condition_var );
}
}
break;
the multithread is, sometimes... i repeat... sometimes, working correctly. but other times i lose the correct variable adress :(
can anyone tell me what i'm doing wrong with the multithread synchronization?
i had read several tutorials, but i continue with same problems.... 90% of code, works fine... but not always :(
Re: how make a multithread synchronization correctly?
When you share a resource across threads, you need to synchronize access for reading and writing in all cases.
strreaded doesn't seem to be protected in all cases.
Re: how make a multithread synchronization correctly?
Quote:
Originally Posted by
Arjay
When you share a resource across threads, you need to synchronize access for reading and writing in all cases.
strreaded doesn't seem to be protected in all cases.
now they are protected but i continue with problems :(
heres the correct debug output:
"before read: 0x28facc
before read2: 0x28fac4
before read3: 0x28fac0
on function1: 0x28facc
on function2: 0x28fac4
on function3: 0x28fac0"
but sometimes:
"before read: 0x28facc
before read2: 0x28fac4
before read3: 0x28fac0
on function1: 0x28fac4
on function2: 0x28fac4
on function3: 0x28fac0"
why these happens?
"When you share a resource across threads, you need to synchronize access for reading and writing in all cases."
that's why i use:
Code:
pthread_mutex_lock(&myMutex);
when i start the new thread.
and:
Code:
pthread_mutex_unlock(&richedit->myMutex);
when i release the enter key...
but i don't understand what is wrong :(
Re: how make a multithread synchronization correctly?
You need to lock and unlock in each thread - you don't seem to be doing that.
I find it difficult to attempt multithreading using global variables. At the very least I suggest you create a singleton class which thread safe accessors to the data you want to share (by thread safe, I mean both the getter and setter methods would each contain a pair of calls to lock/unlock).
Another improvement is to use RAII for locking.
Try reading some of the multithreaded articles in my signature line.
Re: how make a multithread synchronization correctly?
Quote:
Originally Posted by
Arjay
You need to lock and unlock in each thread - you don't seem to be doing that.
I find it difficult to attempt multithreading using global variables. At the very least I suggest you create a singleton class which thread safe accessors to the data you want to share (by thread safe, I mean both the getter and setter methods would each contain a pair of calls to lock/unlock).
Another improvement is to use RAII for locking.
Try reading some of the multithreaded articles in my signature line.
using an infinite loop, i can test the keyboard input and if was the enter key. but i must let the cpu send the result(see the keyup code).
i'm sorry, your articles are using MFC, i don't use it.
Re: how make a multithread synchronization correctly?
see these update:
Code:
void multi_read(char *chr, string *str, double *dbl)
{
pthread_mutex_lock(&myMutex);
if (blnread==true)
pthread_cond_wait( &condition_var, &myMutex );
blnread=true;
strreaded=str;
dblreaded=dbl;
ostringstream address;
address << strreaded;
std:string name = address.str();
static int i=0;
i=i+1;
DebugText("on function" + to_string(i) + ": "+ name);
pthread_mutex_unlock(&myMutex);
//pthread_exit(NULL);
}
when the enter key is released:
Code:
case WM_KEYUP:
{
if((wParam==VK_RETURN) && (richedit->blnread==true))
{
if((is_number(richedit->readstring)==true))
if(richedit->dblreaded!=NULL)
*richedit->dblreaded=stod(richedit->readstring);
else
{
*richedit->dblreaded=0;
}
if(richedit->strreaded!=NULL)
*richedit->strreaded=richedit->readstring;
richedit->readstring="";
//richedit->strreaded=NULL;
richedit->blnread=false;
//pthread_mutex_unlock(&richedit->myMutex);
pthread_cond_signal( &richedit->condition_var );
}
}
break;
but sometimes, again :( :
"before read: 0x28facc
before read2: 0x28fac4
before read3: 0x28fac0
on function1: 0x28facc
on function2: 0x28fac0
on function3: 0x28fac0"
i'm reading: http://codebase.eu/tutorial/posix-th...tion_variables (multithread tutorial)
but, by some reason, i can't use the pthread_join(), because freezes the application\form... or i'm, too, confused how i can use it too :(
Re: how make a multithread synchronization correctly?
Quote:
Originally Posted by
Cambalinho
i'm sorry, your articles are using MFC, i don't use it.
Yes, they use MFC but not for the threading concepts. You are having trouble because you don't understand the basics of thread synchronization. Working through my articles, in spite of the MFC probably would help you.
Re: how make a multithread synchronization correctly?
Quote:
Originally Posted by
Arjay
Yes, they use MFC but not for the threading concepts. You are having trouble because you don't understand the basics of thread synchronization. Working through my articles, in spite of the MFC probably would help you.
i'm so sorry.. don't be mad with me, but can you tell me what is confuse me on code, please?
the code seems fine from what i readed :(
Re: how make a multithread synchronization correctly?
See the SimpleThread article - that is a simple console app that doesn't use MFC. Trying to create a thread safe app using global variables is difficult and the hard way to do it (no wonder why folks that take this approach find multi-threading so hard).
At any rate, the issue with your code is that the richedit control can access the data at any time and you aren't protecting that data. You protect it in the worker thread, but don't protected it when access from the UI thread that has the richedit control. Since you are using globals, I can't offer any suggestions on fixing your code.
Re: how make a multithread synchronization correctly?
In multi-threaded code, you need to protect shared variables from being accessed/updated whilst they are being modified. This can be done using a mutex. In every case use of these shared variables is protected by using a mutex lock. The code that manipulates the shared variables is protected by use of a mutex lock - but every case of usage - whether read or modify - must be protected so that across multiple threads access to the shared variables is serialised. In your WM_KEYUP code I don't see that access to the shared variables is protected by the mutex? :confused:
PS Why are you using Posix pthreads for a c++11 WIN32 program? Why not use c++11 in-built multi-threading? or use the standard WIN32 multi-threading API's.
See
http://www.cplusplus.com/reference/multithreading/
https://msdn.microsoft.com/en-US/library/y6h8hye8.aspx
Re: how make a multithread synchronization correctly?
i found the problem. how i resolve it: asynchronous the Read() function. but the next lines was not executed, because the Read() isn't a new thread. let me ask: imagine that 1 variable string have a value of 1 adress. can i use that value and convert it to LPVOID?
Re: how make a multithread synchronization correctly?
Quote:
Originally Posted by
bestellen
i found the problem. how i resolve it: asynchronous the Read() function. but the next lines was not executed, because the Read() isn't a new thread. let me ask: imagine that 1 variable string have a value of 1 adress. can i use that value and convert it to LPVOID?
Why are you responding to this thread? If you have a question, start a new thread?
Re: how make a multithread synchronization correctly?
i was getting several problems for make a shyncronization multithread. so, finally, i finish my own multithread class:
Code:
class Multithread
{
private:
HANDLE hThread=NULL;
DWORD dwThreadId=0;
bool blnSingleThreadAtTime=false;
bool blnCreationOrder=true;
function<void()> multithreadfunction=NULL;
function<void(LPVOID param)> multithreadparameterfunction=NULL;
HANDLE myEvent = CreateEvent(0, 0, 0, 0);
struct mytread
{
Multithread *classpointer=NULL;
LPVOID multithreadparameters=NULL;
};
vector<mytread> mtparameterthread;
public:
void SingleThreadAtTime(bool SingleThread)
{
blnSingleThreadAtTime=SingleThread;
}
bool SingleThreadAtTime()
{
return blnSingleThreadAtTime;
}
//make the threads by creation order
void CreationOrder(bool OrderCreation)
{
blnCreationOrder=OrderCreation;
}
bool CreationOrder()
{
return blnCreationOrder;
}
void WaitCondition()
{
WaitForSingleObject(myEvent, INFINITE);
}
void SetCondition()
{
SetEvent(myEvent);
}
static DWORD WINAPI MyThreadFunction( LPVOID lpParam )
{
static bool blnfirsttime=false;
Multithread *pThis = static_cast<Multithread*>(lpParam);
if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
pThis->WaitCondition();
blnfirsttime=true;
pThis->multithreadfunction();
if(pThis->blnSingleThreadAtTime==true && blnfirsttime==true)
pThis->SetCondition();
return 0;
}
static DWORD WINAPI MyParameterThreadFunction( LPVOID lpParam )
{
static bool blnfirsttime=false;
mytread *pThis = static_cast<mytread*>(lpParam);
if(pThis->classpointer->blnSingleThreadAtTime==true && blnfirsttime==true)
pThis->classpointer->WaitCondition();
blnfirsttime=true;
pThis->classpointer->multithreadparameterfunction(pThis->multithreadparameters);
if(pThis->classpointer->blnSingleThreadAtTime==true && blnfirsttime==true)
pThis->classpointer->SetCondition();
return 0;
}
Multithread(std::function<void()> SetFunction)
{
mtparameterthread.reserve(100);
multithreadfunction=SetFunction;
}
Multithread( function<void(LPVOID)> SetFunction )
{
mtparameterthread.reserve(100);
multithreadparameterfunction =SetFunction;
}
//corrigir
template<typename tpVariant>
Multithread( function<void(tpVariant)> SetFunction )
{
mtparameterthread.reserve(100);
multithreadparameterfunction = [=]( LPVOID pv ) { SetFunction( static_cast<tpVariant>( pv ) ); };
}
int i=-1;
template<typename tpVariant>
void operator ()(tpVariant &vrParam)
{
//LPVOID lpParam=static_cast<LPVOID>(&vrParam);
i=i+1;
mtparameterthread[i].classpointer = this;
mtparameterthread[i].multithreadparameters = &vrParam;
hThread= CreateThread(
NULL, // default security attributes
0, // use default stack size
&Multithread::MyParameterThreadFunction, // thread function name
&mtparameterthread[i], // argument to thread function
0, // use default creation flags
&dwThreadId);
if(i==100)
i=-1;
if(blnCreationOrder==true)
delay(100);
}
void operator ()(LPVOID vrParam)
{
i=i+1;
mtparameterthread[i].classpointer = this;
mtparameterthread[i].multithreadparameters = vrParam;
hThread= CreateThread(
NULL, // default security attributes
0, // use default stack size
&Multithread::MyParameterThreadFunction, // thread function name
&mtparameterthread[i], // argument to thread function
0, // use default creation flags
&dwThreadId);
if(i==100)
i=-1;
//delay for avoiding execution of all threads in same time and for not losing data because of that
if(blnCreationOrder==true)
delay(100);
}
void operator ()()
{
hThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
&Multithread::MyThreadFunction, // thread function name
this, // argument to thread function
0, // use default creation flags
&dwThreadId);
if(blnCreationOrder==true)
delay(100);
}
~Multithread()
{
CloseHandle(hThread);
CloseHandle(myEvent);
}
};
- i use a delay(sleep()) for garantie that the threads are create in same order that i create them;
- i let the wait conditions for be more flexible on any situation;
- i use a vector for never lose the data;
- i overload 3 time the function operator for accept no arguments, LPVOID and other types.
heres how i use it on read():
Code:
struct strucread
{
LPVOID varadress=NULL; //for get the variable adress
string vartype=""; //for get what type is
variant varvalue=""; //these is for write()... i had created the variant type too
};
vector<strucread> readdata;
//these constructor function works fine for a string, but not for a numbers or char* :(
Multithread mtRead{ [&]( LPVOID varname)
{
strucread *strTest=static_cast<strucread*>(varname);
if(strTest->vartype!="write")//for write().. these is for make the write been by read order dependency
blnread=true;
while(blnread==true)
{
MSG TMsg;
do
{
if(blnread==false)
break;
TranslateMessage(&TMsg);
if(blnread==false)
break;
DispatchMessage(&TMsg);
if(blnread==false)
break;
}
while (PeekMessage(&TMsg, 0, 0, 0, true) || (blnread==true));
}
if(strTest->vartype=="string")//read(string)
*((string*)(strTest->varadress)) = readstring;
else if(strTest->vartype=="char*")
{
char *cstr = new char[readstring.length() + 1];
strcpy(cstr, readstring.c_str());
*((char*)(strTest->varadress)) =cstr[0];
delete [] cstr;
}
else if(strTest->vartype=="char")
{
char cstr = readstring[0];
*((char*)(strTest->varadress)) =cstr;
}
else if(strTest->vartype=="double")
{
if(is_number(readstring)==true)
{
*((double*)(strTest->varadress)) = stof(readstring);
}
else
{
*((double*)(strTest->varadress)) =0;
}
}
else if(strTest->vartype=="int")
{
if(is_number(readstring)==true)
{
*((int*)(strTest->varadress)) = stoi(readstring);
}
else
{
*((int*)(strTest->varadress)) =0;
}
}
else if(strTest->vartype=="variant")
*((variant*)(strTest->varadress)) = readstring;
else if(strTest->vartype=="write")
{
CHARRANGE cr;
cr.cpMin = -1;
cr.cpMax = -1;
SendMessage(consoleedit, EM_EXSETSEL, 0, (LPARAM)&cr);
string strValue=strTest->varvalue;
SendMessage(consoleedit, EM_REPLACESEL, 0, (LPARAM)(char*)strTest->varvalue);
}
readstring="";
}};
void read(string &txttext)
{
//alterar o formato e a cor de texto
CHARFORMAT2 cf ;
cf.cbSize = sizeof( CHARFORMAT2 ) ;
cf.dwMask = CFM_COLOR | CFM_BACKCOLOR | CFM_EFFECTS2 ;
cf.crTextColor =clrTextColor;
cf.dwEffects =0;
cf.crBackColor = clrTextBackColor;
SendMessage(consoleedit, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf );
i=i+1;
readdata[i].varadress=&txttext;
readdata[i].vartype="string";
mtRead(&readdata[i]);
if(i==100)
i=-1;
}
- i used an array vector for not lose the data. the 100 is number of elements for the vector.
heres on write():
Code:
void write(variant strText)
{
i=i+1;
readdata[i].vartype="write";
readdata[i].varvalue=strText;
mtRead(&readdata[i]);
if(i==100)
i=-1;
}
i'm using the variant type, but it's ony for show how i use it.
i hope that my class helps the others like is help me.
sorry something and thanks to all
Re: [RESOLVED] how make a multithread synchronization correctly?
Unsynchronized Access/Race Condition on lines:
54,56,58,60
68,70,72,74
104,115,116
123,134,135
>> i use a delay(sleep()) for garantie ...
That is far from any type of garantie.
You are trying to do too much in one class - separate out the concerns. If you want a simple C++ wrapper to the CreateThread() C interface, then do only that.
gg
Re: [RESOLVED] how make a multithread synchronization correctly?
Quote:
Originally Posted by
Codeplug
Unsynchronized Access/Race Condition on lines:
54,56,58,60
68,70,72,74
104,115,116
123,134,135
>> i use a delay(sleep()) for garantie ...
That is far from any type of garantie.
You are trying to do too much in one class - separate out the concerns. If you want a simple C++ wrapper to the CreateThread() C interface, then do only that.
gg
sorry... on your test do you use SingleThreadAtTime(true)? yes these make sure that waits until the last thread is finished
Re: [RESOLVED] how make a multithread synchronization correctly?
No test is needed. When two or more threads access the same memory location, and at least one of those threads is writing then proper synchronization is needed - otherwise you have unsynchronized access / data races. This is the case on the mentioned lines.
gg
Re: [RESOLVED] how make a multithread synchronization correctly?
Quote:
Originally Posted by
Cambalinho
sorry... on your test do you use SingleThreadAtTime(true)? yes these make sure that waits until the last thread is finished
With regard to your comment of
Quote:
//delay for avoiding execution of all threads in same time and for not losing data because of that if(blnCreationOrder==true) delay(100);
As codeplug mentioned, this isn't the proper way to synchronize access to a shared resource. You need to use a synchronization primitive (e.g. critical section or mutex) to do so.
Spreading threads apart with a delay does nothing to help synchronize resource access.
Re: [RESOLVED] how make a multithread synchronization correctly?
Before you go much further, I would suggest you read and digest this book 'C++ Concurrency In Action'
http://www.amazon.co.uk/C-Concurrenc...multithreading
You will then have an understanding of the concurrency issues within the code that Arjay, Codeplug, myself et al have highlighted. Multi-threaded code needs to be built from strong foundations. Just doing a 'few tests' that seem 'to work' does not mean that the code is correct! As an example, having delays in multi-threaded code to 'make it work' is always a sign of incorrect design/implementation. Correct multi-threaded code doesn't have/need these 'delays'.
Re: [RESOLVED] how make a multithread synchronization correctly?
i found the book.. thanks.
i will share it, if i have permition(the link where i download it)
to be honest that class is working great and i had tested. i'm using it on read() and write(). it's great
Re: [RESOLVED] how make a multithread synchronization correctly?
Quote:
Originally Posted by
Cambalinho
to be honest that class is working great and i had tested. i'm using it on read() and write(). it's great
Actually, you are getting lucky and it only appears to work on the environment you are testing it on.
With multithreading code luck only gets you so far, so look forward to some debugging sessions when the code you thought 'works great' starts failing intermittently on other machines.
Re: [RESOLVED] how make a multithread synchronization correctly?
I have read and digest this book 'C++ Concurrency In Action'. Very intresting and ushelp.