Trap socket error 10055

This is the forum for miscellaneous technical/programming questions.

Moderator: 2ffat

Re: Trap socket error 10055

Postby mark_c » Tue Jan 14, 2020 11:42 pm

Yes Remy, true what you say. I noticed that programming and playing the piano are two very similar activities: if you don't keep practicing and reviewing what you know, you forget everything.
Anyway I solved the problem as you say too and that is instantiating 100 classes with 100 threads and 100 sockets but my problem now lies in the initialization of the 100 threads as, I am using a global variable that creates problems for me for the usual race condition problem .
This is a portion of the program with the problem.

The purpose of this part of the code is only to understand the initialization of the 100 threads through a global variable. As you can see, I have not used semaphores but a sm variable that blocks the creation of the other threads to prevent the myadr variable from being overwritten by the creation of other threads.

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

class TMyThread : public TThread
{
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread();
};

TMyThread *TMyTh[100];
AnsiString myadr;

bool sm;

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

__fastcall TMyThread::TMyThread()
: TThread(true)
{
}
//---------------------------------------------------------------------------

void __fastcall TMyThread::Execute()
{
   BOOL bErrorFlag = FALSE;
   DWORD dwBytesWritten;

   HANDLE hFile;

   AnsiString fname = "dirout\\" + myadr + ".txt";
        AnsiString msg;

   hFile = CreateFile(fname.c_str(),
                           GENERIC_WRITE,
                           FILE_SHARE_WRITE,
                           NULL,
                           CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);
        sm=false;

        msg = myadr;

   bErrorFlag = WriteFile( hFile,
                                msg.c_str(),
                                msg.Length(),
                                &dwBytesWritten,
                                NULL);

   CloseHandle(hFile);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   for(int i = 0; i<100; i++)   {

      myadr = "adr_" + IntToStr(i+1);
      TMyTh[i] = new TMyThread();
      TMyTh[i]->Resume();

                sm=true;
                while(sm);
   }

   Caption="created";

   for(int i = 0; i<1000; i++)
   {
      if (TMyTh[i])
                        TMyTh[i]->Terminate();
   }

        Caption="Terminated";
}
//---------------------------------------------------------------------------

mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 180
Joined: Thu Jun 21, 2012 1:13 am

Re: Trap socket error 10055

Postby rlebeau » Wed Jan 15, 2020 11:48 am

mark_c wrote:my problem now lies in the initialization of the 100 threads as, I am using a global variable that creates problems for me for the usual race condition problem.


Don't use globals to pass values into your threads. Add parameters to your Thread's constructor instead, eg:

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

class TMyThread : public TThread
{
private:
   AnsiString myadr;
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread(const AnsiString &Adr);
};

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------

__fastcall TMyThread::TMyThread(const AnsiString &Adr)
   : TThread(false), myadr(Adr)
{
}
//---------------------------------------------------------------------------

void __fastcall TMyThread::Execute()
{
   AnsiString fname = "dirout\\" + myadr + ".txt";

   HANDLE hFile = CreateFileA(fname.c_str(),
                           GENERIC_WRITE,
                           FILE_SHARE_WRITE,
                           NULL,
                           CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);
   if (hFile != INVALID_HANDLE_VALUE)
   {
      DWORD dwBytesWritten;
      WriteFile( hFile,
                                myadr.c_str(),
                                myadr.Length(),
                                &dwBytesWritten,
                                NULL);

      CloseHandle(hFile);
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   TMyThread* TMyTh[100] = {};
   HANDLE hTh[100] = {};
   DWORD NumThreads = 0;

   try
   {
      for(int i = 0; i < 100; ++i) {
         TMyTh[i] = new TMyThread("adr_" + IntToStr(i+1));
         ++NumThreads;
         hTh[i] = reinterpret_cast<HANDLE>(TMyTh[i]->Handle);
      }

      Caption = "created";

      do
      {
         DWORD dwRet = MsgWaitForMultipleObjects(NumThreads, hTh, FALSE, INFINITE, QS_ALLINPUT);
         if (dwRet == WAIT_FAILED)
            RaiseLastOSError();

         else if ((dwRet >= WAIT_OBJECT_0) && (dwRet < (WAIT_OBJECT_0+count)))
         {
            DWORD dwIndex = dwRet - WAIT_OBJECT_0;

            delete TMyTh[dwIndex];
            for(DWORD i = dwIndex + 1; i < NumHandles; ++i) {
               TMyTh[i-1] = TMyTh[i];
               hTh[i-1] = hTh[i];
            }

            --NumThreads;
         }

         else if (dwRet == (WAIT_OBJECT_0+count))
            Application->ProcessMessages();
      }
      while (NumThreads > 0);

      Caption = "Terminated";
   }
   __finally
   {
      for(DWORD i = 0; i < NumThreads; ++i) {
         delete TMyTh[i];
      }
   }
}
//---------------------------------------------------------------------------



Alternatively:

Code: Select all
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

class TMyThread : public TThread
{
private:
   AnsiString myadr;
protected:
   void __fastcall Execute();
public:
   __fastcall TMyThread(const AnsiString &Adr);
};

//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int ThreadsRunning = 0;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
}
//---------------------------------------------------------------------------

