Solved

Problem with pthread.

Posted on 2010-09-08
10
396 Views
Last Modified: 2012-06-27
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.
0
Comment
Question by:PDamasceno
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 3
10 Comments
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 375 total points
ID: 33627190
>>    reinterpret_cast<ServerDispatcher::startThread *>(arg)->run( );

ServerDispatcher::startThread is not a type. It's a static member function.

You need to specify a type when doing a cast, so :

        typedef void* (*StartThreadFunPtr)(void*);

and then :

        reinterpret_cast<StartThreadFunPtr>(arg)->run( );
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 375 total points
ID: 33627214
However, that doesn't make much sense.

Maybe what you meant to do was :

       reinterpret_cast<ServerDispatcher*>(arg)->run( );
0
 
LVL 12

Expert Comment

by:w00te
ID: 33627327
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
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 12

Expert Comment

by:w00te
ID: 33627334
Ah I hate you Infinity :p haha.
0
 

Author Comment

by:PDamasceno
ID: 33627356
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
0
 

Author Comment

by:PDamasceno
ID: 33627370
**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?
0
 
LVL 12

Assisted Solution

by:w00te
w00te earned 125 total points
ID: 33627433
Yeah, you can cycle through and do it.  I'd recommend changing that to a list though - they have more efficiency adding/removing from parts of the container aside from the ends.  You could use the List.Remove() funciton and pass in the poitner to the one you want to remove and it will do it all for you, without you needing to iterate yourself.  Here's a nice example:

http://www.cplusplus.com/reference/stl/list/remove/

If you wish to do it with your deque you should use erase, but read this first to get the background (it's short):

http://www.cplusplus.com/reference/stl/deque/erase/

PS: removing something from a queue or list wont deallocate the memory when it's a pointer, so make sure you keep the pointer you pass into the remove function and call delete on it after removing it from the list.  It also wouldn't hurt for good programming convention to set that pointer to NULL afterwards.

-w00te
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 375 total points
ID: 33627463
>> Ah I hate you Infinity :p haha.

Why, thank you ! ;)


>> 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?

You can use the erase function to delete items from a deque :

        http://www.cplusplus.com/reference/stl/deque/erase/

To find the item you want to delete, you can indeed iterate over the deque until you find it, and then use the iterator as argument for the erase function.

Alternatively, you could use the find or find_if algorithm to find the right item :

        http://www.cplusplus.com/reference/algorithm/find/
        http://www.cplusplus.com/reference/algorithm/find_if/


Btw, is there a reason you made m_Clients a global, rather than a data member of the ServerDispatcher class ?
0
 

Author Comment

by:PDamasceno
ID: 33627490
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.
0
 

Author Comment

by:PDamasceno
ID: 33627496
I thought I had to do it since I had already created a deque iterator as private in the ServerDispatcher.h.
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Socket Programming (Unix) 8 159
How to convert MFC::CString to UTF8 wchar_t* 10 449
shell script or linux command to upload a directory to artifactory? 2 332
Finding Divisors 5 60
Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

732 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question