- NOTES, how things work... or are suppose to - LOCKING Locking must be done in a multi-threaded enviroment, where data can be accessed by all threads at the same time. In ARISA I have choosen a tree based locking model. You must lock inward of the tree, although you don't have to start at the base. The tree looks like this, and follows the way the data structures are defined global-+-main_settings |-network_settings |-(networks)-+-network-+-info-+-squeue | |-network | `-nick_tracker | `-network `-settings | |-(packlists)-packlist-+-(packs)-+-pack | | |-pack | | `-pack | `-queue-> | |-(queues)-queue-+-(qsends)-+-send-pack | | |-send-pack | | `-send-pack | `-pool-> | |-(interfaces)-interface-+-(pools)-+-pool-(csends)-+-send-pack | | | |-send-pack | | `-pool `-send-pack | | | |-(uploads)-+-send-pack | | `-send-pack | | | `-(chats)-+-chat-queue | `-chat-queue |-(admins)-+-chat-queue | `-chat-queue |-log |-party_line `-host_tracker Examples A) We want to send a message to a network, which we have the name of, we would do the following: 1. LOCK global 2. LOCK each network, test to see if it is the desired one, else UNLOCK 3. (network is now LOCKED), LOCK info 4. Insert message into the queue, functions provided LOCK it as well 5. UNLOCK info 6. UNLOCK network 7. UNLOCK global B) Same as (A), but we know the pointer to the already network this time: 1. LOCK network 2. LOCK info 3. Insert message into the queue, functions provided LOCK it as well 4. UNLOCK info 5. UNLOCK network No global lock is required since we don't access the list of networks in global. Exceptions Any of the structs attached to global, which are not members of arrays may be accessed without holding the global lock. Deletion Since data structures maybe referenced by a pointer without locking we have to carefully purge these references before deallocating the structures, this is done by a three stage process (for data structures which require it, e.g. networks, queues, etc). For complex structures: 1. Deletion marks, when a structure is "deleted" it marked so, but not deallocated immediately. 2. After a time period (at present 5 minutes) data structures which are marked as deleted, are deallocated and any remaining globally accessible references forcibly removed. Threads are expected to expire their own local references to deleted structures by this point. For (almost) all structures: 3. Deallocation always occurs in the same thread, at present the following pattern is used: Main/Manager Thread: netset_t, network_t, pool_t, queue_t, packlist_t, chat_t Network Thread: netlocal_t, channel_t Sender Thread: send_t (active ones) - EXECUTION FLOWS Below are documented the more complex execution flows. Send Addition - Within Entry Thread, (Network or Chat): 1. Create send structure from pack 2. Attempt to place in pool 3. If pool full, attempt to queue 4. If queue full, notify user 5. If queue successful, notify user Within Sender Thread: 1. New send detected on loop cycle, 2. Socket opened, internal structures allocated 3. DCC SEND sent OR 1. Dequeue occurs and send is added to pool FIXME: Finish ^_^;;