mirror of https://github.com/KLayout/klayout.git
WIP: locking of netlist for better performance.
This commit is contained in:
parent
d57ede441c
commit
54adb84e27
|
|
@ -1129,13 +1129,13 @@ size_t DeviceClass::terminal_id_for_name (const std::string &name) const
|
|||
// Netlist class implementation
|
||||
|
||||
Netlist::Netlist ()
|
||||
: m_valid_topology (false)
|
||||
: m_valid_topology (false), m_lock_count (0)
|
||||
{
|
||||
m_circuits.changed ().add (this, &Netlist::invalidate_topology);
|
||||
}
|
||||
|
||||
Netlist::Netlist (const Netlist &other)
|
||||
: m_valid_topology (false)
|
||||
: m_valid_topology (false), m_lock_count (0)
|
||||
{
|
||||
operator= (other);
|
||||
m_circuits.changed ().add (this, &Netlist::invalidate_topology);
|
||||
|
|
@ -1173,11 +1173,16 @@ Netlist &Netlist::operator= (const Netlist &other)
|
|||
void Netlist::invalidate_topology ()
|
||||
{
|
||||
if (m_valid_topology) {
|
||||
|
||||
m_valid_topology = false;
|
||||
m_top_circuits = 0;
|
||||
m_top_down_circuits.clear ();
|
||||
m_child_circuits.clear ();
|
||||
m_parent_circuits.clear ();
|
||||
|
||||
if (m_lock_count == 0) {
|
||||
m_top_circuits = 0;
|
||||
m_top_down_circuits.clear ();
|
||||
m_child_circuits.clear ();
|
||||
m_parent_circuits.clear ();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1195,6 +1200,8 @@ void Netlist::validate_topology ()
|
|||
{
|
||||
if (m_valid_topology) {
|
||||
return;
|
||||
} else if (m_lock_count > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_child_circuits.clear ();
|
||||
|
|
@ -1295,6 +1302,21 @@ void Netlist::validate_topology ()
|
|||
m_valid_topology = true;
|
||||
}
|
||||
|
||||
void Netlist::lock ()
|
||||
{
|
||||
if (m_lock_count == 0) {
|
||||
validate_topology ();
|
||||
}
|
||||
++m_lock_count;
|
||||
}
|
||||
|
||||
void Netlist::unlock ()
|
||||
{
|
||||
if (m_lock_count > 0) {
|
||||
--m_lock_count;
|
||||
}
|
||||
}
|
||||
|
||||
const tl::vector<Circuit *> &Netlist::child_circuits (Circuit *circuit)
|
||||
{
|
||||
if (! m_valid_topology) {
|
||||
|
|
|
|||
|
|
@ -1806,6 +1806,30 @@ public:
|
|||
*/
|
||||
void clear ();
|
||||
|
||||
/**
|
||||
* @brief Starts a sequence of operations during which topology updates are not desired
|
||||
*
|
||||
* If the hierarchy is modified, the topology information (top-down order, children
|
||||
* and parent information) may be recomputed frequently. This may cause performance issues
|
||||
* and may not be desired.
|
||||
*
|
||||
* Calling this method will bring the netlist into a state in which updates on the
|
||||
* list will not happen. Using "unlock" will end this state.
|
||||
*
|
||||
* "lock" and "unlock" are incremental and can be nested. Use "NetlistLocker" for safe locking
|
||||
* and unlocking.
|
||||
*
|
||||
* Before lock, the state will be validated, so inside the locked operation, the topology
|
||||
* information will be valid with respect to the initial state.
|
||||
*/
|
||||
void lock ();
|
||||
|
||||
/**
|
||||
* @brief Ends a sequence of operations during which topology updates are not desired
|
||||
* See "lock" for more details.
|
||||
*/
|
||||
void unlock ();
|
||||
|
||||
/**
|
||||
* @brief Adds a circuit to this netlist
|
||||
*
|
||||
|
|
@ -1974,6 +1998,7 @@ private:
|
|||
circuit_list m_circuits;
|
||||
device_class_list m_device_classes;
|
||||
bool m_valid_topology;
|
||||
int m_lock_count;
|
||||
tl::vector<Circuit *> m_top_down_circuits;
|
||||
tl::vector<tl::vector<Circuit *> > m_child_circuits;
|
||||
tl::vector<tl::vector<Circuit *> > m_parent_circuits;
|
||||
|
|
@ -1986,6 +2011,31 @@ private:
|
|||
const tl::vector<Circuit *> &parent_circuits (Circuit *circuit);
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief A helper class using RAII for safe locking/unlocking
|
||||
*/
|
||||
class DB_PUBLIC NetlistLocker
|
||||
{
|
||||
public:
|
||||
NetlistLocker (Netlist *netlist)
|
||||
: mp_netlist (netlist)
|
||||
{
|
||||
if (mp_netlist.get ()) {
|
||||
mp_netlist->lock ();
|
||||
}
|
||||
}
|
||||
|
||||
~NetlistLocker ()
|
||||
{
|
||||
if (mp_netlist.get ()) {
|
||||
mp_netlist->unlock ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
tl::weak_ptr<Netlist> mp_netlist;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -902,9 +902,19 @@ TEST(12_NetlistTopology)
|
|||
EXPECT_EQ (td2string (nl.get ()), "c1,c2");
|
||||
EXPECT_EQ (bu2string (nl.get ()), "c2,c1");
|
||||
|
||||
std::auto_ptr<db::NetlistLocker> locker (new db::NetlistLocker (nl.get ()));
|
||||
|
||||
db::Circuit *c3 = new db::Circuit ();
|
||||
c3->set_name ("c3");
|
||||
nl->add_circuit (c3);
|
||||
|
||||
// because we locked, it did not get updated:
|
||||
EXPECT_EQ (nl->top_circuit_count (), size_t (2));
|
||||
EXPECT_EQ (td2string (nl.get ()), "c1,c2");
|
||||
EXPECT_EQ (bu2string (nl.get ()), "c2,c1");
|
||||
locker.reset (0);
|
||||
|
||||
// after removing the lock, it's updated
|
||||
EXPECT_EQ (nl->top_circuit_count (), size_t (3));
|
||||
EXPECT_EQ (td2string (nl.get ()), "c1,c2,c3");
|
||||
EXPECT_EQ (bu2string (nl.get ()), "c3,c2,c1");
|
||||
|
|
|
|||
Loading…
Reference in New Issue