nodeguy/docs/development/wrapper_caching/index.html
2023-03-07 20:59:20 +00:00

38 lines
13 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="generator" content="Docusaurus v2.0.0-alpha.64">
<link rel="preconnect" href="https://www.google-analytics.com">
<script>window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)},ga.l=+new Date,ga("create","UA-145065218-1","auto"),ga("send","pageview")</script>
<script async src="https://www.google-analytics.com/analytics.js"></script>
<link rel="search" type="application/opensearchdescription+xml" title="NodeGui" href="/opensearch.xml"><title data-react-helmet="true">wrapper_caching | NodeGui</title><meta data-react-helmet="true" name="docsearch:version" content="current,latest"><meta data-react-helmet="true" name="twitter:card" content="summary_large_image"><meta data-react-helmet="true" property="og:title" content="wrapper_caching | NodeGui"><meta data-react-helmet="true" name="description" content="Wrapper caching and memory management"><meta data-react-helmet="true" property="og:description" content="Wrapper caching and memory management"><meta data-react-helmet="true" property="og:url" content="https://nodegui.org/docs/development/wrapper_caching"><link data-react-helmet="true" rel="shortcut icon" href="/img/favicon.ico"><link data-react-helmet="true" rel="preconnect" href="https://BH4D9OD16A-dsn.algolia.net" crossorigin="true"><link data-react-helmet="true" rel="canonical" href="https://nodegui.org/docs/development/wrapper_caching"><link rel="stylesheet" href="/styles.920797bd.css">
<link rel="preload" href="/styles.af071a21.js" as="script">
<link rel="preload" href="/runtime~main.df3c8c03.js" as="script">
<link rel="preload" href="/main.ebdb87c0.js" as="script">
<link rel="preload" href="/1.a07fac2c.js" as="script">
<link rel="preload" href="/2.17db72ff.js" as="script">
<link rel="preload" href="/3.a48590d3.js" as="script">
<link rel="preload" href="/1be78505.7c14a9f1.js" as="script">
<link rel="preload" href="/412.e74da700.js" as="script">
<link rel="preload" href="/935f2afb.78360da5.js" as="script">
<link rel="preload" href="/17896441.ffc93e5d.js" as="script">
<link rel="preload" href="/c1411b4d.992488d8.js" as="script">
</head>
<body>
<script>!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}()</script><div id="__docusaurus">
<nav class="navbar navbar--fixed-top"><div class="navbar__inner"><div class="navbar__items"><div aria-label="Navigation bar toggle" class="navbar__toggle" role="button" tabindex="0"><svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30" role="img" focusable="false"><title>Menu</title><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></div><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo-circle.png" alt="NodeGui Logo"><strong class="navbar__title">NodeGui</strong></a></div><div class="navbar__items navbar__items--right"><a class="navbar__item navbar__link" href="/docs/guides/getting-started">Docs</a><a class="navbar__item navbar__link" href="/docs/api/manual/synopsis">API</a><a class="navbar__item navbar__link" href="/blog">Blog</a><a href="https://github.com/nodegui/nodegui" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub</a><div class="react-toggle react-toggle--disabled displayOnlyInLargeViewport_2aTZ"><div class="react-toggle-track"><div class="react-toggle-track-check"><span class="toggle_BsTx">🌜</span></div><div class="react-toggle-track-x"><span class="toggle_BsTx">🌞</span></div></div><div class="react-toggle-thumb"></div><input type="checkbox" disabled="" aria-label="Dark mode toggle" class="react-toggle-screenreader-only"></div><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><svg width="20" height="20" class="DocSearch-Search-Icon" viewBox="0 0 20 20"><path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z" stroke="currentColor" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round"></path></svg><span class="DocSearch-Button-Placeholder">Search</span><span class="DocSearch-Button-Key"></span><span class="DocSearch-Button-Key">K</span></button></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div><div class="navbar-sidebar"><div class="navbar-sidebar__brand"><a class="navbar__brand" href="/"><img class="navbar__logo" src="/img/logo-circle.png" alt="NodeGui Logo"><strong class="navbar__title">NodeGui</strong></a></div><div class="navbar-sidebar__items"><div class="menu"><ul class="menu__list"><li class="menu__list-item"><a class="menu__link" href="/docs/guides/getting-started">Docs</a></li><li class="menu__list-item"><a class="menu__link" href="/docs/api/manual/synopsis">API</a></li><li class="menu__list-item"><a class="menu__link" href="/blog">Blog</a></li><li class="menu__list-item"><a href="https://github.com/nodegui/nodegui" target="_blank" rel="noopener noreferrer" class="menu__link">GitHub</a></li></ul></div></div></div></nav><div class="main-wrapper"><div class="docPage_2gpo"><main class="docMainContainer_3EyW"><div class="container padding-vert--lg docItemWrapper_1EkI"><div class="row"><div class="col docItemCol_2ASc"><div class="docItemContainer_3QWW"><article><header><h1 class="docTitle_1Lrw">wrapper_caching</h1></header><div class="markdown"><h1><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="wrapper-caching-and-memory-management"></a>Wrapper caching and memory management<a aria-hidden="true" tabindex="-1" class="hash-link" href="#wrapper-caching-and-memory-management" title="Direct link to heading">#</a></h1><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="wrapper-keep-alive-case"></a>&quot;Wrapper Keep Alive&quot; case<a aria-hidden="true" tabindex="-1" class="hash-link" href="#wrapper-keep-alive-case" title="Direct link to heading">#</a></h2><p>The goal of the &quot;Wrapper Keep Alive&quot; case is to maintain and &quot;keep alive&quot; wrappers for the life-time of a <code>QObject</code> whose life-cycle is under complete control by Qt itself. i.e. Qt may expose the object, but it creates the instance itself and also destroys it later on. This situation applies to <code>QScreen</code> and <code>QClipboard</code> for example. A common use case for keeping a wrapper alive is to receive and relay signals from a <code>QObject</code> back to JS during the object&#x27;s life-time.</p><p><img alt="Wrapper cache diagram" src="/assets/images/wrapper_cache.drawio-46451808d90ee4e514947480ab75f185.svg"></p><p>The WrapperCache (C++) holds strong JS references to the Napi wrapper instances. This keeps them alive. When the core QObject is destroyed the &quot;destroyed&quot; signal is emitted and received by WrapperCache (C++). It then removes the Napi wrapper from its cache and uses a callback function to inform the WrapperCache (JS) about the destruction. WrapperCache (JS) can also perform clean up and null out references to the Napi wrappers. If someone then tries to use a JS side wrapper, then will get a JS side null pointer exception with stacktrace.</p><p><strong>Life-cycle Sequence</strong></p><p>This sequence diagram shows the events when the application calls <code>QWindow.screen()</code> to fetch the <code>QScreen</code> for the window. The <code>QScreen</code> instance is fully created and managed by Qt. Here you can see how the wrapper creation interacts with the JS and C++ side cache classes. You can also see how the wrappers are gracefully shutdown when the core Qt object is destroyed. Any JS side use of the destroyed wrapper / Qt object results in a neat JS side null pointer exception. This is much better than null pointer segfault on the C++ side.</p><p><img alt="Wrapper keep alive sequence diagram" src="/assets/images/wrapper_keep_alive_seq-1b49fcf3124585ae8900b6d67037c76e.png"></p><h2><a aria-hidden="true" tabindex="-1" class="anchor enhancedAnchor_2cZh" id="wrapper-recycle-case"></a>&quot;Wrapper Recycle&quot; case<a aria-hidden="true" tabindex="-1" class="hash-link" href="#wrapper-recycle-case" title="Direct link to heading">#</a></h2><p>A related use case is where we want to &quot;recycle&quot; wrappers and ensure that for a QObject we only have one coresponding JS wrapper active at the same time. For example, repeated calls to <code>QObject.parent()</code> should return the same value/object.</p><p>Another goal of this use case is to ensure that the unexpected destruction of the underlying QObject is handled in a more graceful and helpful way than just segfaulting the whole application. This requires the tracking of the QObject via its &quot;destroy&quot; signal and using that to communicate back to JS what has happened.</p><p>The object creation sequence runs quite differently than in the &quot;Wrapper Keep Alive&quot; case because the application initiates the creation of the object and NodeGui then creates the different wrappers on the JS and C++ sides.</p><p><img alt="Wrapper recycle sequence diagram" src="/assets/images/wrapper_recycle_seq-fff36b6a9f35e317fc1f0a3fe2d31542.png"></p><p>The destruction sequence in the case of the C++ object being destroyed is basically the same as the &quot;Wrapper Keep Alive&quot; case.</p></div></article><div class="margin-vert--xl"><div class="row"><div class="col"><a href="https://github.com/nodegui/nodegui/edit/master/website/docs/development/wrapper_caching.md" target="_blank" rel="noreferrer noopener"><svg fill="currentColor" height="1.2em" width="1.2em" preserveAspectRatio="xMidYMid meet" viewBox="0 0 40 40" style="margin-right:0.3em;vertical-align:sub"><g><path d="m34.5 11.7l-3 3.1-6.3-6.3 3.1-3q0.5-0.5 1.2-0.5t1.1 0.5l3.9 3.9q0.5 0.4 0.5 1.1t-0.5 1.2z m-29.5 17.1l18.4-18.5 6.3 6.3-18.4 18.4h-6.3v-6.2z"></path></g></svg>Edit this page</a></div></div></div><div class="margin-vert--lg"><nav class="pagination-nav" aria-label="Blog list page navigation"><div class="pagination-nav__item"></div><div class="pagination-nav__item pagination-nav__item--next"></div></nav></div></div></div><div class="col col--3"><div class="tableOfContents_3SO_"><ul class="table-of-contents table-of-contents__left-border"><li><a href="#wrapper-keep-alive-case" class="table-of-contents__link">&quot;Wrapper Keep Alive&quot; case</a></li><li><a href="#wrapper-recycle-case" class="table-of-contents__link">&quot;Wrapper Recycle&quot; case</a></li></ul></div></div></div></div></main></div></div><footer class="footer footer--dark"><div class="container"><div class="row footer__links"><div class="col footer__col"><h4 class="footer__title">Docs</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/docs/guides/getting-started">Getting Started</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/api/manual/synopsis">API</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">Community</h4><ul class="footer__items"><li class="footer__item"><a href="https://spectrum.chat/nodegui" target="_blank" rel="noopener noreferrer" class="footer__link-item">Spectrum</a></li><li class="footer__item"><a href="https://nodegui.slack.com" target="_blank" rel="noopener noreferrer" class="footer__link-item">Slack</a></li><li class="footer__item"><a href="https://twitter.com/node_gui" target="_blank" rel="noopener noreferrer" class="footer__link-item">Twitter</a></li><li class="footer__item"><a href="https://medium.com/nodegui" target="_blank" rel="noopener noreferrer" class="footer__link-item">Medium</a></li></ul></div><div class="col footer__col"><h4 class="footer__title">More</h4><ul class="footer__items"><li class="footer__item"><a class="footer__link-item" href="/blog">Blog</a></li><li class="footer__item"><a href="https://react.nodegui.org" target="_blank" rel="noopener noreferrer" class="footer__link-item">React NodeGui</a></li><li class="footer__item"><a class="footer__link-item" href="/docs/faq">FAQ</a></li></ul></div></div><div class="text--center"><div>Copyright © 2023 NodeGui</div></div></div></footer></div>
<script src="/styles.af071a21.js"></script>
<script src="/runtime~main.df3c8c03.js"></script>
<script src="/main.ebdb87c0.js"></script>
<script src="/1.a07fac2c.js"></script>
<script src="/2.17db72ff.js"></script>
<script src="/3.a48590d3.js"></script>
<script src="/1be78505.7c14a9f1.js"></script>
<script src="/412.e74da700.js"></script>
<script src="/935f2afb.78360da5.js"></script>
<script src="/17896441.ffc93e5d.js"></script>
<script src="/c1411b4d.992488d8.js"></script>
</body>
</html>