void SyncUser::log_out() { if (m_is_admin) { // Admin users cannot be logged out. return; } std::lock_guard<std::mutex> lock(m_mutex); if (m_state == State::LoggedOut) { return; } m_state = State::LoggedOut; // Move all active sessions into the waiting sessions pool. If the user is // logged back in, they will automatically be reactivated. for (auto& pair : m_sessions) { if (auto ptr = pair.second.lock()) { ptr->log_out(); m_waiting_sessions[pair.first] = ptr; } } m_sessions.clear(); // Mark the user as 'dead' in the persisted metadata Realm. if (!m_is_admin) { SyncManager::shared().perform_metadata_update([=](const auto& manager) { auto metadata = SyncUserMetadata(manager, m_identity, false); metadata.mark_for_removal(); }); } }
static int rwlock_unlock(int semid, struct semid_pool *semaptr) { sysv_print("unlock id = %d %x\n", semid, semaptr); if (!sema_exist(semid, semaptr)) { /* Internal resources must be freed. */ mark_for_removal(semid); errno = EINVAL; return (-1); } #ifdef SYSV_RWLOCK sysv_rwlock_unlock(&semaptr->rwlock); #else sysv_mutex_unlock(&semaptr->mutex); #endif return (0); }
static int try_rwlock_wrlock(int semid, struct semid_pool *semaptr) { #ifdef SYSV_RWLOCK sysv_print("before wrlock id = %d %x\n", semid, semaptr); sysv_rwlock_wrlock(&semaptr->rwlock); #else sysv_print("before lock id = %d %x\n", semid, semaptr); sysv_mutex_lock(&semaptr->mutex); #endif sysv_print("lock id = %d\n", semid); if (!sema_exist(semid, semaptr)) { errno = EINVAL; sysv_print("error sema %d doesn't exist\n", semid); #ifdef SYSV_RWLOCK sysv_rwlock_unlock(&semaptr->rwlock); #else sysv_mutex_unlock(&semaptr->mutex); #endif /* Internal resources must be freed. */ mark_for_removal(semid); return (-1); } return (0); }
/* * We simplify the pattern recursively, using node "start" as a * "zipper" to zip the pattern up ("start" moves from left to * right as the recursion proceeds, and the recusion ends when * "start" reaches the end of the pattern). * * Overall strategy: We "check" whether we can remove "start" without * changing what ordinal the pointed pattern notates. But if we remove * "start", we have to remove anything connected to it (via less1, * or via decompositions), so we have to ask the same question about * all those nodes as well, which in turn requires asking the same * question about any node THEY'RE connected to, and so on. */ static pattern *simplify_recurse( pattern *p, node *start ) { node *n; pattern *q; /* * Mark all nodes in the pattern as being unchecked during this iteration */ for ( n = p->first_node; n; n = n->next ) n->simplify_data = SIMPL_UNCHECKED; /* * Under no circumstances would we remove the pattern's designated point */ if ( start == p->point ) { start = start->next; if ( !start ) return p; } /* * Attempt to mark "start" for removal. * If the attempt fails (because it would * require removing p->point) then move on * to the next start. */ if ( ! mark_for_removal(p,start,start) ) { if ( !start->next ) return p; return simplify_recurse( p, start->next ); } /* * If "start" was successfully marked for * removal, then remove it, along with anything * else that was marked as collateral damage. * Actually, do all this in a copy q of p. */ q = execute_removal(p); /* * Check whether the copy q, with "start" removed, * still notates the same ordinal that p does. * If so, continue trying to further simplify q. * If not, revert back to p and increment "start". */ if ( same_point(q,p) ) { start = isom(start,q); if ( start ) return simplify_recurse( q, start ); else return q; } else { if ( start->next ) return simplify_recurse( p, start->next ); else return p; } }
/* * Attempt to mark a node x for removal, along with (recursively) * all nodes that would also have to be removed if that node were. * Returns 0 if the pattern's designated point would have to be * removed. The node *start input keeps track of which node we * were originally wanting to remove (before getting lost in the * mazes of recursion). */ static int mark_for_removal( pattern *p, node *x, node *start ) { node *n, **d, *L; if ( x == p->point ) return 0; /* * Black-magic shortcut: * if the point we're recursively trying to mark is further left * than the original point we care about marking, then marking * x would force us to mark p->point. Why? Because if we could * have marked x, then we would have done so already, in simplify_recurse, * before even considering "start". */ if ( x->position < start->position ) return 0; /* * If x is the left endpoint of a circle and p->point lies within that * circle, then we cannot mark x for removal without marking p->point */ if ( x->position <= p->point->position && p->point->position <= x->less1->position ) return 0; /* * If we've already marked x for removal, there's nothing left to do. */ if ( x->simplify_data == SIMPL_MARKED ) return 1; /* * Mark x for removal. */ x->simplify_data = SIMPL_MARKED; /* * Now recursively mark for removal all things which would have to * be removed if we remove x. */ for ( n = x->next; n; n = n->next ) { /* * Anything which is a decomposition involving doomed nodes, is doomed. */ if ( n->decomposition ) { for ( d = n->decomposition; *d; d++ ) { if ( (*d)->simplify_data == SIMPL_MARKED ) break; } if ( *d ) { if ( !mark_for_removal( p, n, start ) ) return 0; } else { /* * Suppose n=x_1+...+x_n (a descending sum of indecomposables), and none * of the x_i have been marked for removal. It will still be necessary * to mark n for removal if any of x_1+...+x_(n-i) are marked. */ node *d_bak; // backup of *d node *acl; // "arithmetical closure" for ( d = n->decomposition; *d; d++ ) { d_bak = *d; *d = NULL; acl = get_node_by_decomposition( p, n->decomposition ); *d = d_bak; if ( acl == n ) continue; if ( acl->simplify_data == SIMPL_MARKED ) break; } if ( *d ) { if ( !mark_for_removal( p, n, start ) ) return 0; } } } } /* * If x is the left endpoint of a less1-circle, then to remove x, * we must remove everything within that circle. */ if ( x->less1 != x ) { for ( n = x->next; n->position <= x->less1->position; n = n->next ) { if ( !mark_for_removal( p, n, start ) ) return 0; } } else { /* * Otherwise, consider the case whether x is the right endpoint of * a less1-circle. We search for the leftmost (if any) node L such * that L is the left-endpoint of a circle whose right endpoint is x. */ for ( L = p->first_node; L; L = L->next ) { if ( L == x ) break; if ( L->less1 == x ) break; if ( L->less1->position < x->position ) L = L->less1; } /* * If we found a circle with left endpoint L and right endpoint x, * we are obliged to remove that circle and everything inside it. */ if ( L && L != x ) { for ( n = L; L->position < x->position; L++ ) { if ( !mark_for_removal( p, n, start ) ) return 0; } } } return 1; }