{"id":56740,"date":"2023-02-13T10:20:46","date_gmt":"2023-02-13T04:50:46","guid":{"rendered":"https:\/\/www.tothenew.com\/blog\/?p=56740"},"modified":"2023-02-13T10:20:46","modified_gmt":"2023-02-13T04:50:46","slug":"concurrency-with-swift-structured-concurrency","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/concurrency-with-swift-structured-concurrency\/","title":{"rendered":"Concurrency with swift: Structured concurrency"},"content":{"rendered":"<h5><i><span style=\"font-weight: 400;\">This is part 2 of the article series on <\/span><\/i><b><i>Concurrency with Swift. <\/i><\/b><i><span style=\"font-weight: 400;\">The article\u2019s content assumes that the reader understands the <\/span><\/i><b><i>Async\/Await <\/i><\/b><i><span style=\"font-weight: 400;\">concept.<\/p>\n<p>If you are unfamiliar with the Async\/Await concept, please read the first part: <\/span><\/i><a href=\"https:\/\/www.tothenew.com\/blog\/concurrency-with-swift-async-await\/\"><b><i>Concurrency with Swift: Async\/Await<\/i><\/b><\/a><i><span style=\"font-weight: 400;\">.<\/span><\/i><\/h5>\n<p><span style=\"font-weight: 400;\">Before we learn Structured Concurrency<\/span><i><span style=\"font-weight: 400;\">,<\/span><\/i><span style=\"font-weight: 400;\"> it is essential to understand Structured Programming. And, if you are here after reading the first part you are already a step closer to understanding Structured Concurrency.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We have already been doing concurrent programming for a long time. <\/span><span style=\"font-weight: 400;\">For example, if we want to implement an asynchronous task we do it by implementing a function with the closure parameters. When this async function is called the flow will continue after the function call. Once the async task is done, it will call closure in the form of a completion block. So in this case the program flow and closure completion flow was called at different times which is missing the sequential structured flow(Programming) and hence the <\/span><b>Structured Concurrency<\/b><span style=\"font-weight: 400;\">.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">But if we choose <\/span><b>Async\/Await<\/b><span style=\"font-weight: 400;\"> to implement an asynchronous function we follow the program from top to bottom attaining Structured Programming and thus opening doors to implement multiple tasks in parallel thereby following structural control flow and implementing Structured Concurrency together.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">So, <\/span><b>Structured concurrency<\/b><span style=\"font-weight: 400;\"> provides a paradigm for spawning concurrent <\/span><b><i>child tasks<\/i><\/b> <span style=\"font-weight: 400;\">in a well-defined hierarchy of tasks that allows for cancellation, error propagation, priority management, and other tricky details of concurrency management to be handled transparently.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In the <\/span><a href=\"https:\/\/www.tothenew.com\/blog\/concurrency-with-swift-async-await\/\"><span style=\"font-weight: 400;\">first part<\/span><\/a><span style=\"font-weight: 400;\">, I stated that <\/span><b>Structured Concurrency<\/b><span style=\"font-weight: 400;\"> has three major features: <\/span><b>Unstructured<\/b> <b>Tasks, async-let, <\/b><span style=\"font-weight: 400;\">and<\/span><b> Task Group. <\/b><span style=\"font-weight: 400;\">There we discussed Tasks very briefly but don\u2019t worry we\u2019ll talk about <\/span><b>Unstructured Tasks<\/b><span style=\"font-weight: 400;\"> in much more detail later.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For now, just remember\u00a0<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Tasks provide a fresh context to run asynchronous code.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Tasks are concurrent with respect to other execution contexts.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Tasks are deeply integrated and start immediately.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Let us discuss the simplest of these &#8211;\u00a0<\/span><\/p>\n<h3><b>async-let Task:<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">async-let binding is also known as <\/span><b>concurrent binding<\/b><span style=\"font-weight: 400;\"> which is generally used in a situation where the result of a task is not required until later in the program. This creates work that can be carried out in parallel.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Let us understand with an example:<\/span><\/p>\n<p><span style=\"font-weight: 400;\">For convenience, we are taking an example of a Dice game with all hard code values and rules to quickly demonstrate the concepts. <\/span><\/p>\n<h5 style=\"text-align: left;\"><i><span style=\"font-weight: 400;\">A major assumption is that getting a dice result is a time-consuming operation.<\/span><\/i><\/h5>\n<h5 style=\"text-align: left;\"><i><span style=\"font-weight: 400;\">Rule of the game (business requirement):<\/span><\/i> <i><span style=\"font-weight: 400;\">The player opted to use two dice but with a catch that there is a max value for the sum of the dice number. If the sum of two dice is greater than the max it will throw the error<\/span><\/i><span style=\"font-weight: 400;\">.<\/span><\/h5>\n<p><span style=\"font-weight: 400;\">Check this function using async\/await for getting the dice throw.<\/span><\/p>\n<div id=\"attachment_56714\" style=\"width: 1210px\" class=\"wp-caption aligncenter\"><a href=\"https:\/\/github.com\/ankittlp\/SwiftConcurrency\/tree\/main\/SwiftConcurrencyDemo\"><img aria-describedby=\"caption-attachment-56714\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-56714\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValues2.png\" alt=\"\" width=\"1200\" height=\"448\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValues2.png 1200w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValues2-300x112.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValues2-1024x382.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValues2-768x287.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValues2-624x233.png 624w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/a><p id=\"caption-attachment-56714\" class=\"wp-caption-text\"><a href=\"https:\/\/github.com\/ankittlp\/SwiftConcurrency\/tree\/main\/SwiftConcurrencyDemo\"><span style=\"font-weight: 400;\">Download as Xcode Project<\/span><\/a><\/p><\/div>\n<p><span style=\"font-weight: 400;\">This is a better way than using GCD\/Operations as we get the support of inbuilt error propagation, no more missing completion, and a top-to-the-bottom structured flow of the program.<\/span><\/p>\n<div id=\"attachment_56715\" style=\"width: 1428px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56715\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-56715\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValuesResult.png\" alt=\"\" width=\"1418\" height=\"208\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValuesResult.png 1418w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValuesResult-300x44.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValuesResult-1024x150.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValuesResult-768x113.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/sequentialDiceValuesResult-624x92.png 624w\" sizes=\"(max-width: 1418px) 100vw, 1418px\" \/><p id=\"caption-attachment-56715\" class=\"wp-caption-text\">Result of SequentialDiceValue function call &#8211; it took around 4-sec to return value.<\/p><\/div>\n<p><span style=\"font-weight: 400;\">This approach has an important drawback: Although the Int.random is asynchronous and lets other work happen while it progresses, only one call to <\/span><span style=\"font-weight: 400;\">Int.random<\/span><span style=\"font-weight: 400;\"> runs at a time. Each dice value is realised completely before the next one starts the task. However, there\u2019s no need for these operations to wait\u2014each dice can get the value independently, or even at the same time. So here we have missed the concurrent factor big time.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">So, how to achieve concurrency?<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In Swift, we have two ways to work with structured concurrency:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">async-let<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Task groups<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">The simplest solution is <\/span><b>async-let.<\/b><\/p>\n<p><span style=\"font-weight: 400;\">The following code demonstrates how to apply <\/span><b>async-let<\/b><span style=\"font-weight: 400;\"> binding to our previous example:<\/span><\/p>\n<p style=\"text-align: center;\"><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-full wp-image-56716\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue.png\" alt=\"\" width=\"2180\" height=\"718\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue.png 2180w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue-300x99.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue-1024x337.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue-768x253.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue-1536x506.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue-2048x675.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValue-624x206.png 624w\" sizes=\"(max-width: 2180px) 100vw, 2180px\" \/><a href=\"https:\/\/github.com\/ankittlp\/SwiftConcurrency\/tree\/main\/SwiftConcurrencyDemo\"><span style=\"font-weight: 400;\">Download as Xcode Project<\/span><\/a><\/p>\n<p><b>async-let<\/b><span style=\"font-weight: 400;\"> is the best fit required to refactor our <\/span><em><span style=\"font-weight: 400;\">func sequentialDiceValues<\/span><\/em><span style=\"font-weight: 400;\">. Here we<\/span><span style=\"font-weight: 400;\"> annotated the <\/span><em><span style=\"font-weight: 400;\">firstDice<\/span><\/em><span style=\"font-weight: 400;\"> and <\/span><em><span style=\"font-weight: 400;\">secondDice<\/span><\/em><span style=\"font-weight: 400;\"> with the <\/span><b>async-let<\/b><span style=\"font-weight: 400;\"> keyword, the program flow will not block and continue to call <\/span><em><span style=\"font-weight: 400;\">Int.random<\/span><\/em><span style=\"font-weight: 400;\"> async properties in parallel. At the end where we are waiting for the result from the async task, we will get blocked until results from <\/span><em><span style=\"font-weight: 400;\">firstDice<\/span><\/em><span style=\"font-weight: 400;\"> and <\/span><em><span style=\"font-weight: 400;\">secondDice<\/span> <span style=\"font-weight: 400;\">Int.random<\/span><\/em><span style=\"font-weight: 400;\"> async calls are received or any of them raises an exception as indicated by the try keyword.<\/span><\/p>\n<div id=\"attachment_56717\" style=\"width: 2252px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56717\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-56717\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult.png\" alt=\"\" width=\"2242\" height=\"254\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult.png 2242w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult-300x34.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult-1024x116.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult-768x87.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult-1536x174.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult-2048x232.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueResult-624x71.png 624w\" sizes=\"(max-width: 2242px) 100vw, 2242px\" \/><p id=\"caption-attachment-56717\" class=\"wp-caption-text\">Result of parallerDiceValues function call &#8211; it took around 5 sec to return value.<\/p><\/div>\n<p><span style=\"font-weight: 400;\">That was all it took us to write a Structured Control-Flow Concurrent function but have we achieved Structured Concurrency?<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Yes! We hit that.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">With <\/span><b>async-let<\/b><span style=\"font-weight: 400;\">, we ran two tasks concurrently until results are awaited and these async-let child tasks are structured too.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Let\u2019s understand how.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">As mentioned earlier, <\/span><b>async-let<\/b><span style=\"font-weight: 400;\"> is also called <\/span><b>Concurrent binding<\/b><span style=\"font-weight: 400;\">. It is similar to <\/span><strong>let<\/strong><span style=\"font-weight: 400;\"> constant<strong> sequential binding<\/strong> where the expression on the right side of <\/span><b>=<\/b><span style=\"font-weight: 400;\"> is evaluated and the let constant is initialised.\u00a0 However, the difference is that the initialiser expression is evaluated in a separate <\/span><b>concurrently-executing child task<\/b><span style=\"font-weight: 400;\">.<\/span><\/p>\n<div id=\"attachment_56718\" style=\"width: 1546px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56718\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-56718\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/IMG_0219.png\" alt=\"\" width=\"1536\" height=\"1360\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/IMG_0219.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/IMG_0219-300x266.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/IMG_0219-1024x907.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/IMG_0219-768x680.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/IMG_0219-624x553.png 624w\" sizes=\"(max-width: 1536px) 100vw, 1536px\" \/><p id=\"caption-attachment-56718\" class=\"wp-caption-text\">Concurrent binding<\/p><\/div>\n<p><span style=\"font-weight: 400;\">As soon as swift sees an <\/span><span style=\"font-weight: 400;\"><strong>async-let<\/strong>,<\/span><span style=\"font-weight: 400;\"> a new Swift Concurrency task is spawned behind the scene. This task will run as a child of the task that&#8217;s currently running. And will start running immediately. On normal completion, the child task will initialise the variables in the <\/span><strong>async-let <\/strong><span style=\"font-weight: 400;\">and we must use <\/span><strong>await<\/strong><span style=\"font-weight: 400;\"> whenever we want to use the <\/span><strong>async-let<\/strong><span style=\"font-weight: 400;\"> task&#8217;s value.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Though it is completely legal to not await the child task if we don\u2019t care about the task result. But we should not be practicing this as child tasks are scoped to the context they are defined. As soon as the scope ends these child tasks will be implicitly marked cancelled which means that we should stop performing any work on the child task to respect the <\/span><b>Swift<\/b>\u00a0<b>Concurrency\u2019s cooperative cancellation<\/b><span style=\"font-weight: 400;\">.<\/span><\/p>\n<div id=\"attachment_56719\" style=\"width: 716px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56719\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-56719\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/Async-let-but-no-await.png\" alt=\"\" width=\"706\" height=\"150\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/Async-let-but-no-await.png 706w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/Async-let-but-no-await-300x64.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/Async-let-but-no-await-624x133.png 624w\" sizes=\"(max-width: 706px) 100vw, 706px\" \/><p id=\"caption-attachment-56719\" class=\"wp-caption-text\">Async-let without await (Don\u2019t try this in the project ?)<\/p><\/div>\n<p><b>\u201cCooperative Cancellation\u201d, <\/b><span style=\"font-weight: 400;\">is one aspect of <\/span><b>Structured Concurrency<\/b><span style=\"font-weight: 400;\"> which makes use of a concept called <\/span><b>The<\/b> <b>Task Tree.<\/b><\/p>\n<p><b>The Task Tree:<\/b><\/p>\n<div id=\"attachment_56724\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56724\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56724\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/Untitled-879x1024.png\" alt=\"\" width=\"625\" height=\"728\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/Untitled-879x1024.png 879w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/Untitled-257x300.png 257w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/Untitled-768x895.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/Untitled-1318x1536.png 1318w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/Untitled-624x727.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/Untitled.png 1458w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56724\" class=\"wp-caption-text\">Task Tree<\/p><\/div>\n<ul>\n<li><span style=\"font-weight: 400;\">The task tree is a hierarchy that our structured concurrency code runs on. It influences the attribute of tasks like cancellation, priority, and task local variables.\u00a0<\/span><\/li>\n<li><span style=\"font-weight: 400;\">A child task will always inherit the same priority and will run on the same actor the parent task is running on.<\/span><\/li>\n<li><span style=\"font-weight: 400;\">Tasks are not the child of a specific function, but their life may be scoped to it (we saw the example earlier)<br \/>\n<\/span><\/li>\n<li><span style=\"font-weight: 400;\">A task <\/span><b>parent-child link<\/b><span style=\"font-weight: 400;\"> enforces a rule that says a parent task can only finish its work if all of its child tasks have finished.<\/span>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">We can see this happening in the <\/span><em><span style=\"font-weight: 400;\">func parallerDiceValues <\/span><\/em><span style=\"font-weight: 400;\">where await is the point of suspension blocking the flow until both concurrent tasks return either successfully or with error.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">When both child tasks finish successfully, <\/span><em><span style=\"font-weight: 400;\">parallerDiceValues <\/span><\/em><span style=\"font-weight: 400;\">return with value after the await with max time to that of one of the child tasks with higher wait time.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">But if One of them errors out causing the parent, which was try awaiting on it, to throw an error: the <\/span><b>tree<\/b><span style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"> is responsible to cancel other child tasks and then await for them to finish before the parent task function can exit\/throw.<\/span><\/span>\n<p><div id=\"attachment_56725\" style=\"width: 610px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56725\" decoding=\"async\" loading=\"lazy\" class=\"size-full wp-image-56725\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskCancellationWithCancelCheck.gif\" alt=\"\" width=\"600\" height=\"96\" \/><p id=\"caption-attachment-56725\" class=\"wp-caption-text\"><em>parallerDiceValues<\/em> logs show that when one child is cancelled the other task in flight was marked canceled but it does not stop as we haven\u2019t done the manual <em>task.checkCancellation<\/em><\/p><\/div><\/li>\n<li style=\"font-weight: 400;\">Marking a task cancelled will not stop the task. It simply informs the task that its results are no longer needed because <b>Cancellation is cooperative<\/b><\/li>\n<li style=\"font-weight: 400;\">All the child tasks and their descendants will be cancelled when their parent is cancelled because the tree is formed by <b>Structured Tasks<\/b>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><b>Cancellation is Cooperative:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">We talked about how cancellation is cooperative in the swift task tree but still didn\u2019t see how to stop the task marked cancelled.<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Check the task cancellation explicitly using <\/span><span style=\"font-weight: 400;\"><em>try<\/em> <em>Task.checkCancellation() <\/em><\/span><span style=\"font-weight: 400;\">or <\/span><em><span style=\"font-weight: 400;\">Task.isCancelled<\/span><\/em><span style=\"font-weight: 400;\"> to throw a cancellation error or partial return in the appropriate context.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">We should design our task with cancellation in mind aiming to stop the task as soon as possible.<\/span><\/li>\n<\/ul>\n<div id=\"attachment_56726\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56726\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56726\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/CooperativeCancelationWithCancellationCheck-1024x749.png\" alt=\"\" width=\"625\" height=\"457\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/CooperativeCancelationWithCancellationCheck-1024x749.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CooperativeCancelationWithCancellationCheck-300x219.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CooperativeCancelationWithCancellationCheck-768x562.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CooperativeCancelationWithCancellationCheck-1536x1124.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CooperativeCancelationWithCancellationCheck-624x456.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CooperativeCancelationWithCancellationCheck.png 1862w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56726\" class=\"wp-caption-text\">Here we are checking the task cancellation at the appropriate time. <a href=\"https:\/\/github.com\/ankittlp\/SwiftConcurrency\/tree\/main\/SwiftConcurrencyDemo\"><span style=\"font-weight: 400;\">Download as Xcode Project<\/span><\/a><\/p><\/div>\n<p><span style=\"font-weight: 400;\">With This in place, our call to <\/span><em><span style=\"font-weight: 400;\">func<\/span> <span style=\"font-weight: 400;\">parallerDiceValues <\/span><\/em><span style=\"font-weight: 400;\">will stop the child tasks if any task errors and respectively the parent task.<\/span><\/p>\n<p><img decoding=\"async\" loading=\"lazy\" class=\"aligncenter size-large wp-image-56727\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueCancellationCheckResult-1024x90.png\" alt=\"\" width=\"625\" height=\"55\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueCancellationCheckResult-1024x90.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueCancellationCheckResult-300x26.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueCancellationCheckResult-768x67.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueCancellationCheckResult-1536x134.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueCancellationCheckResult-2048x179.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/ParallelDiceValueCancellationCheckResult-624x55.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><\/p>\n<p><span style=\"font-weight: 400;\">These logs clearly show that one child task failed and it throws an error while another child task is waiting at the suspension point and is in flight. But after the suspension\u00a0 point, we again check for the task cancellation. This makes the task finish the task with a cancellation error (It can be very handy in many cases).<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To Summarize the <\/span><b>async-let:<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">It is a <\/span><b>structured<\/b> <b>task<\/b><span style=\"font-weight: 400;\">.<\/span><\/li>\n<li style=\"font-weight: 400;\"><b>async-let<\/b><span style=\"font-weight: 400;\"> should be always awaited for results later in the program flow and should not use as a means to run code asynchronously after the function is exited.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Use it for concurrent async work where results can be deferred to a later time.\u00a0<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Can be used for scenarios where a <strong>finite length of concurrency<\/strong> is required.<\/span><\/li>\n<li style=\"font-weight: 400;\">We can not use <b>async-var<\/b> because a variable can change but <b>async-let<\/b> is initialised by concurrent binding.<\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">Another feature of structured concurrency is <strong>TaskGroup<\/strong> and we\u2019ll talk about TaskGroup in the next article on Structured Concurrency.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">But before we wrap up let\u2019s understand<\/span><b> Unstructured Concurrency.<\/b><\/p>\n<h3><b>Unstructured Task:<\/b><\/h3>\n<p><span style=\"font-weight: 400;\">A <\/span><b>Task<\/b><span style=\"font-weight: 400;\"> with no parent is an unstructured task that is required to bridge between the synchronous and asynchronous context.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">There are some situations in which you will feel the need to use unstructured concurrency:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Launch task from the asynchronous context.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Start a <\/span><b>detached task<\/b><span style=\"font-weight: 400;\"> to avoid inheriting the parent task traits.<\/span><\/li>\n<\/ul>\n<p><b>How to launch a Task?<\/b><\/p>\n<p><span style=\"font-weight: 400;\">We have done this before when we call any asynchronous function from a synchronous context. Check out the <\/span><a href=\"https:\/\/www.tothenew.com\/blog\/concurrency-with-swift-async-await\/\"><span style=\"font-weight: 400;\">async-await<\/span><\/a><span style=\"font-weight: 400;\"> article for more information about bridging between the contexts.<\/span><\/p>\n<div id=\"attachment_56732\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56732\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56732\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFunc-1024x51.png\" alt=\"\" width=\"625\" height=\"31\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFunc-1024x51.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFunc-300x15.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFunc-768x38.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFunc-1536x77.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFunc-2048x102.png 2048w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFunc-624x31.png 624w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56732\" class=\"wp-caption-text\">Error: Calling from a synchronous context<\/p><\/div>\n<div id=\"attachment_56731\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56731\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56731\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFuncFromTask-1024x93.png\" alt=\"\" width=\"625\" height=\"57\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFuncFromTask-1024x93.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFuncFromTask-300x27.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFuncFromTask-768x70.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFuncFromTask-624x57.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/CallToAsyncFuncFromTask.png 1300w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56731\" class=\"wp-caption-text\">Task creates a bridge between the contexts.<\/p><\/div>\n<p><span style=\"font-weight: 400;\">In the above example, we saw how to create the task, It is to mind that as soon a task is encountered it starts immediately.<\/span><\/p>\n<p><b>Tasks are independent and can run in parallel:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">We can run multiple tasks in parallel, consider the following example here we are running two unrelated tasks in parallel.<\/span><\/p>\n<div id=\"attachment_56733\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56733\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56733\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/UnstructuredParallelTask-1024x248.png\" alt=\"\" width=\"625\" height=\"151\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/UnstructuredParallelTask-1024x248.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/UnstructuredParallelTask-300x73.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/UnstructuredParallelTask-768x186.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/UnstructuredParallelTask-624x151.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/UnstructuredParallelTask.png 1430w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56733\" class=\"wp-caption-text\">Unstructured Parallel Task. <a href=\"https:\/\/github.com\/ankittlp\/SwiftConcurrency\/tree\/main\/SwiftConcurrencyDemo\"><span style=\"font-weight: 400;\">Download as the Xcode Project<\/span><\/a><\/p><\/div>\n<p>&nbsp;<\/p>\n<div id=\"attachment_56734\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56734\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56734\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelUnstructuredResult-Complete-1024x455.png\" alt=\"\" width=\"625\" height=\"278\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelUnstructuredResult-Complete-1024x455.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelUnstructuredResult-Complete-300x133.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelUnstructuredResult-Complete-768x342.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelUnstructuredResult-Complete-624x278.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelUnstructuredResult-Complete.png 1268w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56734\" class=\"wp-caption-text\">Unstructured Task In Parallel Result<\/p><\/div>\n<p><span style=\"font-weight: 400;\">These tasks run in parallel and are concurrent to each other as well as to other synchronous functions but are <\/span><b>unstructured <\/b><span style=\"font-weight: 400;\">compared to async-let tasks. As in the above example the first task is set to throw an error (custom reserved number error) but the other tasks keep running to the end as in result. Whereas in structured concurrency a task tree is formed which dictates the structured behaviour.<\/span><\/p>\n<div id=\"attachment_56735\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56735\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56735\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/StructuredParallelTask-1024x161.png\" alt=\"\" width=\"625\" height=\"98\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/StructuredParallelTask-1024x161.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/StructuredParallelTask-300x47.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/StructuredParallelTask-768x121.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/StructuredParallelTask-624x98.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/StructuredParallelTask.png 1484w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56735\" class=\"wp-caption-text\">Structured Parallel task<\/p><\/div>\n<div id=\"attachment_56736\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56736\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56736\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelStructuredREsult-1024x315.png\" alt=\"\" width=\"625\" height=\"192\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelStructuredREsult-1024x315.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelStructuredREsult-300x92.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelStructuredREsult-768x236.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelStructuredREsult-1536x472.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelStructuredREsult-624x192.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/TaskInParallelStructuredREsult.png 1840w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56736\" class=\"wp-caption-text\"><span style=\"font-weight: 400;\">The first task errored out causing the other task to be marked cancelled. <\/span><\/p><\/div>\n<p><b>Cancel a Task:<\/b><\/p>\n<p><span style=\"font-weight: 400;\">Cancellation is cooperative in structured concurrency whereas cancellation is manual for an unstructured task.<\/span><\/p>\n<pre><span style=\"font-weight: 400;\">someTask.cancel()\r\n\r\n<\/span><\/pre>\n<p><span style=\"font-weight: 400;\">It will mark the task cancelled but will not stop the task. We will have to check the task cancellation using <\/span><em><span style=\"font-weight: 400;\">try Task.checkCancellation() <\/span><\/em><span style=\"font-weight: 400;\">or<\/span><em><span style=\"font-weight: 400;\"> Task.isCancelled <\/span><\/em><span style=\"font-weight: 400;\">bool check followed by throwing an error.<\/span><\/p>\n<p><b>Other important characteristics of an unstructured task:<\/b><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Inherit actor isolation and priority of the origin context.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Lifetime is not confined to any scope (can be stored for future reference).<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Can be launched anywhere, even non-async functions.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">Must be manually cancelled or awaited (No tree).<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">We saw all these characteristics in the above example. But interestingly if anyone has noticed that at the call site of <\/span><em><span style=\"font-weight: 400;\">runTwoParallelTasks <\/span><\/em><span style=\"font-weight: 400;\">after the <\/span><b>await<\/b><span style=\"font-weight: 400;\"> the print statement is executed on the main thread.<\/span><\/p>\n<div id=\"attachment_56737\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56737\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56737\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnMainThread-NormalTask-1024x148.png\" alt=\"\" width=\"625\" height=\"90\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnMainThread-NormalTask-1024x148.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnMainThread-NormalTask-300x43.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnMainThread-NormalTask-768x111.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnMainThread-NormalTask-1536x222.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnMainThread-NormalTask-624x90.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnMainThread-NormalTask.png 1714w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56737\" class=\"wp-caption-text\">Unstructured task inherits @MainActor<\/p><\/div>\n<p><span style=\"font-weight: 400;\">It is because as stated Tasks inherit the traits from the originating context. So the task which calls the <\/span><span style=\"font-weight: 400;\">runTwoParallelTasks <\/span><span style=\"font-weight: 400;\">inherits the @MainActor trait.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To avoid this behavior we may make use of <\/span><b>DetachedTask<\/b><span style=\"font-weight: 400;\"> to call the <\/span><span style=\"font-weight: 400;\">runTwoParallelTasks <\/span><span style=\"font-weight: 400;\">function.<\/span><\/p>\n<div id=\"attachment_56738\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56738\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56738\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/DetachedTask-1024x182.png\" alt=\"\" width=\"625\" height=\"111\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/DetachedTask-1024x182.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/DetachedTask-300x53.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/DetachedTask-768x137.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/DetachedTask-624x111.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/DetachedTask.png 1248w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56738\" class=\"wp-caption-text\">A Detached Task. <a href=\"https:\/\/github.com\/ankittlp\/SwiftConcurrency\/tree\/main\/SwiftConcurrencyDemo\"><span style=\"font-weight: 400;\">Download as Xcode Project<\/span><\/a><\/p><\/div>\n<div id=\"attachment_56739\" style=\"width: 635px\" class=\"wp-caption aligncenter\"><img aria-describedby=\"caption-attachment-56739\" decoding=\"async\" loading=\"lazy\" class=\"size-large wp-image-56739\" src=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnOtherThread-DetachedTask-1024x24.png\" alt=\"\" width=\"625\" height=\"15\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnOtherThread-DetachedTask-1024x24.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnOtherThread-DetachedTask-300x7.png 300w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnOtherThread-DetachedTask-768x18.png 768w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnOtherThread-DetachedTask-1536x36.png 1536w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnOtherThread-DetachedTask-624x14.png 624w, \/blog\/wp-ttn-blog\/uploads\/2023\/02\/PrintOnOtherThread-DetachedTask.png 1640w\" sizes=\"(max-width: 625px) 100vw, 625px\" \/><p id=\"caption-attachment-56739\" class=\"wp-caption-text\">A Detached task did not inherit @MainActor.<\/p><\/div>\n<p><span style=\"font-weight: 400;\">For more information about managing detached tasks, see <\/span><a href=\"https:\/\/developer.apple.com\/documentation\/swift\/task\"><span style=\"font-weight: 400;\">Task<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">In the final word, it is suggested to stick around with <\/span><b>Structured concurrency<\/b><span style=\"font-weight: 400;\"> but if required switch to or mix <\/span><b>Unstructured Tasks<\/b><span style=\"font-weight: 400;\"> (Normal &amp; Detached) to attain flexibility.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">We\u2019ll talk about the <\/span><b>Tasks Group<\/b><span style=\"font-weight: 400;\"> in the next part!!\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Stay tuned.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">Happy Coding.<\/span><\/p>\n<div class=\"ap-custom-wrapper\"><\/div><!--ap-custom-wrapper-->","protected":false},"excerpt":{"rendered":"<p>This is part 2 of the article series on Concurrency with Swift. The article\u2019s content assumes that the reader understands the Async\/Await concept. If you are unfamiliar with the Async\/Await concept, please read the first part: Concurrency with Swift: Async\/Await. Before we learn Structured Concurrency, it is essential to understand Structured Programming. And, if you [&hellip;]<\/p>\n","protected":false},"author":1138,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":59},"categories":[1400],"tags":[5110,2715],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/56740"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/1138"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=56740"}],"version-history":[{"count":3,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/56740\/revisions"}],"predecessor-version":[{"id":56757,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/56740\/revisions\/56757"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=56740"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=56740"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=56740"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}