{"id":43029,"date":"2024-04-30T17:07:51","date_gmt":"2024-04-30T21:07:51","guid":{"rendered":"https:\/\/mjtsai.com\/blog\/?p=43029"},"modified":"2024-04-30T17:10:24","modified_gmt":"2024-04-30T21:10:24","slug":"swift-proposal-synchronous-mutual-exclusion-lock","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2024\/04\/30\/swift-proposal-synchronous-mutual-exclusion-lock\/","title":{"rendered":"Swift Proposal: Synchronous Mutual Exclusion Lock"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/main\/proposals\/0433-mutex.md\">SE-0433<\/a>:<\/p>\n<blockquote cite=\"https:\/\/github.com\/apple\/swift-evolution\/blob\/main\/proposals\/0433-mutex.md\">\n<p>Not all code may be able (or want) to adopt actors. Reasons for this can be very varied, for example code may have to execute synchronously without any potential for other tasks interleaving with it. Or the <code>async<\/code> effect introduced on methods may prevent legacy code which cannot use Swift Concurrency from interacting with the protected state.<\/p>\n<p>[&#8230;]<\/p>\n<p>We propose a new type in the Standard Library Synchronization module: <code>Mutex<\/code>. This type will be a wrapper over a platform-specific mutex primitive, along with a user-defined mutable state to protect.<\/p>\n<p>[&#8230;]<\/p>\n<p><code>Mutex<\/code> will be decorated with the <code>@_staticExclusiveOnly<\/code> attribute, meaning you will not be able to declare a variable of type <code>Mutex<\/code> as <code>var<\/code>. These are the same restrictions imposed on the recently accepted <code>Atomic<\/code> and <code>AtomicLazyReference<\/code> types. [&#8230;] We do not want to introduce dynamic exclusivity checking when accessing a value of <code>Mutex<\/code> as a class stored property for instance.<\/p>\n<p>[&#8230;]<\/p>\n<p><code>Mutex<\/code> is unconditionally <code>Sendable<\/code> regardless of the value it's protecting. We can ensure the safetyness of this value due to the <code>transferring<\/code> marked parameters of both the initializer and the closure <code>inout<\/code> argument.<\/p>\n<\/blockquote>\n\n<p>On Apple platforms, this is based on <a href=\"https:\/\/developer.apple.com\/documentation\/os\/os_unfair_lock\">os_unfair_lock<\/a>, which is a bit tricky to <a href=\"https:\/\/stackoverflow.com\/a\/68615042\">directly use from Swift<\/a> because you have to manage the memory for the lock yourself to prevent Swift from moving it. macOS 13 brought <a href=\"https:\/\/developer.apple.com\/documentation\/os\/osallocatedunfairlock\">OSAllocatedUnfairLock<\/a>, which is Apple&rsquo;s implementation that handles this for you. <code>Mutex<\/code> is better still because it <a href=\"https:\/\/discuss.systems\/@steve\/112338588609588184\">doesn&rsquo;t need<\/a> to allocate a separate block of memory for the lock.<\/p>\n\n<p><a href=\"https:\/\/hachyderm.io\/@groue\/112331290728648797\">Gwendal Rou&eacute;<\/a>:<\/p>\n<blockquote cite=\"https:\/\/hachyderm.io\/@groue\/112331290728648797\"><p>My experience with Swift Concurrency might be somewhat particular.<\/p><p>[&#8230;]<\/p><p>And I&rsquo;m not sure I&rsquo;ll replace DispatchQueues with any Swift concurrency constructs any time soon, because a demanding user of SQLite won&rsquo;t accept to be limited to strictly serialized accesses. SQLite supports concurrent database accesses, including parallel reads and writes. Indeed databases support concurrency in a way that is almost never found in any memory-based synchronization primitive: actors, mutexes, read-write locks are all too limited.<\/p><p>Final nail in the coffin: a demanding SQLite user expects to be able to perform synchronous database accesses at will (i.e. when needed) &#x2013; just like the regular C API &#x2013; without any risk of concurrency bugs. There&rsquo;s currently no Swift concurrency construct that allows both sync and async accesses.<\/p><\/blockquote>\n\n<p><a href=\"https:\/\/mastodon.social\/@iKyle\/112327961590246530\">Kyle Howells<\/a>:<\/p>\n<blockquote cite=\"https:\/\/mastodon.social\/@iKyle\/112327961590246530\"><p>I can&rsquo;t help feeling Swift&rsquo;s async, Actor, isolation system is a mistake.<\/p><p>Rather than making the safe thing the default, even if a bit slow, and making a slightly awkward API for a &ldquo;fast mode&rdquo; it makes most code think about async isolation most of the time.<\/p><\/blockquote>\n\n<p>Previously:<\/p>\n<ul>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2024\/03\/27\/noncopyable-generics-walkthrough\/\">Noncopyable Generics Walkthrough<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2023\/03\/22\/swift-atomics-1-1\/\">Swift Atomics 1.1<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2022\/05\/12\/mainactor-not-guaranteed\/\">@MainActor Not Guaranteed<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2019\/02\/05\/swift-5-exclusivity-enforcement\/\">Swift 5 Exclusivity Enforcement<\/a><\/li>\n<li><a href=\"https:\/\/mjtsai.com\/blog\/2016\/10\/07\/os_unfair_lock\/\">os_unfair_lock<\/a><\/li>\n<\/ul>","protected":false},"excerpt":{"rendered":"<p>SE-0433: Not all code may be able (or want) to adopt actors. Reasons for this can be very varied, for example code may have to execute synchronously without any potential for other tasks interleaving with it. Or the async effect introduced on methods may prevent legacy code which cannot use Swift Concurrency from interacting with [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"2024-04-30T21:07:54Z","apple_news_api_id":"590ab528-f004-442a-9487-44e3d32a4d2f","apple_news_api_modified_at":"2024-04-30T21:10:28Z","apple_news_api_revision":"AAAAAAAAAAAAAAAAAAAAAQ==","apple_news_api_share_url":"https:\/\/apple.news\/AWQq1KPAERCqUh0Tj0ypNLw","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[800,1412,46,71,2200,901],"class_list":["post-43029","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-concurrency","tag-grdb","tag-languagedesign","tag-programming","tag-swift-concurrency","tag-swift-programming-language"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/43029","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=43029"}],"version-history":[{"count":3,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/43029\/revisions"}],"predecessor-version":[{"id":43036,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/43029\/revisions\/43036"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=43029"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=43029"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=43029"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}