/* Cria uma lista ligada para representar o conjunto dos termos */ void new_lst (TERMO *head, int size, char *body[]) { int i; TERMO *p; for (i = 0, p = head; i < size; i++, p = p->next) p->next = new_t (body[i]); }
// Apply transformations of the form // // (ite c (+ k1 a) (+ k2 a)) --> (+ (ite c k1 k2) a) // (ite c (* k1 a) (* k2 a)) --> (* (ite c k1 k2) a) // // These transformations are useful for bit-vector problems, since // they will minimize the number of adders/multipliers/etc br_status push_ite(func_decl * f, unsigned num, expr * const * args, expr_ref & result) { if (!m().is_ite(f)) return BR_FAILED; expr * c = args[0]; expr * t = args[1]; expr * e = args[2]; func_decl * f_prime = 0; expr_ref new_t(m()), new_e(m()), common(m()); bool first; TRACE("push_ite", tout << "unifying:\n" << mk_ismt2_pp(t, m()) << "\n" << mk_ismt2_pp(e, m()) << "\n";);
void solver_na2as::assert_expr(expr * t, expr * a) { if (a == nullptr) { assert_expr(t); } else { SASSERT(is_uninterp_const(a)); SASSERT(m.is_bool(a)); TRACE("solver_na2as", tout << "asserting\n" << mk_ismt2_pp(t, m) << "\n" << mk_ismt2_pp(a, m) << "\n";); m_assumptions.push_back(a); expr_ref new_t(m); new_t = m.mk_implies(a, t); assert_expr(new_t); }
int main() { const auto n = std::thread::hardware_concurrency(); std::cout << n << " concurrent threads are supported.\n"; //////////////////////////////////////// // Invoke Each Thread //////////////////////////////////////// { std::thread t(f1); // no parameter t.join(); } { std::thread t(f2, 1); // pass by value t.join(); } { int data = 42; std::cout << "before: " << data << std::endl; std::thread t(f3, std::ref(data)); // pass by reference, need std::ref t.join(); std::cout << "after: " << data << std::endl; } { int data = 42; std::cout << "before: " << data << std::endl; std::thread t(f4, std::ref(data)); std::thread new_t(std::move(t)); // new_t is now running f4(), t is no longer a thread new_t.join(); std::cout << "after: " << data << std::endl; } //////////////////////////////////////// // Async & Future //////////////////////////////////////// { int data = 42; // explicitly use std::launch::async to force program use thread auto future = std::async(std::launch::async, &f4, std::ref(data)); future.wait(); std::cout << "result from future: " << future.get() << std::endl; } //////////////////////////////////////// // Promise //////////////////////////////////////// { int data = 42; std::promise<int> myPromise; auto future = myPromise.get_future(); std::thread t(f5, std::ref(data), std::move(myPromise)); future.wait(); std::cout << "future.get(): " << future.get() << std::endl; t.join(); } //////////////////////////////////////// // packaged_task //////////////////////////////////////// { // future from a packaged_task std::packaged_task<int(int, int)> task([=](int a, int b){ return a+b; }); // wrap the function std::future<int> future = task.get_future(); // get a future std::thread(std::move(task), 42, 56).detach(); // launch on a thread future.wait(); std::cout << "future.get(): " << future.get() << std::endl; } { std::packaged_task<int(int, int)> task([=](int a, int b){ return a+b; }); // wrap the function std::future<int> future = task.get_future(); // get a future task(42, 56); // launch on same thread, this will block std::cout << "future.get(): " << future.get() << std::endl; task.reset(); // re-use same task object future = task.get_future(); // re-get the future std::thread(std::move(task), 43, 57).detach(); // launch on another thread future.wait(); std::cout << "future.get(): " << future.get() << std::endl; } return 0; }
/* atomic "new_tran" construct; it returns: <0 on error +1 if a request did not match a transaction - it that was an ack, the calling function shall forward statelessly - otherwise it means, a new transaction was introduced and the calling function shall reply/relay/whatever_appropriate 0 on retransmission */ int t_newtran( struct sip_msg* p_msg ) { int lret, my_err; int canceled; /* is T still up-to-date ? */ DBG("DEBUG: t_newtran: msg id=%d , global msg id=%d ," " T on entrance=%p\n",p_msg->id,global_msg_id,T); if ( T && T!=T_UNDEFINED ) { /* ERROR message moved to w_t_newtran */ DBG("DEBUG: t_newtran: " "transaction already in process %p\n", T ); return E_SCRIPT; } global_msg_id = p_msg->id; T = T_UNDEFINED; /* first of all, parse everything -- we will store in shared memory and need to have all headers ready for generating potential replies later; parsing later on demand is not an option since the request will be in shmem and applying parse_headers to it would intermix shmem with pkg_mem */ if (parse_headers(p_msg, HDR_EOH_F, 0 )) { LOG(L_ERR, "ERROR: t_newtran: parse_headers failed\n"); return E_BAD_REQ; } if ((p_msg->parsed_flag & HDR_EOH_F)!=HDR_EOH_F) { LOG(L_ERR, "ERROR: t_newtran: EoH not parsed\n"); return E_OUT_OF_MEM; } /* t_lookup_requests attempts to find the transaction; it also calls check_transaction_quadruple -> it is safe to assume we have from/callid/cseq/to */ lret = t_lookup_request( p_msg, 1 /* leave locked if not found */, &canceled ); /* on error, pass the error in the stack ... nothing is locked yet if 0 is returned */ if (lret==0) return E_BAD_TUPEL; /* transaction found, it's a retransmission */ if (lret>0) { if (p_msg->REQ_METHOD==METHOD_ACK) { t_release_transaction(T); } else { t_retransmit_reply(T); } /* things are done -- return from script */ return 0; } /* from now on, be careful -- hash table is locked */ if (lret==-2) { /* was it an e2e ACK ? if so, trigger a callback */ /* no callbacks? complete quickly */ if ( !has_tran_tmcbs(t_ack,TMCB_E2EACK_IN) ) { UNLOCK_HASH(p_msg->hash_index); return 1; } REF_UNSAFE(t_ack); UNLOCK_HASH(p_msg->hash_index); /* we don't call from within REPLY_LOCK -- that introduces * a race condition; however, it is so unlikely and the * impact is so small (callback called multiple times of * multiple ACK/200s received in parallel), that we do not * better waste time in locks */ if (unmatched_totag(t_ack, p_msg)) { run_trans_callbacks( TMCB_E2EACK_IN , t_ack, p_msg, 0, -p_msg->REQ_METHOD ); } UNREF(t_ack); return 1; } /* transaction not found, it's a new request (lret<0, lret!=-2); establish a new transaction ... */ if (p_msg->REQ_METHOD==METHOD_ACK) { /* ... unless it is in ACK */ my_err=1; goto new_err; } my_err=new_t(p_msg); if (my_err<0) { LOG(L_ERR, "ERROR: t_newtran: new_t failed\n"); goto new_err; } if (canceled) T->flags|=T_CANCELED; /* mark it for future ref. */ UNLOCK_HASH(p_msg->hash_index); /* now, when the transaction state exists, check if there is a meaningful Via and calculate it; better do it now than later: state is established so that subsequent retransmissions will be absorbed and will not possibly block during Via DNS resolution; doing it later would only burn more CPU as if there is an error, we cannot relay later whatever comes out of the the transaction */ if (!init_rb( &T->uas.response, p_msg)) { LOG(L_ERR, "ERROR: t_newtran: unresolvable via1\n"); put_on_wait( T ); t_unref(p_msg); return E_BAD_VIA; } return 1; new_err: UNLOCK_HASH(p_msg->hash_index); return my_err; }
/* atomic "new_tran" construct; it returns: <0 on error +1 if a request did not match a transaction - it that was an ack, the calling function shall forward statelessly - otherwise it means, a new transaction was introduced and the calling function shall reply/relay/whatever_appropriate 0 on retransmission */ int t_newtran( struct sip_msg* p_msg, int full_uas ) { int lret, my_err; context_p ctx_backup; /* is T still up-to-date ? */ LM_DBG("transaction on entrance=%p\n",T); if ( T && T!=T_UNDEFINED ) { LM_DBG("transaction already in process %p\n", T ); return E_SCRIPT; } T = T_UNDEFINED; /* first of all, parse everything -- we will store in shared memory and need to have all headers ready for generating potential replies later; parsing later on demand is not an option since the request will be in shmem and applying parse_headers to it would intermix shmem with pkg_mem */ if (parse_headers(p_msg, HDR_EOH_F, 0 )<0) { LM_ERR("parse_headers failed\n"); return E_BAD_REQ; } if ((p_msg->parsed_flag & HDR_EOH_F)!=HDR_EOH_F) { LM_ERR("EoH not parsed\n"); return E_OUT_OF_MEM; } /* t_lookup_requests attempts to find the transaction; it also calls check_transaction_quadruple -> it is safe to assume we have from/callid/cseq/to */ lret = t_lookup_request( p_msg, 1 /* leave locked if not found */ ); /* on error, pass the error in the stack ... nothing is locked yet if 0 is returned */ if (lret==0) return E_BAD_TUPEL; /* transaction found, it's a retransmission */ if (lret>0) { if (p_msg->REQ_METHOD==METHOD_ACK) { t_release_transaction(T); } else { t_retransmit_reply(T); } /* hide the transaction from the upper layer */ t_unref( p_msg ); /* things are done -- return from script */ return 0; } /* from now on, be careful -- hash table is locked */ if (lret==-2) { /* was it an e2e ACK ? if so, trigger a callback */ if (e2eack_T->relaied_reply_branch==-2) { /* if a ACK for a local replied transaction, release the INVITE transaction and break the script -> simply absorb the ACK request */ t_release_transaction(e2eack_T); return 0; } LM_DBG("building branch for end2end ACK - flags=%X\n",e2eack_T->flags); /* to ensure unigueness acros time and space, compute the ACK * branch in the same maner as for INVITE, but put a t->branch * value that cannot exist for that INVITE - as it is compute as * an INVITE, it will not overlapp with other INVITEs or requests. * But the faked value for t->branch guarantee no overalap with * corresponding INVITE --bogdan */ if (!t_calc_branch(e2eack_T, e2eack_T->nr_of_outgoings+1, p_msg->add_to_branch_s, &p_msg->add_to_branch_len )) { LM_ERR("ACK branch computation failed\n"); } return 1; } /* transaction not found, it's a new request (lret<0, lret!=-2); establish a new transaction ... */ if (p_msg->REQ_METHOD==METHOD_ACK) /* ... unless it is in ACK */ return 1; my_err=new_t(p_msg, full_uas); if (my_err<0) { LM_ERR("new_t failed\n"); goto new_err; } UNLOCK_HASH(p_msg->hash_index); /* now, when the transaction state exists, check if there is a meaningful Via and calculate it; better do it now than later: state is established so that subsequent retransmissions will be absorbed and will not possibly block during Via DNS resolution; doing it later would only burn more CPU as if there is an error, we cannot relay later whatever comes out of the the transaction */ if (!init_rb( &T->uas.response, p_msg)) { LM_ERR("unresolvable via1\n"); put_on_wait( T ); t_unref(p_msg); return E_BAD_VIA; } if (auto_100trying && p_msg->REQ_METHOD==METHOD_INVITE) { ctx_backup = current_processing_ctx; current_processing_ctx = NULL; t_reply( T, p_msg , 100 , &relay_reason_100); current_processing_ctx = ctx_backup; } return 1; new_err: UNLOCK_HASH(p_msg->hash_index); return my_err; }
/* Verifica se um termo pertence a um intervalo fazendo as devidas ligacoes na lista de intervalos. Devolve a ultima celula da lista. */ TERMO *chk_t (TERMO *head, char maxt[], TERMO *last, int vars) { TERMO *p, *buff, *ab; int i, j, stop, remove = 0; char *interval; ab = last; for (p = head->next; p != NULL; p = p->next) { stop = 0; buff = p; remove = 0; for (i = 0; i < vars; i++) { if (p->body[i] == 'x') { interval = (char*) calloc (vars, sizeof(char)); interval[i] = compl(maxt[i]); /* Copia os termos restantes */ for (j = i + 1; j < vars; j++) { if (p->body[j] == compl(maxt[j])) { stop++; break; } else interval[j] = p->body[j]; } if (stop != 0) { free (interval); break; } for (j = i - 1; j >= 0; j--) { if (p->body[j] == compl(maxt[j])) { stop++; break; } else interval[j] = p->body[j]; } if (stop != 0) { free( interval); break; } /* Cria a celula com o novo intervalo filho. Marca que o intervalo pai deve ser removido ao final */ ab->next = new_t(interval); ab = ab->next; remove = 1; } else if (p->body[i] != maxt[i]) break; } if (remove == 1) rm_t (head, buff); printf("chk:\n"); printb (head, vars); if (p == last) break; } return ab; }