This is the forum for miscellaneous technical/programming questions.
Moderator: 2ffat
mark_c
BCBJ Master
Posts: 263 Joined: Thu Jun 21, 2012 1:13 am
Post
by mark_c » Thu Feb 28, 2019 1:40 am
Hello,
I'm struggling with an old educational project for the study of synchronization, I do not understand why in this case there is no collision!
In my opinion, it should be there when Thread1 writes to the StringGrid: am I wrong?
Thank you
Code: Select all
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
class TMyThread1 : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread1();
void __fastcall MySincrSock1();
String msg;
};
TMyThread1 *Thread1 = NULL;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ServerSocket1->Port = 5000;
ServerSocket1->Active = true;
}
//---------------------------------------------------------------------------
__fastcall TMyThread1::TMyThread1()
: TThread(true)
{
}
//---------------------------------------------------------------------------
void __fastcall TMyThread1::MySincrSock1()
{
try{
for(int actconn = 0; actconn < Form1->ServerSocket1->Socket->ActiveConnections; actconn++)
{
Form1->ServerSocket1->Socket->Connections[actconn]->SendText(msg);
Form1->Caption="1";
}
} catch(...) { }
}
//---------------------------------------------------------------------------
void __fastcall TMyThread1::Execute()
{
while (!Terminated)
{
for(int i=0; i<10;i++)
{
msg.sprintf("Y27.5,1,192.168.1.%d,5694,25,25,127",i);
Synchronize(&MySincrSock1);
Form1->StringGrid1->Cells[1][i]=msg;
Sleep(100);
Form1->StringGrid1->Cells[1][i]="";
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete Thread1;
ServerSocket1->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Thread1 = new TMyThread1();
Button1->Enabled = false;
Button2->Enabled = true;
Caption = "Started.....";
Thread1->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if (Thread1) Thread1->Terminate();
Button1->Enabled = true;
Button2->Enabled = false;
Caption = "Stopped.....";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
Socket->Close();
ErrorCode = 0;
}
//---------------------------------------------------------------------------
mark_c
BCBJ Master
Posts: 263 Joined: Thu Jun 21, 2012 1:13 am
Post
by mark_c » Fri Mar 01, 2019 2:59 am
finally with this version I can experience a collision: apparently a single thread, the previous version of the code, is not enough to cause a collision or, it can happen a collision but in a non-deterministic time
Code: Select all
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
class TMyThread1 : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread1();
void __fastcall MySincrSock1();
String msg;
};
class TMyThread2 : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread2();
void __fastcall MySincrSock2();
String msg;
};
TMyThread1 *Thread1 = NULL;
TMyThread2 *Thread2 = NULL;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ServerSocket1->Port = 5000;
ServerSocket1->Active = true;
ServerSocket2->Port = 5001;
ServerSocket2->Active = true;
}
//---------------------------------------------------------------------------
__fastcall TMyThread1::TMyThread1()
: TThread(true)
{
}
//---------------------------------------------------------------------------
__fastcall TMyThread2::TMyThread2()
: TThread(true)
{
}
//---------------------------------------------------------------------------
void __fastcall TMyThread1::MySincrSock1()
{
try{
for(int actconn = 0; actconn < Form1->ServerSocket1->Socket->ActiveConnections; actconn++)
{
Form1->ServerSocket1->Socket->Connections[actconn]->SendText(msg);
Form1->Caption="1";
}
} catch(...) { }
}
//---------------------------------------------------------------------------
void __fastcall TMyThread2::MySincrSock2()
{
try{
for(int actconn = 0; actconn < Form1->ServerSocket2->Socket->ActiveConnections; actconn++)
{
Form1->ServerSocket2->Socket->Connections[actconn]->SendText(msg);
Form1->Caption="2";
}
} catch(...) { }
}
//---------------------------------------------------------------------------
void __fastcall TMyThread1::Execute()
{
while (!Terminated)
{
for(int i=0; i<10;i++)
{
msg.sprintf("Y27.5,1,192.168.1.%d,5694,25,25,127",i);
Synchronize(&MySincrSock1);
Form1->StringGrid1->Cells[1][i]=msg;
Sleep(100);
Form1->StringGrid1->Cells[1][i]="";
}
}
}
//---------------------------------------------------------------------------
void __fastcall TMyThread2::Execute()
{
while (!Terminated)
{
for(int i=0; i<10;i++)
{
msg.sprintf("Y27.5,1,192.168.1.%d,5694,25,25,127",i);
Synchronize(&MySincrSock2);
Form1->StringGrid1->Cells[1][i]=msg;
Sleep(100);
Form1->StringGrid1->Cells[1][i]="";
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete Thread1;
delete Thread2;
ServerSocket1->Active = false;
ServerSocket2->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Thread1 = new TMyThread1();
Thread2 = new TMyThread2();
Button1->Enabled = false;
Button2->Enabled = true;
Caption = "Started.....";
Thread1->Resume();
Thread2->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if (Thread1) Thread1->Terminate();
if (Thread2) Thread2->Terminate();
Button1->Enabled = true;
Button2->Enabled = false;
Caption = "Stopped.....";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket1ClientError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
Socket->Close();
ErrorCode = 0;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ServerSocket2ClientError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
Socket->Close();
ErrorCode = 0;
}
//---------------------------------------------------------------------------
mark_c
BCBJ Master
Posts: 263 Joined: Thu Jun 21, 2012 1:13 am
Post
by mark_c » Sat Mar 09, 2019 12:17 pm
Hello,
but is it possible to declare and implement the shared methods only once so they can be used by multiple threads?
the method below, for example, is very inconvenient.
Code: Select all
class TMyThread1 : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread1();
void __fastcall MySincrSock();
void __fastcall MyStringGrid();
String msg;
int i;
};
class TMyThread2 : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread2();
void __fastcall MySincrSock();
void __fastcall MyStringGrid();
String msg;
int i;
};
void __fastcall TMyThread1::MyStringGrid()
{
Form1->StringGrid1->Cells[1][i]=msg;
if(i > 0)
Form1->StringGrid1->Cells[1][i-1]="";
}
//---------------------------------------------------------------------------
void __fastcall TMyThread2::MyStringGrid()
{
Form1->StringGrid1->Cells[1][i]=msg;
if(i > 0)
Form1->StringGrid1->Cells[1][i-1]="";
}
//---------------------------------------------------------------------------
[b]void __fastcall TMyThread(n)::MyStringGrid()[/b]
{
Form1->StringGrid1->Cells[1][i]=msg;
if(i > 0)
Form1->StringGrid1->Cells[1][i-1]="";
}
//---------------------------------------------------------------------------
rlebeau
BCBJ Author
Posts: 1759 Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:
Post
by rlebeau » Wed Apr 17, 2019 12:17 pm
mark_c wrote: but is it possible to declare and implement the shared methods only once so they can be used by multiple threads?
Simply use a single thread class. Your multiple classes are doing the exact same thing, and thus are completely redundant. Just create multiple object instances of the same class.
Code: Select all
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
class TMyThread : public TThread
{
protected:
void __fastcall Execute();
public:
__fastcall TMyThread(int ANum, TServerSocket *AServer);
void __fastcall MySincrSock();
String msg;
int num;
TServerSocket *server;
};
TMyThread *Thread1 = NULL;
TMyThread *Thread2 = NULL;
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
ServerSocket1->Port = 5000;
ServerSocket1->Active = true;
ServerSocket2->Port = 5001;
ServerSocket2->Active = true;
}
//---------------------------------------------------------------------------
__fastcall TMyThread::TMyThread(int ANum, TServerSocket *AServer)
: TThread(true)
{
num = ANum;
server = AServer;
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::MySincrSock()
{
try{
for(int actconn = 0; actconn < server->Socket->ActiveConnections; actconn++)
{
server->Socket->Connections[actconn]->SendText(msg);
Form1->Caption = num;
}
} catch(...) { }
}
//---------------------------------------------------------------------------
void __fastcall TMyThread::Execute()
{
while (!Terminated)
{
for(int i = 0; i < 10; i++)
{
msg.sprintf("Y27.5,1,192.168.1.%d,5694,25,25,127",i);
Synchronize(&MySincrSock);
Form1->StringGrid1->Cells[1][i]=msg;
Sleep(100);
Form1->StringGrid1->Cells[1][i]="";
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
delete Thread1;
delete Thread2;
ServerSocket1->Active = false;
ServerSocket2->Active = false;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
Thread1 = new TMyThread(1, ServerSocket1);
Thread2 = new TMyThread(2, ServerSocket2);
Button1->Enabled = false;
Button2->Enabled = true;
Caption = "Started.....";
Thread1->Resume();
Thread2->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
if (Thread1) Thread1->Terminate();
if (Thread2) Thread2->Terminate();
Button1->Enabled = true;
Button2->Enabled = false;
Caption = "Stopped.....";
}
//---------------------------------------------------------------------------
// you can assign this one handler to BOTH TServerSocket objects!
void __fastcall TForm1::ServerSocketClientError(TObject *Sender,
TCustomWinSocket *Socket, TErrorEvent ErrorEvent, int &ErrorCode)
{
Socket->Close();
ErrorCode = 0;
}
//---------------------------------------------------------------------------
mark_c
BCBJ Master
Posts: 263 Joined: Thu Jun 21, 2012 1:13 am
Post
by mark_c » Sat Apr 20, 2019 7:09 am
thanks remy, forgive my curiosity: but are you a teacher?
rlebeau
BCBJ Author
Posts: 1759 Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA
Contact:
Post
by rlebeau » Tue Apr 23, 2019 12:09 pm
mark_c wrote: thanks remy, forgive my curiosity: but are you a teacher?
No, I am not. I am a professional software developer.