소스 검색

AK: Allow deferring clear() for the Function class

Ideally a Function should not be clear()ed while it's running.
Unfortunately a number of callers do just that and identifying all of
them would require inspecting all call sites for operator() and clear().

Instead this adds support for deferring clear() until after the
function has finished executing.
Gunnar Beutner 4 년 전
부모
커밋
44418cb351
1개의 변경된 파일12개의 추가작업 그리고 3개의 파일을 삭제
  1. 12 3
      AK/Function.h

+ 12 - 3
AK/Function.h

@@ -48,7 +48,7 @@ public:
 
     ~Function()
     {
-        clear();
+        clear(false);
     }
 
     template<typename CallableType, class = typename EnableIf<!(IsPointer<CallableType> && IsFunction<RemovePointer<CallableType>>)&&IsRvalueReference<CallableType&&>>::Type>
@@ -74,7 +74,8 @@ public:
         VERIFY(wrapper);
         ++m_call_nesting_level;
         ScopeGuard guard([this] {
-            --m_call_nesting_level;
+            if (--m_call_nesting_level == 0 && m_deferred_clear)
+                const_cast<Function*>(this)->clear(false);
         });
         return wrapper->call(forward<In>(in)...);
     }
@@ -181,8 +182,15 @@ private:
         }
     }
 
-    void clear()
+    void clear(bool may_defer = true)
     {
+        bool called_from_inside_function = m_call_nesting_level > 0;
+        VERIFY(may_defer || !called_from_inside_function);
+        if (called_from_inside_function && may_defer) {
+            m_deferred_clear = true;
+            return;
+        }
+        m_deferred_clear = false;
         auto* wrapper = callable_wrapper();
         if (m_kind == FunctionKind::Inline) {
             VERIFY(wrapper);
@@ -229,6 +237,7 @@ private:
     }
 
     FunctionKind m_kind { FunctionKind::NullPointer };
+    bool m_deferred_clear { false };
     mutable Atomic<u16> m_call_nesting_level { 0 };
     // Empirically determined to fit most lambdas and functions.
     static constexpr size_t inline_capacity = 4 * sizeof(void*);