Monday, 29 February 2016

23 Feb

Task Groups

Can create a queue dedicated for one type of queue eg logic, thread runs throughs this
With queue/task group system we can make sure certain threads depend on other events and maintain their order
Eg when rendering is done, send event to animation (do not run before)

Can still be improved - system to create thread-specific queue
Could use CPU affinities (bind thread to a particular core)
Allow some tasks to have higher priority (useful for important tasks so they run first)
Can also batch up similar tasks (group them together)

Mutexes
Deals with shared data - shared data can cause issues
Mutex is a program object that allows multiple threads to access the same resource safely
Mutex can protect shared data by locking it
Offers exclusive, non-recursive ownership semantics (not repetitious)
Useful when one thread may read and another may write
This is known as being 'under concurrent read and writes'
Thread can wait for a mutex to unlock data or skip it if it is not vital
A mutex is a semaphore - object designed for concurrent usage
std::mutex mutexName; to create a mutex
mutexName.lock(); to lock the mutex and disallow other threads reading/writing
std::lock_guard<std::mutex>guard(mutexName); this creates a mutex that automatically unlocks after the thread has run (and is out of scope)
std::defer.lock to make sure the mutex doesn't lock automatically, an amount of time can be placed in

Atomics
Since mutexes are best used for low contention threads, we need something for high contention too
Atomics can be used
An operation type, it appears in all intents and purposes to occur instantaneously as a single operation
Must ensure your ordering to be able to use properly
Use fencing (border, threads) to achieve this
Fence tells compiler: you must use the order this is written in
std::atomic<int>intName; to create one.
Store (write) and load (read)
Use std::thread threadName (constructorName) to pass constructor and run as function pointer
All threads have a unique ID - can see this ID using std::this_thread::get_id();
this_thread:: always writes for current thread and stores in future

Could make threaded task instead(faster?) and store result of execution to std::future
std::async will always run immediately (no deferring)
Prefer using task - for the simple use of future to return value
Inside task an exception can be used to cancel (and close) that particular thread instead of the whole program, if something goes wrong
Can run out of threads, but not tasks
Threads can also cause slowdown if too many threads are called; tasks don't necessarily all run so any excess tasks won't cause any slowdown.

In summary: use threaded tasks

Monday, 8 February 2016

Feb 2

Transport Protocols

TCP = transmission control protocol
UDP = user datagram protocol

TCP guarantees all information will be sent, but is slow
UDP does not guarantee all information's delivery but is fast
While TCP requires a connection, UDP does not have to connect directly
TCP will retransmit information if it is reported lost by the receiver

Sockets
These provide the interface for data transmission
TCP can cut this data into chunks if necessary and send them that way; recombines it when it is received and the correct order is guaranteed
UDP can send data simultaneously. Sometimes known as multi-casting, this allows it to send data to multiple PCs as it doesn't need a connection
There are 2 different nodes unique to either the server or client. For the server there is a listening node and for the client there is a connecting lode
Server needs multiple sockets to support each client, and at least another spare to listen for additional clients
SF::TCPLISTENER is a class to listen for upcoming connections
Accept is a blocking call; blocking calls stop the thread for as long as the network's timer lasts for (up to 2 seconds), then resume

UDP do not need a specific connection but they do need an assigned node listener
Sending data is the same regardless of which protocol is used
All you have to do is define the name and size of the data, and for using UDP the destination must also be defined
It is generally a bad idea to send arrays of bytes
socket.received must include a parameter for how much data was sent
The wait function can be used with an if else statement
using (selector.wait(sf::seconds(10)) with 10 seconds as the example
A selector does not store data (assuming it only selects it)
Exchanging is more difficult than simply sending data. Data must be compatible both ways
Commonly known as packets during exchange
SFML provides constant types that will always work as they will be the same regardless of platform. One example is:
sf::Int32; which is a 32 bit piece of data

sf::Packet works like a normal stream operator, using the >> symbols like cin, cout etc do
packet << x << s << d; sends a packet
packet >> x >> s >> d; receives a packet

It is possible to encrypt or compress sf packets
Add a simple function to encrypt/compress before the data is sent and one for decrypting and decompressing after the packet is received
The client receives a different type of packet so this needs to be factored in as well.

A dumb terminal is a client that sends simple information to the server and does not act upon it. An example is a first person shooter client telling the server that player 1 has clicked, and where.
Server processes this information and sends it back not only to the original client, but every other client connected to the server
This, however, will always cause a delay - latency of the clients determines how much of a delay
Some clients can use rubber banding and other predictions based on what the user has done but this would no longer be seen as a dumb terminal

The peer to peer networking method has no central server so each individual client controls what happens in the game; that information is then sent to every peer
This is exploitable as a server would usually have checks for cheating, without the server it can be easy for users to change the game code to cheat
Peer to peer isn't as commonly used because of this cheating

Interpolation is prediction for what will happen in a multiplayer game. The client guesses what the player's input will achieve and does it before sending to the server; when the server sends the data back the player might teleport or move around strangely as a result of a wrong prediction. Otherwise, interpolation cuts down on latency
Extrapolation can also be used. It is still guessing but it is this time based on current movement and velocity - more of a calculation based on previous input and the assumption that the player will keep moving in that direction
No matter what, multiplayer experience will always be limited by ping, the latency and time it takes for data to be sent and return