The year is 2050, and (at least in the land of undergraduate projects) the competition between machine and machine for the ultimate soccer cup is being broadcast to you live over the internet... This Project was a group software project with a loose robotics theme for the Third Year of my Engineering and Computer Science Masters. Each candidate worked on a different portion of a soccer simulator, such as AI strategy, 3D rendering and content distribution. I worked on content delivery to broadcast the simulated soccer games out over TCP/IP to as many clients as possible. The usual design paradigm for TCP/IP severs was followed: one thread listens for connections, blocking until a client connects. A 'worker' thread is spawned (approximately) to house-keep and serve each client. To provide asynchronous simulation another high-priority thread keeps the discrete time simulation ticking, ball rolling, goals scoring etc. etc. The difficulty arrises when connecting the simulation to the set of active worker threads and synchronising the interactions. Socket operations are usually blocking (I/O causes the worker thread to be suspended) and time-consuming, taking any held locks with them. In the extreme, network disconnects are usually caught with timeouts at around 30 seconds). Consider the simple one-buffer scheme below: Above, one common buffer is used by each worker and the simulation engine. Not only must they all compete independently for the exclusive lock but most of those operations will block, taking some time to complete. This arrangement supported only 5 clients with the simulation rate dropping noticeably with each client joining. Blocking operations on a central buffer must be avoided. Consider a scheme with a buffer for each Worker thread: Dedicating a buffer allows theoretical independence between blocking operations and Simulation updates. Hoverer there must be a process to push updates from Update Buffer to TX Buffers. This process has to compete with (blocking operations holding) locks on TX Buffers. The optimal solution found in this work was to add a Monitor to each Worker thread and push updates from the Simulation Engine on condition of that monitor. This arrangement allowed 100+ clients. The project tested the server to failure by adding an increasing number of 'black hole' clients. The well-known patterns of CPU-saturation, load-average creep and catastrophic failure were observed and explained: |




