[video output=day325 member=cmuratori stream_platform=twitch stream_username=handmade_hero project=code title="Ticket Mutexes" vod_platform=youtube id=A2kCmouscjM annotator=Miblo annotator=AsafGartner] [0:23][Recap and set the stage for the day] [1:31][Blackboard: Ticket Taking] [4:11][Blackboard: Singly-linked list] [6:45][Blackboard: A way to atomically add to a linked list] [7:44][Blackboard: Removing from a list] [9:36][Blackboard: Multithreaded addition to linked lists] [11:46][Blackboard: Multithreaded removal from linked lists] [13:29][Blackboard: Ticket Taking as a way to implement a fast, simple mutex for little chunks of code] [14:37][Blackboard: Atomic compare exchange[ref site="Maurice Herlihy" page="Wait-Free Synchronization" url="https://cs.brown.edu/~mph/Herlihy91/p124-herlihy.pdf"]] [17:41][Blackboard: Atomic increment] [19:02][Blackboard: Ticket Taking and Mutex (mutual exclusion)] [22:57][Blackboard: volatile int mutex][quote 518] [27:39][Blackboard: Annoyingly, this implementation provides no guarantee that any thread will ever get a turn] [30:04][Blackboard: Ticket Taking as a way to ensure that threads get retired in order] [35:12][handmade_shared.h: Introduce struct ticket_mutex, BeginTicketMutex() and EndTicketMutex()] [39:37][handmade_asset.cpp: Implement AddOp()] [42:49][handmade_platform.h: Introduce and add a platform_texture_op_queue to the game_memory struct for AddOp() to use] [45:48][handmade_asset.cpp: Consider not setting Work->Asset->State in LoadAssetWorkDirectly()] [47:21][handmade_asset.cpp: Continue implementing AddOp()] [49:56][handmade_platform.h: Move the ticket mutex in from handmade_shared.h] [51:23][Consider building separate lists for each threads inside task_with_memory] [52:25][handmade_asset.cpp: Add platform_texture_op_queue to load_asset_work and pass it to the necessary functions] [55:54][Run the game and hit the assertion in AddOp()] [56:12][win32_handmade.cpp: Make WinMain() populate the TextureOps free list] [58:53][handmade_opengl.cpp: Make OpenGLManageTextures() return a texture_op] [59:37][win32_handmade.cpp: Make WinMain() call OpenGLManageTextures() inside a mutex] [1:01:15]["You ALMOST only live once"][quote 519] [1:04:49][Run the game and see that it almost worked] [1:05:06][Q&A][:speech] [1:05:50][handmade_asset.cpp: Note that we haven't dealt with Work->Asset->State] [1:07:07][@dmitsuki][Handmade Vulkan renderer when?] [1:07:21][@ezysigh][Do you need a safety write barrier before the current ticket increment (inside mutex_unlock)?] [1:09:07][@phort99][Do you use an sRGB framebuffer and / or premultiplied alpha?] [1:10:20][win32_handmade.cpp: Remove Win32GetThreadStartupForGL()] [1:11:24][Run the game and note that our texture loading bug is 100% reproducible] [1:12:01][@phort99][Can you explain about the secondary framebuffer not being premultiplied? What's the secondary framebuffer for?] [1:13:05][@caviar_liberta][And it might be pointless to do but, since you are using C++, have you used any ASM calls inside your code?] [1:14:23][@baramordax][Is there a reason you're not using scoped mutex guards that handle unlocking whenever the guard goes out of scope?] [1:14:38][win32_handmade.cpp: Demo the difference between our mutex and a scoped mutax guard] [1:17:48][Wrap it up with a few words on what is likely going wrong with the texture loading][:speech] [/video]