/* Do not use C_TYPECHECK on qos parameter, since it might be allocated on heap! */ kernel = v_objectKernel(p); c_lockWrite(&p->lock); result = v_participantQosSet(p->qos, qos, &cm); if ((result == V_RESULT_OK) && (cm != 0)) { builtinMsg = v_builtinCreateParticipantInfo(kernel->builtin,p); c_lockUnlock(&p->lock); v_writeBuiltinTopic(kernel, V_PARTICIPANTINFO_ID, builtinMsg); c_free(builtinMsg); } else { c_lockUnlock(&p->lock); } return result; } v_leaseManager v_participantGetLeaseManager( v_participant p) { assert(C_TYPECHECK(p,v_participant)); return c_keep(p->leaseManager); } #define RESEND_SECS (0U) #define RESEND_NANOSECS (2000000U) /* 2 ms */ void v_participantResendManagerMain( v_participant p) { c_iter writerProxies; v_proxy wp; v_writer w; v_handleResult r; c_time waitTime = { RESEND_SECS, RESEND_NANOSECS }; assert(C_TYPECHECK(p,v_participant)); c_mutexLock(&p->resendMutex); while (!p->resendQuit) { if (c_count(p->resendWriters) == 0) { c_condWait(&p->resendCond, &p->resendMutex); } else { c_condTimedWait(&p->resendCond, &p->resendMutex, waitTime); } if (!p->resendQuit) { writerProxies = c_select(p->resendWriters, 0); c_mutexUnlock(&p->resendMutex); wp = v_proxy(c_iterTakeFirst(writerProxies)); while (wp != NULL) { r = v_handleClaim(wp->source,(v_object *)&w); if (r == V_HANDLE_OK) { assert(C_TYPECHECK(w,v_writer)); v_writerResend(w); v_handleRelease(wp->source); } c_free(wp); wp = v_proxy(c_iterTakeFirst(writerProxies)); } c_iterFree(writerProxies); c_mutexLock(&p->resendMutex); } /* already quiting */ } c_mutexUnlock(&p->resendMutex); }
v_result v_deliveryWaitListWait ( v_deliveryWaitList _this, v_duration timeout) { v_result result = V_RESULT_OK; c_syncResult r; assert(C_TYPECHECK(_this,v_deliveryWaitList)); if (_this->readerGID != NULL) { c_mutexLock(&_this->mutex); if(c_timeCompare(timeout, C_TIME_INFINITE) != C_EQ) { r = c_condTimedWait(&_this->cv,&_this->mutex,timeout); } else { r = c_condWait(&_this->cv,&_this->mutex); } c_mutexUnlock(&_this->mutex); switch (r) { case SYNC_RESULT_SUCCESS: result = V_RESULT_OK; break; case SYNC_RESULT_TIMEOUT: result = V_RESULT_TIMEOUT; break; case SYNC_RESULT_UNAVAILABLE: case SYNC_RESULT_BUSY: case SYNC_RESULT_INVALID: case SYNC_RESULT_FAIL: default: result = V_RESULT_PRECONDITION_NOT_MET; break; } } return result; }
c_ulong v__observerWait( v_observer o) { os_result result = os_resultSuccess; c_ulong flags; assert(o != NULL); assert(C_TYPECHECK(o,v_observer)); if (o->eventFlags == 0) { o->waitCount++; result = c_condWait(&o->cv,&o->mutex); o->waitCount--; } flags = o->eventFlags; /* Reset events but remember destruction event. * To avoid any further use of this observer in case of destruction. */ o->eventFlags &= V_EVENT_OBJECT_DESTROYED; return flags; }
v_networkReaderWaitResult v_networkQueueWait( v_networkQueue queue) { v_networkReaderWaitResult result = V_WAITRESULT_NONE; c_syncResult syncResult; c_bool hasChanged; c_time interval; c_time minSleepTime = MIN_SLEEPTIME; c_equality eq; c_mutexLock(&queue->mutex); /* First update nextWakeup */ v_networkQueueUpdateNextWakeup(queue, &hasChanged); if (hasChanged) { result |= V_WAITRESULT_TIMEOUT; } /* With the new nextWakeup, check if any data is expiring */ if ((int)v_networkQueueHasExpiringData(queue)) { result |= V_WAITRESULT_MSGWAITING; } /* Also check if no request has been issued lately */ if ((int)queue->triggered) { result |= V_WAITRESULT_TRIGGERED; } /* Now go to sleep if needed */ while (result == V_WAITRESULT_NONE) { if (queue->periodic) { c_time org = v_timeGet(); interval = c_timeSub(queue->nextWakeup,org); eq = c_timeCompare(minSleepTime, interval); if (eq == C_LT) { queue->threadWaiting = TRUE; syncResult = c_condTimedWait(&queue->cv, &queue->mutex, interval); queue->threadWaiting = FALSE; } else { syncResult = SYNC_RESULT_TIMEOUT; } if (syncResult == SYNC_RESULT_TIMEOUT) { result |= V_WAITRESULT_TIMEOUT; queue->nextWakeup = c_timeAdd(queue->nextWakeup, queue->resolution); } } else { /* Wait infinitely if the queue is not periodic */ queue->threadWaiting = TRUE; syncResult = c_condWait(&queue->cv, &queue->mutex); queue->threadWaiting = FALSE; } /* Test current status of queue */ if ((int)queue->triggered) { result |= V_WAITRESULT_TRIGGERED; } if (v_networkQueueHasExpiringData(queue)) { result |= V_WAITRESULT_MSGWAITING; } } queue->triggered = 0; c_mutexUnlock(&queue->mutex); return result; }
v_historyResult v_readerWaitForHistoricalDataWithCondition( v_reader _this, c_char* filter, c_char* params[], c_ulong paramsLength, c_time minSourceTime, c_time maxSourceTime, struct v_resourcePolicy *resourceLimits, c_time timeout) { c_iter entries; c_object e; v_historyResult result; v_historicalDataRequest request; c_bool doRequest, doWait; struct historicalWaitArg arg; C_STRUCT(v_event) event; arg._expire_time = c_timeAdd(v_timeGet(), timeout); arg._status = TRUE; request = v_historicalDataRequestNew(v_objectKernel(_this), filter, params, paramsLength, minSourceTime, maxSourceTime, resourceLimits); if(request){ V_READER_LOCK(_this); if(_this->historicalDataRequest) { /* Historical data request already in progress or complete, check * whether request is equal to the original one. */ doRequest = FALSE; if(v_historicalDataRequestEquals(request, _this->historicalDataRequest)){ /* Request is equal to original request*/ result = V_HISTORY_RESULT_OK; if(_this->historicalDataComplete){ /* Request has already been fulfilled. Consider this call * a no-operation. */ doWait = FALSE; } else { /* Request is still in progress, wait for data to arrive*/ doWait = TRUE; } } else { /* The requested parameters are not equal to the originally * requested set. Return a precondition not met. */ doWait = FALSE; result = V_HISTORY_RESULT_PRE_NOT_MET; } c_free(request); } else { /* No active request, so validate it now.*/ if(v_historicalDataRequestIsValid(request, _this)){ /* This request is valid, so request data.*/ doRequest = TRUE; doWait = TRUE; result = V_HISTORY_RESULT_OK; _this->historicalDataRequest = request; } else { /* Request is not valid, so return bad parameter.*/ doRequest = FALSE; doWait = FALSE; result = V_HISTORY_RESULT_BAD_PARAM; c_free(request); } } V_READER_UNLOCK(_this); } else { doRequest = FALSE; doWait = FALSE; result = V_HISTORY_RESULT_ERROR; } if(doWait){ v_readerEntrySetLock(_this); entries = c_select(_this->entrySet.entries, 0); v_readerEntrySetUnlock(_this); if(doRequest){ /* Historical data must be requested, since this is the first time * the operation is called and the request is valid. */ if (_this->qos->durability.kind == V_DURABILITY_VOLATILE) { /* If reader is volatile, the historical data from the * group(s) has/have not been retrieved yet, so do it now. */ e = c_iterTakeFirst(entries); while (e != NULL) { getHistoricalData(e, _this->historicalDataRequest); c_free(e); e = c_iterTakeFirst(entries); } c_iterFree(entries); } event.kind = V_EVENT_HISTORY_REQUEST; event.source = v_publicHandle(v_public(_this)); event.userData = _this->historicalDataRequest; v_observableNotify(v_observable(v_objectKernel(_this)),&event); } V_READER_LOCK(_this); if(!_this->historicalDataComplete){ if (c_timeCompare(timeout, C_TIME_INFINITE) != C_EQ) { if (c_condTimedWait(&_this->historicalDataCondition, &V_READER_GET_LOCK(_this), timeout) != SYNC_RESULT_SUCCESS) { result = V_HISTORY_RESULT_TIMEOUT; } } else if (c_condWait(&_this->historicalDataCondition, &V_READER_GET_LOCK(_this)) != SYNC_RESULT_SUCCESS) { result = V_HISTORY_RESULT_TIMEOUT; } assert( (result == V_HISTORY_RESULT_OK) == _this->historicalDataComplete); } V_READER_UNLOCK(_this); } return result; }
/************************************************************** * Main / notify fnctions **************************************************************/ void v_leaseManagerMain( v_leaseManager _this) { v_leaseAction leaseAction; c_time waitTime = C_TIME_ZERO; c_time expTime; v_duration duration; struct collectExpiredArg arg; c_syncResult waitResult = SYNC_RESULT_SUCCESS; assert(_this != NULL); assert(C_TYPECHECK(_this, v_leaseManager)); c_mutexLock(&_this->mutex); /* initialize the current time once before the loop */ arg.now = v_timeGet(); while (_this->quit == FALSE) { if (_this->firstLeaseToExpire != NULL) { v_leaseGetExpiryAndDuration(_this->firstLeaseToExpire->lease, &expTime, &duration); if (c_timeCompare(expTime, C_TIME_INFINITE) != C_EQ) { waitTime = c_timeSub(expTime, arg.now); if (c_timeCompare(waitTime, C_TIME_ZERO) == C_GT) { waitResult = c_condTimedWait(&_this->cond, &_this->mutex, waitTime); } else { /* If the duration specified with the lease is C_TIME_ZERO, * it is expected that the expiryTime lies in the past, so * only warn if an actual duration was specified. */ if(c_timeCompare(duration, C_TIME_ZERO) != C_EQ){ OS_REPORT(OS_WARNING, "v_leaseManager", 0, "The wait time has become negative! This means " "that the leaseManager could not wake up in time to " "evaluate the lease expiry statusses. This could be " "due to scheduling problems or clock alignment issues on " "multi core machines. The lease manager will continue to " "function normal after this though."); } } } else { /* The shortest expiry time is from a lease with an infinite duration. So * wait indefinately */ waitResult = c_condWait(&_this->cond, &_this->mutex); } } else { /* no leases registered, so wait until the first one is registered */ waitResult = c_condWait(&_this->cond, &_this->mutex); } if (waitResult == SYNC_RESULT_FAIL) { OS_REPORT(OS_CRITICAL, "v_leaseManagerMain", 0, "c_condTimedWait / c_condWait failed - thread will terminate"); break; } /** * First walk through the collection of leases and record all * expired leases in an iterator. We cannot remove expired leases * while walking through the set, since it interferes with the * walk. * Any lease with a repeat bool to TRUE will automatically be renewed * while collecting all the leases. */ arg.expiredLeases = NULL; arg.firstLeaseToExpire = NULL; arg.now = v_timeGet(); c_setWalk(_this->leases, collectExpired, &arg); c_free(_this->firstLeaseToExpire); _this->firstLeaseToExpire = arg.firstLeaseToExpire;/* takes over ref count from arg object */ c_mutexUnlock(&_this->mutex); leaseAction = v_leaseAction(c_iterTakeFirst(arg.expiredLeases)); while (leaseAction != NULL) { if(!leaseAction->repeat) { v_leaseManagerDeregister(_this, leaseAction->lease); } v_leaseManagerProcessLeaseAction(_this, leaseAction, arg.now); c_free(leaseAction); leaseAction = v_leaseAction(c_iterTakeFirst(arg.expiredLeases)); } c_iterFree(arg.expiredLeases); c_mutexLock(&_this->mutex); } _this->quit = FALSE; /* for a next time */ c_mutexUnlock(&_this->mutex); }