#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2005
    Posts
    56
    Rep Power
    17

    MultiThreaded Server Class


    I have written a multithreaded server before, but this time i've we written it in a class and i cant seem to get it working properly.#

    error-

    Code:
    error C2664: 'CreateThread' : cannot convert parameter 3 from 'DWORD (void *)' to 'LPTHREAD_START_ROUTINE'
            None of the functions with this name in scope match the target type
    relevant code-

    defined in class definition
    Code:
    DWORD WINAPI ServerThread(void* SOCKET);
    Code:
    DWORD WINAPI RavenServer::ServerThread(void* SOCKET) 
    {
    	return 0;
    }
    Code:
    void RavenServer::AcceptConnections(SOCKET ls )
    {
    	sockaddr_in ClientAddress;
    	int nClientLength = sizeof(ClientAddress);
    
    	while (1)
    	{
    		SOCKET Socket = accept(ls, (sockaddr*)&ClientAddress, &nClientLength);
    		CreateThread(0, 0, ServerThread, (void*)Socket, 0, NULL);
    	}
    }
    Code:
    bool RavenServer::start()
    {
    	WSAStartup(MAKEWORD(2,2), &m_wsaData);
    	m_Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    
    	m_In.sin_family = AF_INET;
    	m_In.sin_addr.s_addr = INADDR_ANY;
    	m_In.sin_port = htons( iPort );
    
    	bind(m_Socket,(sockaddr*)&m_In,sizeof(m_In));
    	listen(m_Socket,SOMAXCONN);
    
    	AcceptConnections(m_Socket);
    
    	return true;
    }
    thats all. thanks for any help =]
  2. #2
  3. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,489
    Rep Power
    1876
    The problem is, the function you pass to CreateThread() can't really be a member of your class, because all normal class member functions receive an implicit 'this' pointer, and there is no way for the thread code to know how to do this.

    A static member function does not receive any hidden information, but is a member of the class (if that makes sense).

    Anyway, and example
    Code:
    #include <iostream>
    using namespace std;
    
    void mimicThread ( void (*fn)(void*), void *param ) {
        fn( param );
    }
    
    class RavenServer {
      public:
        RavenServer();
        ~RavenServer();
        void connect();
        void doWork();
    
        /* We make this static so it won't have an implicit 'this' */
        static void bouncer( void * );
    
      private:
        int var;
    };
    
    RavenServer::RavenServer ( ) {
        var = 0;
        cout << "ctor: this is " << reinterpret_cast<void *>(this) << endl;
    }
    RavenServer::~RavenServer ( ) {
    }
    
    // do a connection, then spawn the thread
    // make the 'this' pointer the user data the new thread will recieve
    void RavenServer::connect() {
        var++;
        cout << "connect: this is " << reinterpret_cast<void *>(this) << endl;
        mimicThread( bouncer, this );
    }
    
    // do some work
    // var should be 1, if we got the right 'this'
    void RavenServer::doWork() {
        cout << "doWork: this is " << reinterpret_cast<void *>(this) << endl;
        cout << "doWork: Var is " << var << endl;
    }
    
    // Massage the pointer into the correct type, so the invoked
    // function gets a proper 'this' pointer
    void RavenServer::bouncer( void *p ) {
        cout << "bouncer: this is " << p << endl;
        RavenServer *instance = reinterpret_cast<RavenServer *>(p);
        instance->doWork();
    }
    
    int main ( ) {
        RavenServer foo;
        foo.connect();
        return 0;
    }
    Results
    $ ./a.exe
    ctor: this is 0x22ccc0
    connect: this is 0x22ccc0
    bouncer: this is 0x22ccc0
    doWork: this is 0x22ccc0
    doWork: Var is 1


    When you create the thread, and pass the 'this' pointer as the user data pointer, then all the 'class-ness' of it gets washed away. The job of the bouncer function is to get you back into the class, where you can then once again invoke member functions and have the correct 'this' pointer to play with.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2005
    Posts
    56
    Rep Power
    17
    aha! thanks for the help! =]

IMN logo majestic logo threadwatch logo seochat tools logo