{"payload":{"feedbackUrl":"https://github.com/orgs/community/discussions/53140","repo":{"id":218405352,"defaultBranch":"main","name":"libunifex","ownerLogin":"facebookexperimental","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2019-10-29T23:50:53.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/12853545?v=4","public":true,"private":false,"isOrgOwned":true},"refInfo":{"name":"","listCacheKey":"v0:1724711564.0","currentOid":""},"activityList":{"items":[{"before":"1308447d91287d81c191ff87bf33d7abd23e5fe9","after":"6b6259d13ab6d0e1ad87a31bdbcaf005e68a0ada","ref":"refs/heads/coroutine_async_stack_support","pushedAt":"2024-08-27T00:55:36.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Fix opt and C++20 builds","shortMessageHtmlLink":"Fix opt and C++20 builds"}},{"before":"81a6193ead2a60c3cbef38dfdbb5452fbdd70fe9","after":"1308447d91287d81c191ff87bf33d7abd23e5fe9","ref":"refs/heads/coroutine_async_stack_support","pushedAt":"2024-08-27T00:51:13.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Fix opt and C++20 builds","shortMessageHtmlLink":"Fix opt and C++20 builds"}},{"before":null,"after":"81a6193ead2a60c3cbef38dfdbb5452fbdd70fe9","ref":"refs/heads/coroutine_async_stack_support","pushedAt":"2024-08-26T22:32:44.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Add async stack support to coroutines\n\nThis change extends the work in #616 to support async stack frames in\n`task<>` coroutines, including those that invoke `at_coroutine_exit()`.\n\nIn `task<>`, when `UNIFEX_NO_ASYNC_STACKS` is falsey, the awaiter returned from\n`task<>`'s customization of `unifex::await_transform` stores an\n`AsyncStackFrame`. The awaiter pushes its frame onto the current async stack in\n`await_suspend()` and pops it again in `await_resume()`; since\n`await_resume()` is only invoked for value and error completions, this\narrangement leaves it up to the waiting task to pop the awaiter's frame\nwhen the awaited task completes with done. This can be expressed as a\nnew rule:\n\n- when a coroutine completes with a value or an error, it is responsible\n for popping its own `AsyncStackFrame`; but\n- when a coroutine completes with done, the *caller* is responsible for\n popping the callee's `AsyncStackFrame` as a part of the caller's\n `unhandled_done()` coroutine.\n\nTo support this new requirement of `unhandled_done()` (that it is\nresponsible for popping the callee's stack frame), this change\nintroduces `popAsyncStackFrameFromCaller`, which takes the caller's\nstack frame by reference so that it can assert that, after popping the\ncurrent async frame (whatever it is), the new top frame is the caller's\nframe.\n\nA `task<>` promise has an `AsyncStackFrame*` that, when it's not\n`nullptr`, points to the `AsyncStackFrame` in the awaiter waiting for\nthe task. This pointer exists even when `UNIFEX_NO_ASYNC_STACKS` is\ntruthy to help mitigate against ODR violations; linking together two TUs\nwith `UNIFEX_NO_ASYNC_STACKS` set differently is not explicitly\nsupported but, by ensuring this pointer always exists, some ODR problems\nare avoided. When a `task<>` is awaited from a TU with async stack\nsupport enabled, the awaited task's awaiter sets the promise's\n`AsyncStackFrame*` to point to the awaiter's frame; when a `task<>` is\nawaited from a TU with async stack support disabled, this assignment\nnever happens and the promise's pointer remains null.\n\nThe above description of `task<>`'s async stack maintenance only covers\nthe recursive case of on coroutine awaiting another. The base case is\nhandled in `connect_awaitable()`, where an `AsyncStackRoot` is set up\nbefore starting the connected awaitable.\n\n`stop_if_requested` used to model both `sender` and `awaitable` so that\n`co_await stop_if_requested();` could take advantage of symmetric\ntransfer. The `stop_if_requested` sender now customizes\n`await_transform` to express its participation in async stack\nmanagement. This means of expressing async stack awareness is\nunsatisfying but I don't have any better ideas right now.\n\nLastly, `unifex::await_transform()` now wraps naturally-awaitable\narguments in an `awaiter_wrapper` that ensures the `coroutine_handle<>`\npassed to the wrapped awaitable is one that establishes an active\n`AsyncStackRoot` before resuming the real waiting coroutine.","shortMessageHtmlLink":"Add async stack support to coroutines"}},{"before":null,"after":"6ab1716f58fcc183ea6fb6bf1e4f75656b64724e","ref":"refs/heads/add_return_address_to_as_sender","pushedAt":"2024-08-26T18:22:19.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Customize get_return_address for as_sender\n\nThis change customizes `unifex::get_return_address()` for the\n`as_sender` adapter that makes awaitables connectable.\n\n```\nvoid foo(auto someAwaitable) {\n auto s = unifex::as_sender(std::move(someAwaitable));\n\n // now returns the call-site of as_sender, which is probably the call\n // to as_sender in foo (but might be the call to foo if foo is\n // inlined), rather than the result of\n // unifex::_get_return_address::default_return_address()\n auto rtnAdr = unifex::get_return_address(s);\n}\n```","shortMessageHtmlLink":"Customize get_return_address for as_sender"}},{"before":"bf24fde8ccb5cf37ff948c5210b1a7b077e36326","after":null,"ref":"refs/heads/simplify_await_transform","pushedAt":"2024-08-26T17:19:12.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"}},{"before":"d2f6972b50d7ae0d8008a305de96f9c6ba91b8e1","after":"cc9c161ca1aad66a56a829a53bd2519ea393a623","ref":"refs/heads/main","pushedAt":"2024-08-26T17:19:08.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Restore the default branch to await_transform\n\nAddress @janondrusek's feedback from #627 by reinstituting the default\nbranch to `unifex::await_transform()`'s type-switching logic. I've added\na separate overload rather than extend the conditions on the existing\n\"naturally awaitable\" overload because a future change will add async\nstack-related changes to the existing branch but not to the new branch\nI'm adding here.","shortMessageHtmlLink":"Restore the default branch to await_transform"}},{"before":"eacfbcb489a5f07ba56534f54621bdd1e506b1c4","after":"bf24fde8ccb5cf37ff948c5210b1a7b077e36326","ref":"refs/heads/simplify_await_transform","pushedAt":"2024-08-26T16:52:34.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Restore the default branch to await_transform\n\nAddress @janondrusek's feedback from #627 by reinstituting the default\nbranch to `unifex::await_transform()`'s type-switching logic. I've added\na separate overload rather than extend the conditions on the existing\n\"naturally awaitable\" overload because a future change will add async\nstack-related changes to the existing branch but not to the new branch\nI'm adding here.","shortMessageHtmlLink":"Restore the default branch to await_transform"}},{"before":"66d773fbfcb9f31d53eb163c1378d9926f43afb6","after":"d2f6972b50d7ae0d8008a305de96f9c6ba91b8e1","ref":"refs/heads/main","pushedAt":"2024-08-26T06:02:11.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"jesswong","name":null,"path":"/jesswong","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/5247012?s=80&v=4"},"commit":{"message":"Simplify await_transform's type-switching logic (#627)\n\nThis change simplifies the implementation-selection logic in\r\n`unifex::await_transform()`. Instead of a multi-level `if constexpr`, we\r\nnow choose how to transform an awaited expression with\r\nmutually-exclusive `requires` clauses. The new order of preference is:\r\n\r\n1. rely on the awaited type's customization of `await_transform`\r\n2. return naturally-awaitable expressions directly\r\n3. map senders to awaitables with the existing `_as_awaitable` logic\r\n\r\nThis preference ordering matches the old behaviour.","shortMessageHtmlLink":"Simplify await_transform's type-switching logic (#627)"}},{"before":"206fc69a75678c94c069787419d581f3836f4d00","after":"eacfbcb489a5f07ba56534f54621bdd1e506b1c4","ref":"refs/heads/simplify_await_transform","pushedAt":"2024-08-25T02:28:19.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Simplify await_transform's type-switching logic\n\nThis change simplifies the implementation-selection logic in\n`unifex::await_transform()`. Instead of a multi-level `if constexpr`, we\nnow choose how to transform an awaited expression with\nmutually-exclusive `requires` clauses. The new order of preference is:\n\n1. rely on the awaited type's customization of `await_transform`\n2. return naturally-awaitable expressions directly\n3. map senders to awaitables with the existing `_as_awaitable` logic\n\nThis preference ordering matches the old behaviour.","shortMessageHtmlLink":"Simplify await_transform's type-switching logic"}},{"before":"39f556f45aa8a671cd0baa313bdcc423e2be4c63","after":null,"ref":"refs/heads/frame_in_spawn_detached","pushedAt":"2024-08-25T02:06:44.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"}},{"before":"78739367c4adcf23d53ca0a0e332a4ad5989cd04","after":"66d773fbfcb9f31d53eb163c1378d9926f43afb6","ref":"refs/heads/main","pushedAt":"2024-08-25T02:06:40.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Give spawn_detached's receiver an async stack frame (#626)\n\n* Give spawn_detached's receiver an async stack frame\r\n\r\nThis change adds an `AsyncStackFrame` (when support is enabled) to the\r\ncapstone receiver connected to any sender passed to\r\n`unifex::spawn_detached()`.\r\n\r\n* Amend the copyright text in modified files\r\n\r\n* Unit-test async stack frame behaviour","shortMessageHtmlLink":"Give spawn_detached's receiver an async stack frame (#626)"}},{"before":"9a65872ed5fe230d50cf6572f3d80de6e09c9a3e","after":"39f556f45aa8a671cd0baa313bdcc423e2be4c63","ref":"refs/heads/frame_in_spawn_detached","pushedAt":"2024-08-25T01:28:04.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Try to fix broken opt builds","shortMessageHtmlLink":"Try to fix broken opt builds"}},{"before":"bab73a9444127b7f06fa455cc35b62e2ee896b42","after":"9a65872ed5fe230d50cf6572f3d80de6e09c9a3e","ref":"refs/heads/frame_in_spawn_detached","pushedAt":"2024-08-25T01:09:37.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Update the copyright in spawn_detached_test.cpp","shortMessageHtmlLink":"Update the copyright in spawn_detached_test.cpp"}},{"before":"3fdb0cefbd813354516c6f1bf0bc953fd165a1a9","after":"bab73a9444127b7f06fa455cc35b62e2ee896b42","ref":"refs/heads/frame_in_spawn_detached","pushedAt":"2024-08-25T00:57:07.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Unit-test async stack frame behaviour","shortMessageHtmlLink":"Unit-test async stack frame behaviour"}},{"before":null,"after":"206fc69a75678c94c069787419d581f3836f4d00","ref":"refs/heads/simplify_await_transform","pushedAt":"2024-08-24T05:14:27.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Simplify await_transform's type-switching logic\n\nThis change simplifies the implementation-selection logic in\n`unifex::await_transform()`. Instead of a multi-level `if constexpr`, we\nnow choose how to transform an awaited expression with\nmutually-exclusive `requires` clauses. The new order of preference is:\n\n1. rely on the awaited type's customization of `await_transform`\n2. return naturally-awaitable expressions directly\n3. map senders to awaitables with the existing `_as_awaitable` logic\n\nThis preference ordering matches the old behaviour.","shortMessageHtmlLink":"Simplify await_transform's type-switching logic"}},{"before":"fbdd70af03ef39b9e23bb1db790a69ed2d59e27b","after":"3fdb0cefbd813354516c6f1bf0bc953fd165a1a9","ref":"refs/heads/frame_in_spawn_detached","pushedAt":"2024-08-24T04:55:33.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Amend the copyright text in modified files","shortMessageHtmlLink":"Amend the copyright text in modified files"}},{"before":null,"after":"fbdd70af03ef39b9e23bb1db790a69ed2d59e27b","ref":"refs/heads/frame_in_spawn_detached","pushedAt":"2024-08-23T19:19:12.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Give spawn_detached's receiver an async stack frame\n\nThis change adds an `AsyncStackFrame` (when support is enabled) to the\ncapstone receiver connected to any sender passed to\n`unifex::spawn_detached()`.","shortMessageHtmlLink":"Give spawn_detached's receiver an async stack frame"}},{"before":"22cf8f4fa9a0c3c23c2cfa248d5c384962652806","after":null,"ref":"refs/heads/include_continuations_instead_of_async_trace","pushedAt":"2024-08-17T18:28:07.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"}},{"before":"58fec3fda93d8192483a6dab44ac4957f5a4bc6f","after":"78739367c4adcf23d53ca0a0e332a4ad5989cd04","ref":"refs/heads/main","pushedAt":"2024-08-17T18:28:04.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Include continuations.hpp instead of async_trace.hpp (#625)\n\n* Include continuations.hpp instead of async_trace.hpp\r\n\r\nAs discovered in compiler-explorer/compiler-explorer#6711, GCC 15\r\ndoesn't like compiling `unifex/async_trace.hpp` as C++17 *however*,\r\nthere's almost no need to include `unifex/async_trace.hpp` anywhere\r\nbecause it's only included to get `unifex/continuations.hpp` as a side\r\neffect. This change just includes the actual dependency directly.\r\n\r\n* clang-format the modified files\r\n\r\n* Update copyright headers in modified files\r\n\r\n* Fix formatting in dematerialize.hpp","shortMessageHtmlLink":"Include continuations.hpp instead of async_trace.hpp (#625)"}},{"before":"1590dd08b71fc88909128af45b6938516efdc9c9","after":"22cf8f4fa9a0c3c23c2cfa248d5c384962652806","ref":"refs/heads/include_continuations_instead_of_async_trace","pushedAt":"2024-08-17T18:15:12.000Z","pushType":"push","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Fix formatting in dematerialize.hpp","shortMessageHtmlLink":"Fix formatting in dematerialize.hpp"}},{"before":"2d730865aab01260c35f151e0d1c7f39068ae336","after":"1590dd08b71fc88909128af45b6938516efdc9c9","ref":"refs/heads/include_continuations_instead_of_async_trace","pushedAt":"2024-08-17T18:09:09.000Z","pushType":"push","commitsCount":2,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Update copyright headers in modified files","shortMessageHtmlLink":"Update copyright headers in modified files"}},{"before":null,"after":"2d730865aab01260c35f151e0d1c7f39068ae336","ref":"refs/heads/include_continuations_instead_of_async_trace","pushedAt":"2024-08-17T17:54:10.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Include continuations.hpp instead of async_trace.hpp\n\nAs discovered in compiler-explorer/compiler-explorer#6711, GCC 15\ndoesn't like compiling `unifex/async_trace.hpp` as C++17 *however*,\nthere's almost no need to include `unifex/async_trace.hpp` anywhere\nbecause it's only included to get `unifex/continuations.hpp` as a side\neffect. This change just includes the actual dependency directly.","shortMessageHtmlLink":"Include continuations.hpp instead of async_trace.hpp"}},{"before":"847bf2ac13dc3e084b013efaaf3c9c757ecbb40d","after":"58fec3fda93d8192483a6dab44ac4957f5a4bc6f","ref":"refs/heads/main","pushedAt":"2024-08-16T23:26:16.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"fixes for error_types","shortMessageHtmlLink":"fixes for error_types"}},{"before":"891a9c6082a2e45eb86d7fcbd4a29865ad386379","after":null,"ref":"refs/heads/enlazy_unhandled_done","pushedAt":"2024-08-05T21:25:33.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"}},{"before":"16740d03a868168922096431fca25e31b170d48f","after":"847bf2ac13dc3e084b013efaaf3c9c757ecbb40d","ref":"refs/heads/main","pushedAt":"2024-08-05T21:25:30.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Enlazy unhandled done (#622)\n\n* Format and update copyright\r\n\r\nIn preparation for more extensive edits to the modified files, I've run\r\n`clang-format -i` on each one and updated the copyright header to match\r\nMeta's new standard copyright banner.\r\n\r\n* Add unifex::unhandled_done\r\n\r\nThis diff adds a new algorithm called `unifex::unhandled_done(Func)`,\r\nwhich takes a callable (with signature `coroutine_handle<>()` or\r\n`void()`) and returns a suspended coroutine. When the returned coroutine\r\nis resumed, it invokes the callable and either a) resumes the coroutine\r\n*it* returns, or b) suspends (if the callable returns `void`). The\r\nintended use of `unhandled_done()` is to make it easier for a coroutine\r\npromise type to implement its own `unhandled_done()`.","shortMessageHtmlLink":"Enlazy unhandled done (#622)"}},{"before":null,"after":"891a9c6082a2e45eb86d7fcbd4a29865ad386379","ref":"refs/heads/enlazy_unhandled_done","pushedAt":"2024-08-04T01:24:07.000Z","pushType":"branch_creation","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Add unifex::unhandled_done\n\nThis diff adds a new algorithm called `unifex::unhandled_done(Func)`,\nwhich takes a callable (with signature `coroutine_handle<>()` or\n`void()`) and returns a suspended coroutine. When the returned coroutine\nis resumed, it invokes the callable and either a) resumes the coroutine\n*it* returns, or b) suspends (if the callable returns `void`). The\nintended use of `unhandled_done()` is to make it easier for a coroutine\npromise type to implement its own `unhandled_done()`.","shortMessageHtmlLink":"Add unifex::unhandled_done"}},{"before":"2d1d85bf8966b4d5af6d88def83d6ae5f9740327","after":null,"ref":"refs/heads/async_stack_traces","pushedAt":"2024-07-18T05:29:37.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"}},{"before":"1916a2f4a76fc5ac5c5364d6b65f3d88dd57eae4","after":"16740d03a868168922096431fca25e31b170d48f","ref":"refs/heads/main","pushedAt":"2024-07-18T05:29:33.000Z","pushType":"pr_merge","commitsCount":1,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Add initial support for async stack traces to Unifex (#616)\n\nThis PR copies the core of Folly's [async stack trace support](https://github.com/facebook/folly/tree/main/folly/tracing) into `include/unifex/tracing` and builds on it to add support for generalized *Senders*.\r\n\r\nWhen `UNIFEX_NO_ASYNC_STACKS` is falsey, `unifex::connect` returns a wrapped operation state that injects async stack tracing into the operation tree.\r\n - The wrapper operation:\r\n - stores an `AsyncStackFrame` for the wrapped operation; and\r\n - wraps the receiver.\r\n - In the wrapper operation's customization of `unifex::start` we:\r\n - create an `AsyncStackRoot` on the stack;\r\n - push the wrapper operation's `AsyncStackFrame` onto the current async stack;\r\n - activate the wrapper operation's `AsyncStackFrame` on the current `AsyncStackRoot`; and\r\n - start the wrapped operation.\r\n - In the wrapper receiver's completion methods we:\r\n - create an `AsyncStackRoot` on the stack;\r\n - copy the *parent* operation's `AsyncStackFrame` to the stack;\r\n - activate the parent `AsyncStackFrame` on the current `AsyncStackRoot`; and\r\n - invoke the parent operation's receiver.\r\n\r\nThe effect is that we build up a linked list (technically a DAG) of `AsyncStackFrame`s pointing \"up\" toward the start of the operation as `unifex::start` recurses into the nested operation state and then unwind it on the way back out as the receiver completion methods are invoked. At any given time, the current thread's `AsyncStackRoot` is sitting on the most recently-activated \"normal\" stack frame that is participating in async stack management, allowing Folly's `co_bt.py` debugger extension to figure out when it should stop walking normal stack frames and start walking async stack frames.\r\n\r\nAs alluded to above, the behaviour of the async stack tracing machinery is controlled by the `UNIFEX_NO_ASYNC_STACKS` preprocessor macro. If it's truthy, async stacks are not traced; if it's falsey, they are traced. The default in `unifex/config.hpp` is to enable async stack tracing in non-Windows debug builds.\r\n - Why not Windows builds?\r\n - Because there's something weird about how `any_sender_of<>` builds on Windows (both Clang and MSVC); the resolution is to land PR #619, but that PR breaks an internal Meta build so I'll have to come back to it.\r\n - Why only debug builds?\r\n - The additional work done to track async stacks adds non-trivial binary size to the output so I figure it should default to off for release builds. You can turn it on by defining `UNIFEX_NO_ASYNC_STACKS=0` in your release build script if the extra debuggability is worth the extra binary size in production.\r\n\r\nThis iteration is an MVP:\r\n - only general senders are supported, not coroutines\r\n - the \"return addresses\" captured for each sender point to `unifex::_get_return_address::default_return_address()`, where `T` is the type of the sender\r\n - this is better than nothing because the resulting symbol includes the sender's fully-qualified name, but it's not great\r\n\r\nFutures PRs will:\r\n - add support for tracing the async stacks of coroutines\r\n - improve the rendering of async stack traces by making senders capture a pointer to the call site of their factory\r\n - maybe shrink the binary size overhead of enabling this feature if I can figure out how to eliminate some of the recursion\r\n\r\nOriginal diff descriptions:\r\n* Import Folly's async stack library\r\n\r\nThis diff, originally by @janondrusek and @jesswong, copies the core of\r\nFolly's [async stack trace support](https://github.com/facebook/folly/tree/main/folly/tracing)\r\ninto `include/unifex/tracing`.\r\n\r\n* Add type-safe instruction and frame pointer types\r\n\r\nStop using `void*` to represent both instruction pointers and stack\r\nframe pointers and start using `unifex::instruction_ptr` and\r\n`unifex::frame_ptr`.\r\n\r\n* Add ScopedAsyncStackRoot::ensureFrameDeactivated()\r\n\r\nWe need a way to restore a `ScopedAsyncStackRoot` to the \"no active\r\nframe\" state before destroying it on the way out of a customization of\r\n`unifex::start` but the frame we want to deactivate is a member of the\r\noperation state, which means it's likely already been destroyed. This\r\ndiff adds `ScopedAsyncStackRoot::ensureFrameDeactivated()`, which\r\nperforms most of the same actions as `deactivateAsyncStackFrame()` but\r\nwithout touching the frame. I think this still technically invokes UB by\r\ncopying and comparing a zapped pointer, but it's better than what we had\r\nbefore.\r\n\r\n* Add get_async_stack_frame\r\n\r\nThis diff adds a new receiver query CPO that is expected to return the\r\naddress of the `AsyncStackFrame` associated with the receiver's\r\noperation.\r\n\r\n* Add get_return_address\r\n\r\nThis diff adds a new sender query CPO that is expected to return the\r\ninstruction pointer best representing the \"return address\" for the\r\nsender; the default implementation returns the return address of a\r\nfunction template instantiation that includes the sender's type in its\r\nsignature as a kind of \"better than nothing\" result.\r\n\r\n* Add a comment re: lldb type summaries\r\n\r\nThe `instruction_ptr` type is best rendered by the debugger as an\r\n\"address\", which will render as a symbol + offset rather than an\r\narbitrary hexadecimal value. This diff adds a comment to the type\r\ndocumenting this fact.\r\n\r\n* Establish an AsyncStackRoot in sync_wait()\r\n\r\nThis diff modifies `unifex::sync_wait()` to establish an\r\n`AsyncStackRoot` on the stack while the awaited operation is running.\r\n\r\n* Modify unifex::connect to inject async stacks\r\n\r\nThis diff modifies `unifex::connect` to inject async stack tracking into\r\nevery operation state is it's built.\r\n\r\n* Work around Windows-only problems\r\n\r\nThe Unifex unit test suite won't build for Windows with async stack\r\ninjection enabled *unless* PR #619 (Make any_sender_of<> play nicer with\r\nMSVC) is also merged, but that PR causes Windows + Clang + ASAN errors\r\nin Meta-internal builds.\r\n\r\nThis diff works around the above conflict by disabling async stack\r\ninjection in Windows builds by default so we don't need PR #619. We can\r\nchange the default once we figure out a proper resolution to the ASAN\r\nproblem.\r\n\r\nCo-authored-by: Ján Ondrušek \r\nCo-authored-by: Jessica Wong \r\nCo-authored-by: Deniz Evrenci ","shortMessageHtmlLink":"Add initial support for async stack traces to Unifex (#616)"}},{"before":"2d1d85bf8966b4d5af6d88def83d6ae5f9740327","after":null,"ref":"refs/heads/maybe_new_async_stack_traces_head","pushedAt":"2024-07-17T05:30:42.000Z","pushType":"branch_deletion","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"}},{"before":"a37253f032172854e07b905264b0b3ff0415849d","after":"2d1d85bf8966b4d5af6d88def83d6ae5f9740327","ref":"refs/heads/async_stack_traces","pushedAt":"2024-07-17T05:30:03.000Z","pushType":"force_push","commitsCount":0,"pusher":{"login":"ispeters","name":"Ian Petersen","path":"/ispeters","primaryAvatarUrl":"https://avatars.githubusercontent.com/u/13162660?s=80&v=4"},"commit":{"message":"Work around Windows-only problems\n\nThe Unifex unit test suite won't build for Windows with async stack\ninjection enabled *unless* PR #619 (Make any_sender_of<> play nicer with\nMSVC) is also merged, but that PR causes Windows + Clang + ASAN errors\nin Meta-internal builds.\n\nThis diff works around the above conflict by disabling async stack\ninjection in Windows builds by default so we don't need PR #619. We can\nchange the default once we figure out a proper resolution to the ASAN\nproblem.","shortMessageHtmlLink":"Work around Windows-only problems"}}],"hasNextPage":true,"hasPreviousPage":false,"activityType":"all","actor":null,"timePeriod":"all","sort":"DESC","perPage":30,"cursor":"djE6ks8AAAAEpNGVvgA","startCursor":null,"endCursor":null}},"title":"Activity · facebookexperimental/libunifex"}