mirror of https://github.com/KLayout/klayout.git
commit
85eee4d6cc
|
|
@ -341,7 +341,7 @@ add_native_impl("QChildEvent", <<'CODE', <<'DECL')
|
|||
virtual bool can_upcast (const void *) const { return false; }
|
||||
|
||||
// Does not bind to a particular type
|
||||
virtual bool is_of_type (const std::type_info & /*ti*/) const { return false; }
|
||||
virtual bool binds () const { return false; }
|
||||
virtual const std::type_info &type () const { return typeid (DummyQObject); }
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -545,6 +545,7 @@ module DRC
|
|||
else
|
||||
str = (" " * indent) + arg
|
||||
RBA::Logger::log(str)
|
||||
self._process_events
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -563,6 +564,7 @@ module DRC
|
|||
@log_file.puts(str)
|
||||
else
|
||||
RBA::Logger::info(str)
|
||||
self._process_events
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -577,6 +579,7 @@ module DRC
|
|||
@log_file.puts("ERROR: " + arg)
|
||||
else
|
||||
RBA::Logger::error(arg)
|
||||
self._process_events
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -591,6 +594,7 @@ module DRC
|
|||
@log_file.puts("WARNING: " + arg)
|
||||
else
|
||||
RBA::Logger::warn(arg)
|
||||
self._process_events
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -1988,6 +1992,7 @@ CODE
|
|||
|
||||
t = RBA::Timer::new
|
||||
t.start
|
||||
self._process_events
|
||||
GC.start # force a garbage collection before the operation to free unused memory
|
||||
res = yield
|
||||
t.stop
|
||||
|
|
@ -2554,6 +2559,12 @@ CODE
|
|||
@used_output_layers[li] = true
|
||||
end
|
||||
end
|
||||
|
||||
def _process_events
|
||||
if RBA::Application.instance
|
||||
RBA::Application.instance.process_events
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
|||
|
|
@ -585,9 +585,9 @@ public:
|
|||
set_name (name);
|
||||
}
|
||||
|
||||
virtual bool is_of_type (const std::type_info &ti) const
|
||||
virtual bool binds () const
|
||||
{
|
||||
return (ti == typeid (X));
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual const std::type_info &type () const
|
||||
|
|
@ -865,15 +865,9 @@ public:
|
|||
return m_subclass_tester.get () && m_subclass_tester->can_upcast (p);
|
||||
}
|
||||
|
||||
virtual bool is_of_type (const std::type_info &ti) const
|
||||
virtual bool binds () const
|
||||
{
|
||||
if (adapted_type_info ()) {
|
||||
// A class matches the typeinfo of the adapted type. We'll sort this out later
|
||||
// on the client side.
|
||||
return (ti == *adapted_type_info ());
|
||||
} else {
|
||||
return (ti == typeid (X));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual const std::type_info &type () const
|
||||
|
|
|
|||
|
|
@ -816,7 +816,7 @@ bool has_class (const std::string &name)
|
|||
|
||||
static void add_class_to_map (const gsi::ClassBase *c)
|
||||
{
|
||||
if (c->declaration () != c) {
|
||||
if (c->declaration () != c || ! c->binds ()) {
|
||||
// only consider non-extensions
|
||||
return;
|
||||
}
|
||||
|
|
@ -833,14 +833,12 @@ static void add_class_to_map (const gsi::ClassBase *c)
|
|||
sp_tname_to_class = new tname_to_class_map_t ();
|
||||
}
|
||||
|
||||
if (ti && c->is_of_type (*ti)) {
|
||||
if (!sp_ti_to_class->insert (std::make_pair (ti, c)).second) {
|
||||
// Duplicate registration of this class
|
||||
tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")";
|
||||
tl_assert (false);
|
||||
} else {
|
||||
sp_tname_to_class->insert (std::make_pair (std::string (ti->name ()), c));
|
||||
}
|
||||
if (!sp_ti_to_class->insert (std::make_pair (ti, c)).second) {
|
||||
// Duplicate registration of this class
|
||||
tl::error << "Duplicate registration of class " << c->name () << " (type " << ti->name () << ")";
|
||||
tl_assert (false);
|
||||
} else {
|
||||
sp_tname_to_class->insert (std::make_pair (std::string (ti->name ()), c));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -446,12 +446,9 @@ public:
|
|||
}
|
||||
|
||||
/**
|
||||
* @brief Class implementation: check C++ type of object
|
||||
*
|
||||
* This method returns true, if objects of this class are compatible with
|
||||
* the given C++ type.
|
||||
* @brief Class implementation: returns true if this class binds to a script class
|
||||
*/
|
||||
virtual bool is_of_type (const std::type_info & /*ti*/) const
|
||||
virtual bool binds () const
|
||||
{
|
||||
tl_assert (false);
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@
|
|||
virtual bool can_upcast (const void *) const { return false; }
|
||||
|
||||
// Does not bind to a particular type
|
||||
virtual bool is_of_type (const std::type_info & /*ti*/) const { return false; }
|
||||
virtual bool binds () const { return false; }
|
||||
virtual const std::type_info &type () const { return typeid (DummyQObject); }
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@ DeferredMethodScheduler::unqueue (DeferredMethodBase *method)
|
|||
}
|
||||
m = mm;
|
||||
}
|
||||
for (std::list<DeferredMethodBase *>::iterator m = m_executing.begin (); m != m_executing.end (); ++m) {
|
||||
if (*m == method) {
|
||||
m_unqueued.insert (method);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -102,19 +108,31 @@ DeferredMethodScheduler::do_enable (bool en)
|
|||
void
|
||||
DeferredMethodScheduler::do_execute ()
|
||||
{
|
||||
std::list<DeferredMethodBase *> methods;
|
||||
|
||||
m_lock.lock ();
|
||||
methods.swap (m_methods);
|
||||
m_executing.clear ();
|
||||
m_unqueued.clear ();
|
||||
m_executing.swap (m_methods);
|
||||
m_scheduled = false;
|
||||
m_lock.unlock ();
|
||||
|
||||
// do the execution outside the locked range to avoid deadlocks if the method's execution
|
||||
// schedules another call.
|
||||
for (std::list<DeferredMethodBase *>::iterator m = methods.begin (); m != methods.end (); ++m) {
|
||||
(*m)->m_scheduled = false;
|
||||
(*m)->execute ();
|
||||
for (std::list<DeferredMethodBase *>::iterator m = m_executing.begin (); m != m_executing.end (); ++m) {
|
||||
bool still_valid;
|
||||
m_lock.lock ();
|
||||
// during execution a method may be unqueued - make sure this is not executed
|
||||
still_valid = (m_unqueued.find (*m) == m_unqueued.end ());
|
||||
m_lock.unlock ();
|
||||
if (still_valid) {
|
||||
(*m)->m_scheduled = false;
|
||||
(*m)->execute ();
|
||||
}
|
||||
}
|
||||
|
||||
m_lock.lock ();
|
||||
m_unqueued.clear ();
|
||||
m_executing.clear ();
|
||||
m_lock.unlock ();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "tlThreads.h"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
|
@ -141,7 +142,8 @@ protected:
|
|||
private:
|
||||
int m_disabled;
|
||||
bool m_scheduled;
|
||||
std::list<DeferredMethodBase *> m_methods;
|
||||
std::list<DeferredMethodBase *> m_methods, m_executing;
|
||||
std::set<DeferredMethodBase *> m_unqueued;
|
||||
tl::Mutex m_lock;
|
||||
|
||||
void do_enable (bool en);
|
||||
|
|
@ -263,8 +265,6 @@ public:
|
|||
*/
|
||||
void execute ()
|
||||
{
|
||||
// cancel execution which might be pending
|
||||
cancel ();
|
||||
(mp_t->*m_method) ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -186,3 +186,29 @@ TEST(1)
|
|||
|
||||
}
|
||||
|
||||
static int y_inst = 0;
|
||||
|
||||
class Y
|
||||
{
|
||||
public:
|
||||
Y () : da (this, &Y::a), db (this, &Y::b) { ++y_inst; }
|
||||
~Y () { --y_inst; }
|
||||
|
||||
void a () { delete this; }
|
||||
void b () { tl_assert(false); }
|
||||
|
||||
tl::DeferredMethod<Y> da, db;
|
||||
};
|
||||
|
||||
TEST(2)
|
||||
{
|
||||
// execution of a deletes db which must not be executed
|
||||
y_inst = 0;
|
||||
Y *y = new Y ();
|
||||
y->da ();
|
||||
y->db ();
|
||||
|
||||
QCoreApplication::instance ()->processEvents ();
|
||||
|
||||
EXPECT_EQ (y_inst, 0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue