c_bool v_networkQueueTakeFirst( v_networkQueue queue, v_message *message, v_networkReaderEntry *entry, c_ulong *sequenceNumber, v_gid *sender, c_bool *sendTo, /* for p2p writing */ v_gid *receiver, c_time *sendBefore, c_ulong *priority, c_bool *more) { c_bool result = FALSE; v_networkStatusMarker currentMarker; v_networkQueueSample sample; *more = FALSE; c_mutexLock(&queue->mutex); currentMarker = queue->firstStatusMarker; /* Note: the current design expects that this function has been preceded * by a NetworkReaderWait. Therefore, the currentMarker should never * be NULL. */ if (currentMarker != NULL) { sample = currentMarker->firstSample; assert(sample != NULL); result = TRUE; V_MESSAGE_STAMP(sample->message,readerDataAvailableTime); /* Copy values */ *message = sample->message; /* no keep, transfer refCount */ sample->message = NULL; /* clean reference because of refCount transfer */ *entry = sample->entry; /* no keep, transfer refCount */ sample->entry = NULL; /* clean reference because of refCount transfer */ *sequenceNumber = sample->sequenceNumber; *sender = sample->sender; *sendTo = sample->sendTo; *receiver = sample->receiver; *sendBefore = currentMarker->sendBefore; *priority = currentMarker->priority; /* Remove and free holder */ queue->currentMsgCount--; /* numberOfSamplesTaken+ & numberOfSamplesWaiting- stats */ v_networkQueueStatisticsAdd(numberOfSamplesTaken,queue->statistics); v_networkQueueStatisticsCounterDec(numberOfSamplesWaiting,queue->statistics); currentMarker->firstSample = sample->next; /* no keep, transfer refCount */ sample->next = queue->freeSamples; queue->freeSamples = sample; if (currentMarker->firstSample == NULL) { queue->firstStatusMarker = currentMarker->next; /* no keep, transfer refCount */ currentMarker->next = queue->freeStatusMarkers; queue->freeStatusMarkers = currentMarker; if (queue->firstStatusMarker == NULL) { queue->lastStatusMarker = NULL; } } *more = (queue->firstStatusMarker != NULL); } else { *message = NULL; *entry = NULL; *more = FALSE; } c_mutexUnlock(&queue->mutex); return result; }
v_actionResult v_dataViewSampleReadTake( v_dataViewSample sample, v_readerSampleAction action, c_voidp arg, c_bool consume) { v_dataViewInstance instance; v_state state; v_state mask; v_actionResult result = 0; instance = v_dataViewSampleInstance(sample); state = v_instanceState(instance); mask = L_NEW | L_DISPOSED | L_NOWRITERS; /* Copy the value of instance state bits specified by the mask * to the sample state bits without affecting other bits. */ v_readerSampleSetState(sample,(state & mask)); v_readerSampleClearState(sample,(~state & mask)); /* If the status of the sample is READ by the previous read * operation and the flag is not yet set (specified by the * LAZYREAD flag) then correct the state before executing the * read action. */ if (v_readerSampleTestState(sample,L_LAZYREAD)) { v_readerSampleSetState(sample,L_READ); v_readerSampleClearState(sample,L_LAZYREAD); } /* An action routine is provided in case the sample needs to be returned * to the user. If an action routine is not provided, it means the sample * needs to be removed from the administration, so the reader should be * modified accordingly. That means the 'proceed' flag should be set in * that case. */ V_MESSAGE_STAMP(v_dataReaderSampleMessage(sample),readerReadTime); if (action) { /* Invoke the action routine with the typed sample. */ result = action(v_readerSample(sample), arg); } else { v_actionResultSet(result, V_PROCEED); } /* A sample is considered 'skipped' if the action routine invoked above * does not want to keep track of the sample (for example because it * didn't match its readerMasks). In that case, it sets the 'skip' flag * to true, which indicates that those samples should be considered * 'untouched' and therefore their instance and sample states should * not be modified. */ if (v_actionResultTestNot(result, V_SKIP)) { V_MESSAGE_STAMP(v_dataReaderSampleMessage(sample),readerCopyTime); V_MESSAGE_REPORT(v_dataReaderSampleMessage(sample), v_dataReaderInstanceDataReader(instance)); v_stateClear(v_instanceState(instance),L_NEW); if (!v_stateTest(v_readerSample(sample)->sampleState,L_READ)) { v_stateSet(v_readerSample(sample)->sampleState,L_LAZYREAD); } if (consume) { v_dataViewSampleListRemove(v_dataViewSampleList(sample)); v_dataViewSampleRemove(sample); } } return result; }
c_bool v_networkQueueWrite( v_networkQueue queue, v_message msg, v_networkReaderEntry entry, c_long sequenceNumber, v_gid sender, c_bool sendTo, /* for p2p writing */ v_gid receiver) { c_bool result = TRUE; c_bool wasEmpty; c_bool found; v_networkStatusMarker *currentMarkerPtr; v_networkStatusMarker currentMarker; v_networkStatusMarker marker; v_networkQueueSample newHolder; c_ulonglong msecsTime; c_ulonglong msecsResult; c_ulonglong msecsLeftOver; c_time sendBeforeNoTrunc; c_time sendBefore; c_time now; c_ulong priorityLookingFor; c_equality eq; c_bool newMarkerCreated = FALSE; c_bool sendNow = FALSE; V_MESSAGE_STAMP(msg,readerInsertTime); c_mutexLock(&queue->mutex); /* numberOfSamplesArrived statistics */ v_networkQueueStatisticsAdd(numberOfSamplesArrived,queue->statistics); if (queue->currentMsgCount == queue->maxMsgCount) { c_mutexUnlock(&queue->mutex); /* numberOfSamplesRejected stat */ v_networkQueueStatisticsAdd(numberOfSamplesRejected,queue->statistics); return FALSE; } currentMarkerPtr = &(queue->firstStatusMarker); currentMarker = *currentMarkerPtr; if (queue->threadWaiting) { wasEmpty = !v_networkQueueHasExpiringData(queue); } else { wasEmpty = FALSE; } marker = NULL; found = FALSE; priorityLookingFor = v_messageQos_getTransportPriority(msg->qos); if (queue->periodic) { if (v_messageQos_isZeroLatency(msg->qos)) { sendBefore = C_TIME_ZERO; sendNow = TRUE; } else { #ifdef _NAT_ now = v_timeGet(); #else now = msg->allocTime; #endif sendBeforeNoTrunc = c_timeAdd(now, v_messageQos_getLatencyPeriod(msg->qos)); TIME_TO_MSEC(sendBeforeNoTrunc, msecsTime); msecsLeftOver = (c_ulonglong)((msecsTime - queue->phaseMilliSeconds) % queue->msecsResolution); msecsResult = (c_ulonglong)(msecsTime - msecsLeftOver); MSEC_TO_TIME(msecsResult, sendBefore); } while ((currentMarker != NULL) && (!found)) { eq = c_timeCompare(sendBefore, currentMarker->sendBefore); switch (eq) { case C_GT: currentMarkerPtr = ¤tMarker->next; currentMarker = *currentMarkerPtr; break; case C_EQ: if (priorityLookingFor < currentMarker->priority) { currentMarkerPtr = ¤tMarker->next; currentMarker = *currentMarkerPtr; } else { found = TRUE; if (priorityLookingFor == currentMarker->priority) { marker = currentMarker; } } break; case C_LT: found = TRUE; break; default: assert(FALSE); break; } } } else { if (currentMarker) { sendBefore = C_TIME_ZERO; if (c_timeIsZero(currentMarker->sendBefore)) { marker = currentMarker; } } } /* Insert after end of list */ if (marker == NULL) { newMarkerCreated = TRUE; if (queue->freeStatusMarkers == NULL) { marker = v_networkStatusMarker(c_new(queue->statusMarkerType)); } else { marker = queue->freeStatusMarkers; queue->freeStatusMarkers = marker->next; } if (marker != NULL) { marker->sendBefore = sendBefore; marker->priority = priorityLookingFor; marker->firstSample = NULL; marker->lastSample = NULL; marker->next = *currentMarkerPtr; /* no keep, transfer refCount */ if (marker->next == NULL) { queue->lastStatusMarker = marker; /* no keep, not reference counted */ } *currentMarkerPtr = marker; /* no keep, transfer refCount */ } else { OS_REPORT(OS_ERROR, "v_networkQueueWrite",0, "Failed to send message."); c_mutexUnlock(&queue->mutex); return FALSE; } } V_MESSAGE_STAMP(msg,readerLookupTime); assert(marker != NULL); if (queue->freeSamples == NULL) { newHolder = c_new(queue->sampleType); } else { newHolder = queue->freeSamples; queue->freeSamples = newHolder->next; } if (newHolder) { queue->currentMsgCount++; /* numberOfSamplesInserted & numberOfSamplesWaiting + stats*/ v_networkQueueStatisticsAdd(numberOfSamplesInserted,queue->statistics); v_networkQueueStatisticsCounterInc(numberOfSamplesWaiting,queue->statistics); newHolder->message = c_keep(msg); newHolder->entry = c_keep(entry); newHolder->sequenceNumber = sequenceNumber; newHolder->sender = sender; newHolder->sendTo = sendTo; newHolder->receiver = receiver; if (marker->lastSample != NULL) { newHolder->next = v_networkQueueSample(marker->lastSample)->next; /* no keep, transfer refCount */ v_networkQueueSample(marker->lastSample)->next = newHolder; /* no keep, transfer refCount */ } else { newHolder->next = marker->firstSample; /* no keep, transfer refCount */ marker->firstSample = newHolder; /* no keep, transfer refCount */ } marker->lastSample = newHolder; /* Write done, wake up waiters if needed */ if (wasEmpty && queue->threadWaiting) { if (sendNow || v_networkQueueHasExpiringData(queue)) { c_condBroadcast(&queue->cv); } } } else { OS_REPORT(OS_ERROR, "v_networkQueueWrite",0, "Failed to send message."); result = FALSE; } c_mutexUnlock(&queue->mutex); return result; }