General lock order: - Client execute lock - Server state lock - Server channel tree - Client channel tree When executing a command: Lock order: - Client execute lock - Client state lock - Server state lock (Server should not try to change state while a client is executing something) Notes: The server might be null or the default server. This must be checked via the given macro! Disconnect/unregister a client: - Lock client execute lock - Lock server state - Unregister client from server and set server variable to nullptr - Underlying server (UDP, Web, etc. disconnect) Client channel tree connect/mode/disconnect: - Lock client execute lock - Lock server channel tree in write mode - Lock client channel tree in write mode - Move client & notify (notify required all clients to have their channel tree locked in shared mode) Command lock overview: CommandResult handleCommandClientUpdate(Command&); CommandResult handleCommandClientEdit(Command&); CommandResult handleCommandClientEdit(Command&, const std::shared_ptr<ConnectedClient>& /* target */); CommandResult handleCommandClientMove(Command&); CommandResult handleCommandClientGetVariables(Command&); CommandResult handleCommandClientKick(Command&); CommandResult handleCommandClientPoke(Command&); CommandResult handleCommandChannelSubscribe(Command&); read lock: server channel tree => client lock write CommandResult handleCommandChannelSubscribeAll(Command&); read lock: server channel tree => client lock write CommandResult handleCommandChannelUnsubscribe(Command&); read lock: server channel tree => client lock write CommandResult handleCommandChannelUnsubscribeAll(Command&); read lock: server channel tree => client lock write CommandResult handleCommandChannelCreate(Command&); write lock server channel tree => iterate clients lock (write) CommandResult handleCommandChannelDelete(Command&); write lock server channel tree => iterate clients lock (write) CommandResult handleCommandChannelEdit(Command&); write lock server channel tree CommandResult handleCommandChannelGetDescription(Command&); read lock: server channel tree CommandResult handleCommandChannelMove(Command&); write lock server channel tree CommandResult handleCommandChannelAddPerm(Command&); read lock: server channel tree => all clients write lock CommandResult handleCommandChannelDelPerm(Command&); read lock: server channel tree => all clients write lock CommandResult handleCommandChannelGroupDel(Command&); read lock: server channel tree => all clients in the group should not be allowed to switch a channel CommandResult handleCommandSetClientChannelGroup(Command&); read lock: server channel tree => client should not be allowed to switch channel CommandResult handleCommandPluginCmd(Command&); CommandResult handleCommandClientMute(Command&); CommandResult handleCommandClientUnmute(Command&); //Original from query but still reachable for all CommandResult handleCommandClientList(Command&); CommandResult handleCommandClientFind(Command&); CommandResult handleCommandClientInfo(Command&); CommandResult handleCommandVerifyChannelPassword(Command&); read lock: server channel tree handleCommandChannelFind read lock: server channel tree handleCommandChannelInfo read lock: server channel tree General command handling: client_command_lock Ensure that only one command at time will be handeled Read access server channel tree: read lock channel_tree_lock Write access server channel tree: lock channel_tree_lock Write access client channel tree: read lock channel_tree_lock => lock client channel tree if we write to the server channel tree no client should have their channel tree updated Read access client channel tree: no lock required Note: the server channel tree should not be accessed! Move client acts like access server channel tree: write lock channel_tree_lock => for each client write lock their tree TODO: Some kind of perm channel lock TODO: Fix handleCommandChannelEdit Test: Channel hide & show with clients! Multiple clients as well!