C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Слушайте, люди помогите. Тема — потоки..., Потоки...
Gambolt
Отправлено: 03.05.2005, 17:17


Ученик-кочегар

Группа: Участник
Сообщений: 3



Имеем:
QUOTE


SERVICE.H

class TMainServ : public TService
{
__published:    // IDE-managed Components
       TServerSocket *CheckServ;
       void __fastcall CheckServGetThread(TObject *Sender,
         TServerClientWinSocket *ClientSocket,
         TServerClientThread *&SocketThread);
       void __fastcall ServiceStart(TService *Sender, bool &Started);
       void __fastcall ServiceStop(TService *Sender, bool &Stopped);
       void __fastcall ServicePause(TService *Sender, bool &Paused);
       void __fastcall ServiceContinue(TService *Sender, bool &Continued);
private:        // User declarations
public:         // User declarations
__fastcall TMainServ(TComponent* Owner);
TServiceController __fastcall GetServiceController(void);
friend void __stdcall ServiceController(unsigned CtrlCode);
       void __fastcall LogP(AnsiString S);
};

extern PACKAGE TMainServ *MainServ;

class PACKAGE TMyServerThread : public Scktcomp::TServerClientThread
{
  public:
     __fastcall TMyServerThread(bool CreateSuspended, TServerClientWinSocket* ASocket)
        : Scktcomp::TServerClientThread(CreateSuspended, ASocket)
        { CreateSuspended = false; KeepInCache=true; FreeOnTerminate=false; };
     void __fastcall ClientExecute(void);

};


Еще имеем:

QUOTE

void __fastcall TMyServerThread::ClientExecute(void)
{
  while (!Terminated && ClientSocket->Connected)
  {
     try
     {
        TWinSocketStream *pStream = new TWinSocketStream(ClientSocket, CLIENTWAITTIME);
        try
        {
           char buffer[BUFFERSIZE];
           memset( buffer, 0, sizeof(buffer) );
           if (pStream->WaitForData(CLIENTWAITTIME))
           {
              if (pStream->Read(buffer, sizeof(buffer)) == 0)
              {
                 ClientSocket->Close();
              }
              else
              {
                 // Тест — возвращаем полученное...
                 pStream->Write( buffer, sizeof(buffer));
              }

           }
           else
              ClientSocket->Close();
        }
        __finally
        {
           delete pStream;
        }
     }
     catch (...)
     {
        HandleException();
     }
  }
}

void __fastcall TMainServ::CheckServGetThread(TObject *Sender,
     TServerClientWinSocket *ClientSocket,
     TServerClientThread *&SocketThread)
{
 SocketThread = new TMyServerThread(false, ClientSocket);
}


Суть:
Соединений на серверный сокет может быть по самое нехочу. А прии создании следующего потока я утрачиваю доступ к предыдущему. Вопрос: Как поэлегантнее запхать их в динамический массив?
Типа привинтить к этому делу указатели на предыдущий (PrivThread) и последующий (NextThread) потоки? Если PrivThread==NULL то мы стоим на первом потоке, если NextThread==NULL на последнем. А снаружи болтается какие-нибудь FirstThread, LastTread для быстрого перемещения в верх и вниз массива и CurrThread для работы с выбранным потоком.
Идея в следующем:
Ставим указатель CurrThread на FirstThread, проверяем идентификатор потока (например ThreadId) если результат проверки не удовлетворителен, Сдвигаем указатель CurrThread на CurrThread->NextThread и так до получения удовлетворительного результата проверки (в этом случае просто работаем с выбранным потоком) или до CurrThread==LastThread (ну далее можно что нибудь тоже сделать)
Вот. Кто может что посоветовать?
Asher
Отправлено: 04.05.2005, 08:31


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.
Простой список указателей на ваши треды.
sdt::list

В этой постановке задачи непонятно кто отвечает за проверку жизнеспособности потоков.
Обычным решением считается создание набора постоянно существующих, спящих по SleepEx(INFINITE, TRUE); потоков в которые добавляются задания через QueueUserAPC. И увеличиваете счетчик заданий для того потока, котору добавили работу.
Только ваша добавляемая функция потока должна уметь уменьшать свой счетчик заданий.
Дальше ищите свободный, т.е. спящий и не потребляющий поток, и озадачиваете его. Если свободных нет, то или озадачиваете минимально нагруженного, или, если задержка недопустима, создаете новый поток и помещаете его в список sdt::list
Это уже от логики вашего приложения зависит.
Gambolt
Отправлено: 04.05.2005, 08:38


Ученик-кочегар

Группа: Участник
Сообщений: 3



Да нет тут тема в другом, потоки сами следят за своей жизнеспособностью. И как только функционал потока исчерпывается — завершаются, но при завершении поток должен уравнять указатель NextThread предыдущего потока со своим NextThread и PrevThread последующего со своим PrevThread после чего затерминейтиться. Признаком жизни потока является существование соединения по соответствующему сокету.
Asher
Отправлено: 04.05.2005, 09:26


Мастер участка

Группа: Модератор
Сообщений: 550



Тогда просто пусть поток делает remove своего элемента из доступного всем потокам списка.
Т.е. создали поток, указатель на него в список push(), у потока доступ к списку и знает указатель на себя.
Перед завершением ищет себя в списке и делает указателю remove.
Все.

Вернуться в Вопросы программирования в C++Builder