Advertisement

More questions regarding handling multiple clients

Started by March 11, 2003 05:12 PM
5 comments, last by Megahertz 21 years, 11 months ago
I read the previous threads regarding handling multiple clients (link http://www.gamedev.net/community/forums/topic.asp?topic_id=144049 and http://www.gamedev.net/community/forums/topic.asp?topic_id=144336) and I''m working on something similar in design, but have run into a few issues with the way im doing things. I basically have the same setup, I have a ConnectionManager class which is more or less a wrapper around a linked list object. There are 2 methods to add and remove from this list, and also 2 methods for transfering of data, one for Sending and one for Recieving. Each method simply calls the objects in the linked list respective SendData and RecieveData method. I also have 2 threads with each one being dedicated to each of these methods. Each thread gets passed in the linked list object as a parameter so that I can call the appropriate methods from inside the thread. My hopes is that I can have one thread iterating through the linked list and handling the sends on each object, while the other at the same time is iterating through the list and handling the recieves. The root of my problem is that because I have two places where I need to iterate through the linked list, it''s going to need to have access proteced in some manner so that I cant modify/access the list while the other thread is iterating through it. I''ve ecapsulated access to the list in the ConnectionManager class so that I can have methods to Add, Delete and Process (Send or Recieve, depending on which thread im in) the objects in the linked list AND have critical sections in these methods so that while im accessing the list to add a connection, I cant delete from the list until the lock is released. The only downside is that I have to also put critical sections around the processing of the objects because I don''t want to delete an object from the list while the other thread might be running its SendData method. Since I might have a lock on access to the list in one thread in the SendData method, I wont be able to do the RecieveData calls in the other thread due to the lock. This prevents both threads from operating on the list of connections at the same time and makes the above idea useless. Is there a way to achieve what I''m wanting to do with 1 list and two threads each doing their own thing on this list? I''d like to keep the 1 list because I also have a list of clients that will be processed in yet another thread. Each client has a member variable which is a refrence to the clients connection object and therefore can push and pop messages off the connections'' queues. This allows me to get a message from one client, say a text message and then queue that message out to either all the clients or perhaps just a subset of the clients based on distance. I hope I explained everything well enough that its all makes sense and any help on this will be greatly appreciated. -=[ Megahertz ]=-
-=[Megahertz]=-
quote:
Original post by Megahertz
The root of my problem is that because I have two places where I need to iterate through the linked list

Why does it have to be implemented as a linked list? Once you change pointers around, other threads may (and will) become confused.

Nothing prevents you from managing a big static vector of inactive elements: add new elements by marking inactive ones as active and remove elements by marking them as deleted. Elements that have been marked as deleted for some time can be made back to the inactive state (kinda garbage collection). The only thing to protect is the check and change for the state flag and that can be made very fast with a critical section (or a spinlock on Linux). I suggest you get one CS per element even if it is inactive; it prevents one thread from sending data while another one is trying to mark it as deleted.

Just a thought...

-cb



[edited by - cbenoi1 on March 11, 2003 7:53:37 PM]
Advertisement
There are better ways to handle multiple clients than using 2 threads to perform send/receive operations.

Is there a reason that you are not using overlapped I/O (and completion ports if you are running under NT or higher)?



[email=direwolf@digitalfiends.com]Dire Wolf[/email]
www.digitalfiends.com
The thought of using an array/vector had crossed my mind, but I usually like to keep things dynamic so that theres no limitations in my code. There will of course be hardware and OS limitations, so I guess I can make an exception here.

As for IO completion ports, I plan on porting the codebase to run on linux after I''ve worked out most of the design issues and have something working on windows. I like Visual studio for development and the debugging process is usually easier.

Thanks for the comments.

-=[ Megahertz ]=-
-=[Megahertz]=-
You should learn POSIX mutexes (mutual exclusions) and condition variables to manage your lists. Mutexes are designed for multithreaded environment just to make sure that data is not changed in one thread while the other thread is processing it. Besides mutexes are widely used in Linux (and BSD) socket apps. So there's no lack of information on the topic. I recommend reading "Advanced Linux Programming" by Mark Mitchel and "Linux Socket Programming" by Sean Walton. It is all explained there in a simple and clear manner. As for coding under MS Windows there's also a mechanism which provides means of preventing data of being changed in a single thread while other threads process it. But the code which utilizes MS Windows threads is hard to port to Linux. So I recommend to make it with Linux tools. There are also POSIX libs designed for Windows, so you probably need to download them as well as docs and instructions on using them if you want your code to be system-independent and compatible and if you want to code for Linux under Windows. If you still have some problems or questions about using mutexes and posix threads after reading provided docs feel free to ask them via e-mail. =)

Look here for info and download links:
http://sources.redhat.com/pthreads-win32/announcement.html
http://sources.redhat.com/pthreads-win32/
http://www.llnl.gov/computing/tutorials/workshops/workshop/pthreads/MAIN.html
http://dis.cs.umass.edu/~wagner/threads_html/tutorial.html
http://users.actcom.co.il/~choo/lupg/tutorials/multi-thread/multi-thread.html

"I'll be Bach!" (c) Johann Sebastian Schwarzenegger


[edited by - x33 on March 11, 2003 10:22:53 PM]
"I'll be Bach!" (c) Johann Sebastian Schwarzenegger
If im understanding your wording right, it seems you are suggesting in your above post that I could have list A and 2 threads B and C.

Using mutexes I could create a lock in A which would prevent threads B and C from accessing the list but also there would be no way to lock B and prevent C from doing its work but at the same time prevent A from messing with the list?

Likewise there would be no way to lock C and prevent B from doing its work but also A wouldnt be able to modify the list.

Im currently using CRITICAL_SECTION(s) to prevent access to the list while the threads are going. However, as i stated above if I lock A , B AND C both have to wait until the lock is released in A, since i need to have the same CRITICAL_SECTION object in B and C. If I lock in B then A has to wait for the lock to be released which is what I want, however C also has to wait for the lock to be released which unfortunately is not what i want.

Hmm, now that i think about this and your mention of conditional variables, perhaps i could protect those and use them to setup the exclusions I need. The only issue would be when I test the variable and in the next line enter the lock that variable could get modified by another thread in between.

Thanks for the list of links. I will definately give those a look and see what I can learn. I''m still pretty new to network programming and writing multi-threaded apps, but I''m sure ill get the hang of it soon. =)

Thanks again.

-=[ Megahertz ]=-

-=[Megahertz]=-
Advertisement
quote:
Original post by Megahertz
The thought of using an array/vector had crossed my mind, but I usually like to keep things dynamic so that theres no limitations in my code. There will of course be hardware and OS limitations, so I guess I can make an exception here.


In the case you have detailed, you have to protect each element of the list against simultaneous processing and deletion, and then you have to protect the integrety of the list''s topology so that an iterating thread could not end up in a deleted element by following the ''next'' pointer. The two protections are intertwined in the case of a linked list, thus the difficulty. Deleting must mean something other than rerouting pointers and freeing an element, hence my suggestion to use flags instead. I also suggested using an array because I knew of the 64 sockets limit of select() in Windows, but you could use a linked list as long as you do not change its topology other than appending new elements.

-cb

This topic is closed to new replies.

Advertisement