[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]
