00001 /* 00002 * threading-model.h 00003 * 00004 * This isn't a real header! 00005 * 00006 * This is just here for doxygen documentation. 00007 */ 00008 00009 /// \ingroup aesop_srv 00010 /*{@*/ 00011 00012 00013 /// \defgroup aesop_srv_thread Server Threading Model 00014 /// 00015 /// The AESOP Server is designed to be multithreaded. This is important so 00016 /// that the server can handle long-latency operations (reading files, etc.) 00017 /// without impacting the core processing loop. 00018 /// 00019 /// In general, the main thread of execution (the startup thread) is what 00020 /// performs the main processing loop. The server object, and other objects, 00021 /// have helper threads to do asynchronous processing. The general pattern is 00022 /// that someone requests work to be done (TCP message from client, or rules 00023 /// engine requesting a map be loaded), and the request is queued. Worker 00024 /// threads check the queue, perform the work, and either queue the result or 00025 /// know how to update state appropriately by updating threadsafe data 00026 /// collections. 00027 /// 00028 /// Objects with helper threads should maintain thread pools (or a single 00029 /// helper thread), and NOT spin off threads as needed. This requires queuing 00030 /// of requests, but helps prevent runaway thread creation. If a request queue 00031 /// gets too long, further requests should be denied. Clients (remote or local) 00032 /// should be able to handle request failure gracefully. 00033 /// 00034 /// However, threading carries penalties and dangers as well. The main 00035 /// penalty is that data shared between threads needs to be synchronized. In 00036 /// general, all data on the heap that could be shared is synchronized using 00037 /// threadsafe collections from the Wavepacket Threadsafe Library: 00038 /// http://wavepacket-lib.sourceforge.net/group__threadsafe.html 00039 /// 00040 /// 00041 /// \n 00042 /// The dangers of threading are related to that. Any important data that 00043 /// isn't protected could result in program crashes or other misbehavior. 00044 /// There, the solution is simple: any data that could be accessed by 00045 /// multiple threads must be protected! More concretely, any data on the 00046 /// heap must be protected by a threadsafe collection. 00047 /// 00048 /// The other danger is deadlocks. See http://en.wikipedia.org/wiki/Deadlock . 00049 /// That article gives a good overview of how deadlocks can occur, and how to 00050 /// avoid them. 00051 /// 00052 /// <b>The AESOP Server takes a simple approach,</b> which the wiki page describes 00053 /// as eliminating the "hold and wait" condition. In the AESOP Server, the 00054 /// only locks allowed to exist are on the threadsafe collections. Threads 00055 /// should never directly lock or unlock mutexes. Instead, threads should 00056 /// use threadsafe collections for all synchronization and communication. 00057 /// This guarantees that a thread will never take two mutexes at once. 00058 /// 00059 /// <b>For now, all code in the AESOP Server should follow this convention and 00060 /// only allow threadsafe collection objects to maintain mutexes.</b> 00061 /// 00062 /// If in the future, data model complexity requires that a thread hold 00063 /// multiple mutexes for some reason, then other solutions could be examined. 00064 /// For the simple data objects used on the server, a hierarchical approach 00065 /// (requiring threads to acquire/release locks in a certain order) may be 00066 /// fine. But given the realities of how networked games work (dropped 00067 /// UDP packets, network lag leading to clients having to guess at state), 00068 /// the simple approach (never hold multiple locks) should be enough. In 00069 /// edge cases it can lead to temporary inconsistencies, but the impact 00070 /// should be no worse than a dropped UDP packet. 00071 ///