📄 transact.cxx
字号:
}const std::vector<CdlConflict>&CdlTransactionBody::get_deleted_structural_conflicts() const{ CYG_REPORT_FUNCNAME("CdlTransaction::get_deleted_structural_conflicts"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return deleted_structural_conflicts;}const std::vector<CdlConflict>&CdlTransactionBody::get_resolved_conflicts() const{ CYG_REPORT_FUNCNAME("CdlTransaction::get_resolved_conflicts"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return resolved_conflicts;}const std::list<CdlConflict>&CdlTransactionBody::get_global_conflicts_with_solutions() const{ CYG_REPORT_FUNCNAME("CdlTransaction::get_global_conflicts_with_solutions"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return global_conflicts_with_solutions;}//}}}//}}}//{{{ Commit/cancel operations // ----------------------------------------------------------------------------voidCdlTransactionBody::add_commit_cancel_op(CdlTransactionCommitCancelOp* op){ CYG_REPORT_FUNCNAME("CdlTransaction::add_commit_cancel_op"); CYG_REPORT_FUNCARG2XV(this, op); CYG_PRECONDITION_THISC(); CYG_PRECONDITIONC(0 != op); commit_cancel_ops.push_back(op); CYG_REPORT_RETURN();}voidCdlTransactionBody::cancel_last_commit_cancel_op(){ CYG_REPORT_FUNCNAME("CdlTransaction::cancel_last_commit_cancel_op"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CdlTransactionCommitCancelOp* op = *(commit_cancel_ops.rbegin()); commit_cancel_ops.pop_back(); op->cancel(this); delete op; CYG_REPORT_RETURN();}CdlTransactionCommitCancelOp*CdlTransactionBody::get_last_commit_cancel_op() const{ CYG_REPORT_FUNCNAMETYPE("CdlTransaction::get_last_commit_cancel_op", "result %p"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CdlTransactionCommitCancelOp* op = *(commit_cancel_ops.rbegin()); CYG_REPORT_RETVAL(op); return op;}const std::vector<CdlTransactionCommitCancelOp*>&CdlTransactionBody::get_commit_cancel_ops() const{ CYG_REPORT_FUNCNAME("CdlTransaction::get_commit_cancel_ops"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return commit_cancel_ops;}//}}}//{{{ Propagation // ----------------------------------------------------------------------------// Propagation should happen whenever one or more changes have been applied,// so that the impact of these changes on other parts of the configuration// can be fully assessed. The transaction keeps track of all the changes// to date and invokes appropriate node and property update handlers.voidCdlTransactionBody::propagate(){ CYG_REPORT_FUNCNAME("CdlTransaction::propagate"); CYG_REPORT_FUNCARG1XV(this); CYG_INVARIANT_THISC(CdlTransactionBody); // Now it is time to worry about value and active changes. // Propagation may result in new entries, so only the // front item of one of the vectors is modified. while ((0 < value_changes.size()) || (0 < active_changes.size())) { if (0 != value_changes.size()) { CdlValuable valuable = value_changes.front(); value_changes.pop_front(); // A value change may invalidate one or more solutions. // This happens during propagation rather than at the time // that the value is actually changed, so that multiple // solutions can be applied in one go. std::list<CdlConflict>::iterator conf_i, conf_j; for (conf_i = new_conflicts.begin(); conf_i != new_conflicts.end(); conf_i++) { CYG_LOOP_INVARIANT_CLASSC(*conf_i); (*conf_i)->update_solution_validity(valuable); } for (conf_i = global_conflicts_with_solutions.begin(); conf_i != global_conflicts_with_solutions.end(); ) { CYG_LOOP_INVARIANT_CLASSC(*conf_i); conf_j = conf_i++; (*conf_j)->update_solution_validity(valuable); if (!(*conf_j)->has_known_solution()) { global_conflicts_with_solutions.erase(conf_j); } } // If the valuable is no longer loaded then there is // no need to worry about propagation if (0 != valuable->get_toplevel()) { // Inform the valuable itself about the update, so that // e.g. the value can be checked against legal_values valuable->update(this, CdlUpdate_ValueChange); std::vector<CdlReferrer>& referrers = valuable->referrers; std::vector<CdlReferrer>::iterator ref_i; for (ref_i = referrers.begin(); ref_i != referrers.end(); ref_i++) { ref_i->update(this, valuable, CdlUpdate_ValueChange); } } } else { CdlNode node = active_changes.front(); active_changes.pop_front(); if (0 != node->get_toplevel()) { node->update(this, CdlUpdate_ActiveChange); std::vector<CdlReferrer>& referrers = node->referrers; std::vector<CdlReferrer>::iterator ref_i; for (ref_i = referrers.begin(); ref_i != referrers.end(); ref_i++) { ref_i->update(this, node, CdlUpdate_ActiveChange); } } } } CYG_REPORT_RETURN();}// ----------------------------------------------------------------------------boolCdlTransactionBody::is_propagation_required() const{ CYG_REPORT_FUNCNAMETYPE("CdlTransaction::is_propagation_required", "result %d"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); bool result = false; if ((0 != value_changes.size()) || (0 != active_changes.size())) { result = true; } CYG_REPORT_RETVAL(result); return result;}// ----------------------------------------------------------------------------voidCdlTransactionBody::add_legal_values_change(CdlValuable valuable){ CYG_REPORT_FUNCNAME("CdlTransaction::add_legal_values_change"); CYG_REPORT_FUNCARG2XV(this, valuable); CYG_PRECONDITION_THISC(); CYG_PRECONDITION_CLASSC(valuable); legal_values_changes.insert(valuable); CYG_REPORT_RETURN();}const std::set<CdlValuable>&CdlTransactionBody::get_legal_values_changes() const{ CYG_REPORT_FUNCNAME("CdlTransaction::get_legal_values_changes"); CYG_REPORT_FUNCARG1XV(this); CYG_PRECONDITION_THISC(); CYG_REPORT_RETURN(); return legal_values_changes;}//}}}//{{{ Cancel // ----------------------------------------------------------------------------// Cancellation is straightforward, essentially it just involves clearing// out all of the STL containers. The transaction object can then be-used,// so fields like parent and toplevel must not change.voidCdlTransactionBody::cancel(){ CYG_REPORT_FUNCNAME("CdlTransaction::cancel"); CYG_REPORT_FUNCARG1XV(this); CYG_INVARIANT_THISC(CdlTransactionBody); // First take care of the cancel ops, if any, in case a cancel op // depends on some of the other transaction state. std::vector<CdlTransactionCommitCancelOp*>::reverse_iterator cancel_i; for (cancel_i = commit_cancel_ops.rbegin(); cancel_i != commit_cancel_ops.rend(); cancel_i++) { (*cancel_i)->cancel(this); delete *cancel_i; *cancel_i = 0; } commit_cancel_ops.clear(); this->changes.clear(); std::list<CdlConflict>::iterator conf_i; for (conf_i = this->new_conflicts.begin(); conf_i != this->new_conflicts.end(); conf_i++) { CYG_LOOP_INVARIANT_CLASSC(*conf_i); delete *conf_i; } this->new_conflicts.clear(); for (conf_i = this->new_structural_conflicts.begin(); conf_i != this->new_structural_conflicts.end(); conf_i++) { CYG_LOOP_INVARIANT_CLASSC(*conf_i); delete *conf_i; } this->new_structural_conflicts.clear(); this->deleted_structural_conflicts.clear(); this->deleted_conflicts.clear(); // Any conflicts created and resolved during this transaction will // still be present in resolved_conflicts. Some global conflicts // may be there as well. std::vector<CdlConflict>::iterator conf_i2; for (conf_i2 = this->resolved_conflicts.begin(); conf_i2 != this->resolved_conflicts.end(); conf_i2++) { if (this == (*conf_i2)->transaction) { delete (*conf_i2); } } this->resolved_conflicts.clear(); // Any global conflicts which have been updated with a solution need // to have that solution cleared. Currently no attempt is made to // keep solutions valid for global conflicts. for (conf_i = this->global_conflicts_with_solutions.begin(); conf_i != this->global_conflicts_with_solutions.end(); conf_i++) { CYG_LOOP_INVARIANT_CLASSC(*conf_i); (*conf_i)->clear_solution(); } this->global_conflicts_with_solutions.clear(); this->activated.clear(); this->deactivated.clear(); this->legal_values_changes.clear(); this->value_changes.clear(); this->active_changes.clear(); CYG_REPORT_RETURN();}//}}}//{{{ Commit // ----------------------------------------------------------------------------// The commit operation. There are two main branches for this code. The// first branch deals with sub-transactions, and basically involves// transferring changes from the sub-transaction to the parent. It is// assumed that the sub-transaction has been fully propagated, so// data can just be transferred from the child to the parent.//// The second branch involves committing changes from a transaction to// the toplevel, invoking the transaction callback if necessary.voidCdlTransactionBody::commit(){ CYG_REPORT_FUNCNAME("CdlTransaction::commit"); CYG_REPORT_FUNCARG1XV(this); CYG_INVARIANT_THISC(CdlTransactionBody); std::map<CdlValuable, CdlValue>::iterator map_i; std::list<CdlConflict>::iterator conf_i, conf_j; std::vector<CdlConflict>::const_iterator conf_i2, conf_j2; std::set<CdlNode>::iterator set_i, set_j, set_k; std::set<CdlValuable>::iterator set_i2, set_j2; if (0 != parent) { // Any conflicts that were solved by the inference engine further // down are still resolved. // Great care has to be taken with conflict ownership. The following // cases have to be considered. // 1) the resolved conflict is global, its transaction is zero, this // conflict must only be destroyed if the toplevel transaction // is committed - at which time time the conflict should appear // on the deleted_conflicts lists. // 2) the conflict belongs to a higher level transaction, we have // recursed a certain amount trying to resolve it e.g. to explore // OR branches of the tree. Again the resolved conflict can only // be destroyed when the appropriate higher-level commit happens, // and should appear on the deleted conflicts list. // 3) the conflict was created and resolved further down the tree. // We are keeping it around for informational purposes only. // Associating it with this transaction allows the code to // distinguish this case from (1) and (2). for (conf_i2 = resolved_conflicts.begin(); conf_i2 != resolved_conflicts.end(); conf_i2++) { CdlConflict conf = *conf_i2; CYG_LOOP_INVARIANT_CLASSC(conf); CYG_LOOP_INVARIANTC(parent->resolved_conflicts.end() == \ std::find(parent->resolved_conflicts.begin(), \ parent->resolved_conflicts.end(), conf)); parent->resolved_conflicts.push_back(conf); parent->dirty = true; if (this == conf->transaction) { conf->transaction = parent; } } resolved_conflicts.clear(); // Any global conflicts for which solutions were found in the // sub-transaction still have solutions in the parent. for (conf_i = global_conflicts_with_solutions.begin(); conf_i != global_conflicts_with_solutions.end(); conf_i++) { CdlConflict conf = *conf_i; CYG_LOOP_INVARIANT_CLASSC(conf); // It is not clear that this search is actually useful, especially // given that the solution is currently stored with the conflict // rather than with the transaction. conf_j = std::find(parent->global_conflicts_with_solutions.begin(), parent->global_conflicts_with_solutions.end(), conf); if (conf_j == parent->global_conflicts_with_solutions.end()) { parent->global_conflicts_with_solutions.push_back(conf); parent->dirty = true; } } global_conflicts_with_solutions.clear(); // Now take care of deleted conflicts. for (conf_i2 = deleted_conflicts.begin(); conf_i2 != deleted_conflicts.end(); conf_i2++) { CdlConflict conf = *conf_i2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -