Link to home
Start Free TrialLog in
Avatar of PDamasceno
PDamascenoFlag for Canada

asked on

Problem with pthread.

Hey Experts.

I have a class ServerDispatcher that need to be started as a thread in other class called Server, just by creating it's object like ServerDispatcher serverDispatcher;. I don't what I'm doing wrong but I can't start the freaking thread in the constructor of ServerDispatcher. I know the error is in the startThread function, but I don't know what to do. The error is this:

ServerDispatcher.cpp:79: error: expected type-specifier
ServerDispatcher.cpp:79: error: expected `>'
ServerDispatcher.cpp:79: error: expected `('
ServerDispatcher.cpp:79: error: expected primary-expression before '>' token
ServerDispatcher.cpp:79: error: 'void*' is not a pointer-to-object type
ServerDispatcher.cpp:79: error: expected `)' before ';' token

Here is the code to ServerDispatcher.cpp:

#include "ServerDispatcher.h"
#include "ClientHandler.h"
#include <string>
#include <deque>
#include <exception>
#include <iostream>
#include <pthread.h>

std::deque< ClientHandler > m_Clients;

ServerDispatcher::ServerDispatcher ( )
{
   pthread_create(&m_thread, 0, &ServerDispatcher::startThread, this);
   pthread_mutex_init( &m_mutex, NULL );
}

ServerDispatcher::~ServerDispatcher ( )
{
   pthread_mutex_destroy( &m_mutex );
}

void ServerDispatcher::AddClient ( ClientHandler *aClientHandler ) {
   m_Clients.push_back( *aClientHandler );
}

void ServerDispatcher::DeleteClient ( ClientHandler *aClientHandler ) {

}

void ServerDispatcher::DispatchMessage ( std::string message ) {
   pthread_mutex_lock(&m_mutex);
   m_ServerMessageQueue.push_front( message );
   pthread_mutex_unlock(&m_mutex);
}

std::string ServerDispatcher::GetMessageFromQueue ( ) {
   while ( true )
   {
      if ( m_ServerMessageQueue.size( ) != 0 )
      {
         break;
      }
   }

   pthread_mutex_lock(&m_mutex);
   std::string message = m_ServerMessageQueue.back( );
   m_ServerMessageQueue.pop_back( );
   pthread_mutex_unlock(&m_mutex);

   return message;
}


void ServerDispatcher::SendMessageToAllClients ( std::string message ) {
   for ( it = m_Clients.begin( ); it != m_Clients.end( ); it++ )
   {
      ClientHandler clientHandler = *it;
      clientHandler.SendMessage ( message );
   }
}

void ServerDispatcher::run ( ) {
   while ( true )
   {
      try
      {
      std::string message = GetMessageFromQueue ( );
      SendMessageToAllClients ( message );
      }
      catch ( std::exception &e )
      {
         std::cerr << "Error while sending message to all clients." << std::endl;
         break;
      }
   }
}

void * ServerDispatcher::startThread ( void *arg ) {
   reinterpret_cast<ServerDispatcher::startThread *>(arg)->run( );
}

Open in new window


And here is the code to ServerDispatcher.h:
#ifndef SERVERDISPATCHER_H
#define SERVERDISPATCHER_H

#include "ClientHandler.h"
#include <string>
#include <deque>
#include <pthread.h>

class ServerDispatcher
{
public:
  ServerDispatcher ( );
  virtual ~ServerDispatcher ( );

  void AddClient ( ClientHandler *aClientHandler );
  void DeleteClient ( ClientHandler *aClientHandler );
  void DispatchMessage ( std::string message );
  void run ( );

private:
  std::deque< std::string > m_ServerMessageQueue;
  std::deque< ClientHandler >::iterator it;
  pthread_mutex_t m_mutex;
  pthread_t m_thread;

  std::string GetMessageFromQueue ( );
  void SendMessageToAllClients ( std::string message );
  static void * startThread ( void *arg );
};

#endif // SERVERDISPATCHER_H

Open in new window


That is my problem.

Also if you guys see any errors or wrong programing practices in my code, feel free to point them to me. I'm kinda new to all this object oriented programing thing. One more thing, if you guys can show me how I can do that DeleteClient function it would be great. The m_Clients deque is a list of all the ClientHandler threads created by the server. I just need a way to delete a specific ClientHandler in the deque. I will use this function after an error in the socket being used by the ClientHandler class is detected, close socket and delete the ClientHandler from the deque.

If you guys need me to show the codes for the ClientHandler  or the Server class just ask.

Thanks for any help in advance.
SOLUTION
Avatar of Infinity08
Infinity08
Flag of Belgium image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You passed "this" when "this" is a ServerDispatcher.  You then cast: reinterpret_cast<ServerDispatcher::startThread *>(arg) into a startThread which is a function.  This can't be right since your arg is the ServerDispatcher and not a function.

I think what you wanted to do instead is cast the "this" object, which is your ServerDispatcher (which will be bassed as a void*)  back into a ServerDispatcher.  You could then call its member function, run, directly.

static_cast<ServerDispatcher*>(arg)->run();

-w00te
Ah I hate you Infinity :p haha.
Avatar of PDamasceno

ASKER

Wow.
Just did like you said Infinity:
    reinterpret_cast<ServerDispatcher*>(arg)->run( );

And it compiled fine. Simple as that.
Also thanks for the depth explain of the matter w00te.

One problem solved.

What about the other matter? Any insight on how to delete a specific ClientHandler object from that deque list? Can I just
**finishing the other post, pressed the send button by mistake.

Can I just roll through each element in the deque and compare then to the ClientHandler being entered as a argument in the DeleteClient function?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks again guys.
No reason at all.
I just removed it from there and added the m_Clients to the private part of the ServerDispatcher.h.
I thought I had to do it since I had already created a deque iterator as private in the ServerDispatcher.h.