Skip to main content
gamedev.net
🔒 Locked

safe variable access

Started by save yourself May 15, 2004 at 12:37 AM 4 replies 700+ views
Original Post
save yourself
save yourself
My program will potentially be running multiple threads (through IOCP) so I need a way to protect the access to my variables. It''s a text based setup, so each room and entity has it''s own instance of a structure, all of which can be modified or just read from based on certain player actions. I realize that critical sections can be used to make sure only one thread at a time can get to certain variables, but does this mean I need to define a critical section for each data structure I have? That seems like quite a bit! If I had just one critical section per structure type then only one thread at a time could actually run and the others would all block even if they weren''t going after the exact same variables, so it seems like I would need a unique critical section for each... is there a better way? Is this going to crush performance somehow?
hplus0603
hplus0603
Structure locking or type locking? Table locking or row locking? Same thing, same problem: you don''t want to design for locking at all. Instead, remove all the unnecessary threads, and use asynchronous events, and overlapped I/O, where possible.
enum Bool { True, False, FileNotFound };
save yourself
save yourself
It's a multiplayer text based rpg game... I'm using IOCP as my method of networking and managing the incoming data and socket accepts. When IOCP allows multiple worker threads to be active, I don't have any control over which one gets to run when so that makes me think I definately need some way to make sure I'm not writing and reading the same memory space at the same time on two different threads. Critical sections were suggested to me in another post, but with the large amount of different data structures I have, I'm just searching to find out the common methods used.

I don't mind learning complex techniques if they are good ones... I'm programming this as a learning experience anyways.

hplus - The only threads I have are the main loop and the worker threads activated by the completion port processing network data... IOCP handles them asynchronously using overlapped I/O, that's why I have the problem.

edit: surely SOMEBODY must have insight on this type of thing... how do YOU make your data thread safe?

[edited by - Save yourself on May 15, 2004 12:37:11 AM]
hplus0603
hplus0603
You have one big data store. This data store is internally linked, because entities are in rooms that connect to other rooms that contain players that are on missions that ...

The locking necessary to make a consistent change to the database bloats quickly, because it''s not enough to protect a specific piece of data, you need to protect the overall state of the world. For example, if there''s two separate action that can generate Shiny Balls, but there''s a rule that there can only be one Shiny Ball in the world at a time, then two players could be performing each of the actions at the same time. Only one should be allowed to create the Shiny Ball -- thus, even though they perform different actions in different rooms, they need to be synchronized on the Shiny Ball rule.

I call it a "database", but it may live on disk, in tables, in structs in memory, as text stored on punch tape... doesn''t matter; it''s the same problem because the data has the same inherent connectivity and rule set.

Start adding constraints like these (and they show up ALL THE TIME), and soon you realize that you have a single, big, interlinked world database, and the only two ways of locking it are:

1) Lock-as-you-go transactions, a la big SQL databases, and transaction rollback when you detect possible deadlock. This takes months, if not years, to implement, test, and work out the final bugs from. (Witness Oracle fix logs...)

2) A single lock for the entire database.

Once you go with option 2), you realize that using more than one completion thread is just silly, because each thread will immediately just acquire the lock, so there will be no benefit from multiple threads. Thus, it sounds as if in this case, you really are better off by using a single worker thread for all your network operations.
enum Bool { True, False, FileNotFound };
save yourself
save yourself
But it''s really not as linked as you would think. Write access to a variable is typically granted for adding a player to a room or swapping the location of items from player to room, player to player, etc... If Joe walks into room number 42, nobody in room 4157 is going to care... Heck, nobody in room 43 is going to care (unless that''s the room Joe left). If Joe gives an apple to Jill, nobody but Joe and Jill care (in terms of writing data).

The point is, I don''t see how one big lock that covers all data would be the way to go in my case. One big lock is pretty much the same as just having one worker thread, like you said. The IOCP method can even potentially run more concurrent threads than I specify, so I would have to really only have one thread in existance so there is never more than one running. I understand the simple solution would be to just let one thread handle the network operations, but taking the simple solution will just eliminate scalability, which was one of the reasons for using IOCP...

Most likely the number of concurrent worker threads will be set to one anyways, but you never know... I suppose a pool of critical sections/mutex''s will have to be my solution, and break up game regions to correspond with a critical section from the pool. That way a thread won''t ALWAYS block if somebody else is doing anything... I was just wondering if there were any clever approaches.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.