14:52 <+bridge_> [ddnet] Is it saver to call static functions from threads than class methods? 14:53 <+Learath2> No difference, however you can't pass a non-static method as a pointer, so the first is usually more convenient. 14:54 <+bridge_> [ddnet] oh ok thats nice 14:54 <+bridge_> [ddnet] but if i singiggle snuggly my sketchy pointer to a object in my thread i can happily call methods there even if they get executed in other threads as well? 14:55 <+bridge_> [ddnet] only problem is object variables i guess 15:19 <+Learath2> You can't even take a pointer to a member function iirc 15:20 <+Learath2> and it wouldn't even make much sense, you can't call a member function without an object. It's signature actually includes the object as a parameter 15:23 <+bridge_> [ddnet] yy i have a pointer to the obj 15:23 <+Learath2> If you just pass a pointer to the object that's also fine. But threads are pretty dangerous 15:23 <+Learath2> You might want a lock 15:24 <+bridge_> [ddnet] i dont know exactly what a lock is but i have a var that is shared by both threads and tracks state of thread 15:27 <+Learath2> When you modify a variable another thread could be reading that variable and that causes issues. To fix it you can have a lock, that makes sure only one thread is using the variable at a time 15:28 <+bridge_> [ddnet] hmm sounds good 15:28 <+bridge_> [ddnet] but too lazy rn to understand how to use it xd 15:29 <+bridge_> [ddnet] i dont see how my threads could mess something up 15:29 <+bridge_> [ddnet] ikr famous last words 15:29 <+Learath2> Or you can make reads and writes atomic, which fixes a lot of issues but there still might be other timing issues, e.g. memory ordering :/ 15:30 <+bridge_> [ddnet] my main thread sets the state var to running then spawns a thread if not running already and the thread then sets state to done and the main thread checks if its done in the gameloop 15:30 <+bridge_> [ddnet] sounds save to me 15:30 <+bridge_> [ddnet] so i spawn max one thread at a time 15:30 <+bridge_> [ddnet] *additional 15:30 <+bridge_> [ddnet] “Some people, when confronted with a problem, think ‘I know, I’ll use multithreading’. Nothhw tpe yawrve o oblems.” (Eiríkr Åsheim, 2012) 15:31 <+bridge_> [ddnet] xd 15:31 <+bridge_> [ddnet] im sure it will be fine 🙂 15:32 <+bridge_> [ddnet] Well the writes and reads are not atomic, so the thread can set the value halfway, then the other thread can read a trap representation, which invokes undefined behaviour 15:33 <+bridge_> [ddnet] what reads and write you mean? to file? 15:33 <+bridge_> [ddnet] Reading and writing to the variable in the memory 15:33 <+bridge_> [ddnet] oh wait ye i read and write to file at same time ur right its messed up xd 15:33 <+bridge_> [ddnet] but not to variables 15:33 <+bridge_> [ddnet] as far as i know 15:33 <+bridge_> [ddnet] Well even the variable that holds the state isn't safe, CPUs don't write in one cycle 15:34 <+bridge_> [ddnet] uh 15:34 <+bridge_> [ddnet] yikes 15:34 <+bridge_> [ddnet] ok my thread is messed up in all possible ways then 15:34 <+bridge_> [ddnet] teach me locks senpai 15:34 <+bridge_> [ddnet] Is this teeworlds code? 15:34 <+bridge_> [ddnet] yy 15:34 <+bridge_> [ddnet] Why don't you just use engine jobs? 15:34 <+bridge_> [ddnet] looked scary to me 15:34 <+bridge_> [ddnet] @heinrich5991 made them pretty safe iirc 15:34 <+bridge_> [ddnet] i can imagine 15:35 <+bridge_> [ddnet] but harder to understand than the crap i built 15:35 <+bridge_> [ddnet] Well actually idk if 0.7 got heinrichs engine jobs 15:35 <+bridge_> [ddnet] mimimi 15:35 <+bridge_> [ddnet] What are you making? 15:35 <+bridge_> [ddnet] ranking 15:35 <+bridge_> [ddnet] reading files calculating rank 15:36 <+bridge_> [ddnet] but i just realized during the rank calculation other ranks could be saved and then there is read and write to file at the same time which is not too good 15:36 <+bridge_> [ddnet] This is why people use sql for this kind of stuff 😄 15:36 <+bridge_> [ddnet] :/ 15:36 <+bridge_> [ddnet] onbgy doesnt 15:36 <+bridge_> [ddnet] he is my big idol 15:36 <+bridge_> [ddnet] Well I guess you can just do it naively and hope things don't go wrong? 15:37 <+bridge_> [ddnet] uff 15:37 <+bridge_> [ddnet] sounds like a chiller approach 15:37 <+bridge_> [ddnet] but works better when i can still hope my code is not broken 15:37 <+bridge_> [ddnet] You can have a lock for the object you are passing around just to be safe 15:38 <+bridge_> [ddnet] do you have a quick lock snipped 15:38 <+bridge_> [ddnet] LOCK l = lock_create() i g 15:38 <+bridge_> [ddnet] LOCK m_Lock; 15:38 <+bridge_> [ddnet] m_Lock = lock_create(); yep 15:39 <+bridge_> [ddnet] Then in the gameloop you only ever lock_trylock(obj.m_Lock); 15:39 <+bridge_> [ddnet] If trylock returns true that means you have the lock, and you can touch the contents of obj safely 15:39 <+bridge_> [ddnet] else just go on, it'll probably free up in a couple gameloops 15:40 <+bridge_> [ddnet] in the other thread whenever you need to touch the contents of the obj, you first do lock_wait 15:40 <+bridge_> [ddnet] which will wait until the lock is available to you 15:40 <+bridge_> [ddnet] after you get the lock you can do things with the object 15:40 <+bridge_> [ddnet] after you are done touching the object always lock_unlock 15:41 <+bridge_> [ddnet] that's all, locks are simple synchronisation primitives 15:41 <+bridge_> [ddnet] does it matter where the lock is? 15:41 <+bridge_> [ddnet] like on what object or somethin? 15:41 <+bridge_> [ddnet] Make it a member of the object 15:41 <+bridge_> [ddnet] or is it just a state i have to use consitently for what ever i want? 15:42 <+bridge_> [ddnet] The object you are "locking" that is 15:42 <+bridge_> [ddnet] so my poiter to GameServer? 15:42 <+bridge_> [ddnet] Wait you are locking the gameserver? 😄 15:42 <+bridge_> [ddnet] and then make the lock member of CGameContext 15:42 <+bridge_> [ddnet] No no no no, that's very illegal 15:42 <+bridge_> [ddnet] :/ 15:42 <+bridge_> [ddnet] xd 15:42 <+bridge_> [ddnet] well my thread state var is a member of CGameContext 15:42 <+bridge_> [ddnet] thought thats fine 15:42 <+bridge_> [ddnet] I see what you are doing, there is no safe way to do it 15:43 <+bridge_> [ddnet] Atleast not without major work on the code that I stopped doing a couple weeks ago because nomotivation 15:43 <+bridge_> [ddnet] The proper solution to this is to have a "job queue" for the gameserver so that we can safely signal the gameserver to do things from within a thread 15:44 <+bridge_> [ddnet] @ChillerDragon you can for now, just make your state variable atomic 15:44 <+bridge_> [ddnet] this sounds like work do you think its even worth the effort if i get problems with two threads reading and writing to files at the same time anyways? 15:45 <+bridge_> [ddnet] sounds like i need a job queue for file io 15:45 <+bridge_> [ddnet] @ChillerDragon reading and writing to the same file without synchronisation is a lot of trouble 15:45 <+bridge_> [ddnet] y 15:45 <+bridge_> [ddnet] The usual idea is to create a lockfile 15:45 <+bridge_> [ddnet] whats that 15:45 <+bridge_> [ddnet] a actual file? 15:45 <+bridge_> [ddnet] If you are using the file test.txt for example 15:45 <+bridge_> [ddnet] You create the file test.txt.lck 15:45 <+bridge_> [ddnet] ah i see 15:46 <+bridge_> [ddnet] And whenever you want to use test.txt, you first check whether a .lck file exists 15:46 <+bridge_> [ddnet] yy 15:46 <+bridge_> [ddnet] if it does you have to wait 15:46 <+bridge_> [ddnet] implementing wait alone sounds like a struggle 15:46 <+bridge_> [ddnet] It's quite simple 15:46 <+bridge_> [ddnet] ye? 15:47 <+bridge_> [ddnet] In your thread loop you check whether the file exists 15:47 <+bridge_> [ddnet] sounds like many things can go wrong 15:47 <+bridge_> [ddnet] if it doesn't just sleep a while 15:47 <+bridge_> [ddnet] well so i need a thread loop 15:47 <+bridge_> [ddnet] for every file io 15:47 <+bridge_> [ddnet] Well it's probably more performant then spawning a new thread the next gameloop if the file is not available 15:49 <+bridge_> [ddnet] or i dont wait 15:50 <+bridge_> [ddnet] if i read a file from two threads at the same time is that save? 15:50 <+bridge_> [ddnet] You could maybe get fancy with creating a hashtable of semaphores that get triggered when a modifying thread quits and is removed if there are 0 threads for a file left 15:50 <+bridge_> [ddnet] @ChillerDragon no 15:50 <+bridge_> [ddnet] so in main thread where i have to write and do important stuff like saving i create lock files and from the rank thread i just abort if lock file exist and done 15:50 <+bridge_> [ddnet] so /rank doesnt work when a file is currently updated 15:51 <+bridge_> [ddnet] np 15:51 <+bridge_> [ddnet] i rly dont wanna get fancy 15:51 <+bridge_> [ddnet] Well the reading is probably safe, but there is no guarantee that the things read will be the same 15:51 <+bridge_> [ddnet] wot? 15:52 <+bridge_> [ddnet] what do you mean by the same? Do you mean somehow altered values by magic or simply old values not updated yet? 15:53 <+bridge_> [ddnet] This is all a bit complicated, when two threads read the same file, it is usually safe 15:53 <+bridge_> [ddnet] ok sounds good to me 15:53 <+bridge_> [ddnet] but if the file is opened non exclusively and a write happens inbetween the reads, the second read might read a half modified file, or a fully modified file, or a non modified file, it all depends on how the write is scheduled by the OS 15:54 <+bridge_> [ddnet] @ChillerDragon yeah what you proposed works, as long as /rank doesn't work if there is a lockfile it's fine 15:54 <+bridge_> [ddnet] yy 15:54 <+bridge_> [ddnet] sounds like fine ux to me 15:54 <+bridge_> [ddnet] And as long as you never have a thread write to the rankfile without creating the lockfile 15:55 <+bridge_> [ddnet] get a error in the rare case while typing /rank and just redo it 15:55 <+bridge_> [ddnet] ok any good conventions for lock files? Anything in tw code already to create and check for lockfiles? 15:56 <+bridge_> [ddnet] is ther something in place for settings? 15:56 <+bridge_> [ddnet] or should i just use first lockfile answer from stackoverflow 15:57 <+bridge_> [ddnet] Doesn't really matter 15:58 <+bridge_> [ddnet] We don't have lockfiles in tw code 15:58 <+bridge_> [ddnet] so the io_write etc code is not very safe? 15:58 <+bridge_> [ddnet] when closing two tw clients at the same time my settings might get messed up? 15:58 <+bridge_> [ddnet] Yes if you are very unlucky and not on windows 15:58 <+bridge_> [ddnet] y just saw that 15:59 <+bridge_> [ddnet] windows seems to be save 15:59 <+bridge_> [ddnet] windows enforces exclusivity 15:59 <+bridge_> [ddnet] sounds like a issue to me tbg 15:59 <+bridge_> [ddnet] tbh* 15:59 <+bridge_> [ddnet] on POSIX you can get the same behaviour with flock iirc 15:59 <+bridge_> [ddnet] mby we should implement that 15:59 <+bridge_> [ddnet] loosing settings can be tragic 16:00 <+bridge_> [ddnet] cant belive that windows is superior in this case 16:01 <+bridge_> [ddnet] ima buy a windows vps now 😄 16:01 <+bridge_> [ddnet] "superior" 16:01 <+bridge_> [ddnet] wait but what does windows do then? 16:01 <+bridge_> [ddnet] just fail? 16:01 <+bridge_> [ddnet] It also commonly breaks software 16:02 <+bridge_> [ddnet] Yeah fopen fails 22:01 <+bridge_> [ddnet] no way that made it to teh start page xd 23:24 <+bridge_> [ddnet] @Learath2 https://www.youtube.com/watch?v=lR0nh-TdpVg 23:24 <+bridge_> [ddnet] rip 23:46 <+bridge_> [ddnet] Again @heinrich5991 23:46 <+bridge_> [ddnet] Is this becoming a memes 23:47 <+bridge_> [ddnet] Or do I have trouble distinguishing talks by this guy 23:47 <+bridge_> [ddnet] again? 23:47 <+bridge_> [ddnet] the latter 23:47 <+bridge_> [ddnet] Idk 23:47 <+bridge_> [ddnet] K