__fastcall TMyThread::TMyThread(const AnsiString &Adr)
   : TThread(true), myadr(Adr)
{
   FreeOnTerminate = true;
}
//---------------------------------------------------------------------------

void __fastcall TMyThread::Execute()
{
   AnsiString fname = "dirout\\" + myadr + ".txt";

   HANDLE hFile = CreateFileA(fname.c_str(),
                           GENERIC_WRITE,
                           FILE_SHARE_WRITE,
                           NULL,
                           CREATE_ALWAYS,
                           FILE_ATTRIBUTE_NORMAL,
                           NULL);
   if (hFile != INVALID_HANDLE_VALUE)
   {
      DWORD dwBytesWritten;
      WriteFile( hFile,
                                myadr.c_str(),
                                myadr.Length(),
                                &dwBytesWritten,
                                NULL);

      CloseHandle(hFile);
   }
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
   for(int i = 0; i < 100; ++i) {
      TMyTh[i] = new TMyThread("adr_" + IntToStr(i+1));
      TMyTh[i]->OnTerminate = &ThreadTerminated;
      TMyTh[i]->Resume();
      ++ThreadsRunning;
   }

   Caption = "created";
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ThreadTerminated(TObject *Sender)
{
   ++ThreadsRunning;
   if (ThreadsRunning == 0)
      Caption = "Terminated";
}
//---------------------------------------------------------------------------

Remy Lebeau (TeamB)
Lebeau Software
User avatar
rlebeau
BCBJ Author
BCBJ Author
 
Posts: 1631
Joined: Wed Jun 01, 2005 3:21 am
Location: California, USA

Re: Trap socket error 10055

Postby mark_c » Thu Jan 16, 2020 5:12 am

thanks Remy, as always.
If I understand your idea, your piece of code that I paste again, it has the function of freeing up the resources of the various threads when they naturally end their life cycle, right?

Code: Select all

do
      {
         DWORD dwRet = MsgWaitForMultipleObjects(NumThreads, hTh, FALSE, INFINITE, QS_ALLINPUT);

         if (dwRet == WAIT_FAILED)
                        {
                 RaiseLastOSError();
                        }
         else if ((dwRet >= WAIT_OBJECT_0) && (dwRet < (WAIT_OBJECT_0+NumThr)))
         {
            DWORD dwIndex = dwRet - WAIT_OBJECT_0;

            delete TMyTh[dwIndex];
            for(DWORD i = dwIndex + 1; i < NumThr; ++i) {
               TMyTh[i-1] = TMyTh[i];
               hTh[i-1] = hTh[i];
            }

            --NumThreads;
         }

         else if (dwRet == (WAIT_OBJECT_0+NumThr))
         Application->ProcessMessages();
      }
      while (NumThreads > 0);
mark_c
BCBJ Guru
BCBJ Guru
 
Posts: 180
Joined: Thu Jun 21, 2012 1:13 am

Previous

Return to Technical

Who is online

Users browsing this forum: Google [Bot] and 11 guests

cron