Showing the changes to Source/Libraries/GSF.Core/Parsing/MultiSourceFrameImageParserBase.cs (1 of 3 files). Show all
Unified · Split
| @@ -219,7 +219,7 @@ namespace GSF.Parsing · 218 unmodified lines | |||
| 219 | public event EventHandler<EventArgs<TSourceIdentifier, IList<TOutputType>>> SourceDataParsed; | 219 | public event EventHandler<EventArgs<TSourceIdentifier, IList<TOutputType>>> SourceDataParsed; |
| 220 | 220 | ||
| 221 | // Fields | 221 | // Fields |
| 222 | private AsyncDoubleBufferedQueue<SourceIdentifiableBuffer> m_bufferQueue; | 222 | private readonly AsyncDoubleBufferedQueue<SourceIdentifiableBuffer> m_bufferQueue; |
| 223 | private readonly ConcurrentDictionary<TSourceIdentifier, bool> m_sourceInitialized; | 223 | private readonly ConcurrentDictionary<TSourceIdentifier, bool> m_sourceInitialized; |
| 224 | private readonly ConcurrentDictionary<TSourceIdentifier, byte[]> m_unparsedBuffers; | 224 | private readonly ConcurrentDictionary<TSourceIdentifier, byte[]> m_unparsedBuffers; |
| 225 | private readonly ConcurrentDictionary<TSourceIdentifier, List<TOutputType>> m_parsedSourceData; | 225 | private readonly ConcurrentDictionary<TSourceIdentifier, List<TOutputType>> m_parsedSourceData; |
| @@ -234,7 +234,8 @@ namespace GSF.Parsing · 8 unmodified lines | |||
| 234 | /// </summary> | 234 | /// </summary> |
| 235 | protected MultiSourceFrameImageParserBase() | 235 | protected MultiSourceFrameImageParserBase() |
| 236 | { | 236 | { |
| 237 | m_bufferQueue = CreateBufferQueue(); | 237 | m_bufferQueue = new AsyncDoubleBufferedQueue<SourceIdentifiableBuffer>(); |
| 238 | m_bufferQueue.ProcessItemsFunction = ParseQueuedBuffers; | ||
| 238 | m_bufferQueue.ProcessException += ProcessExceptionHandler; | 239 | m_bufferQueue.ProcessException += ProcessExceptionHandler; |
| 239 | 240 | ||
| 240 | if (ProtocolUsesSyncBytes) | 241 | if (ProtocolUsesSyncBytes) |
| @@ -255,10 +256,7 @@ namespace GSF.Parsing · 14 unmodified lines | |||
| 255 | { | 256 | { |
| 256 | get | 257 | get |
| 257 | { | 258 | { |
| 258 | if ((object)m_bufferQueue != null) | 259 | return m_bufferQueue.Count; |
| 259 | return m_bufferQueue.Count; | ||
| 260 | |||
| 261 | return 0; | ||
| 262 | } | 260 | } |
| 263 | } | 261 | } |
| 264 | 262 | ||
| @@ -400,75 +398,48 @@ namespace GSF.Parsing · 135 unmodified lines | |||
| 400 | throw new NotImplementedException("This method should not be called directly, call the Parse(TSourceIdentifier,byte[],int,int) method to queue data for parsing instead."); | 398 | throw new NotImplementedException("This method should not be called directly, call the Parse(TSourceIdentifier,byte[],int,int) method to queue data for parsing instead."); |
| 401 | } | 399 | } |
| 402 | 400 | ||
| 403 | /// <summary> | 401 | // This method is used by the internal <see cref="ProcessQueue{T}"/> to process all queued data buffers. |
| 404 | /// Creates the internal buffer queue. | 402 | private void ParseQueuedBuffers(IList<SourceIdentifiableBuffer> buffers) |
| 405 | /// </summary> | ||
| 406 | /// <remarks> | ||
| 407 | /// <para> | ||
| 408 | /// This method is virtual to allow derived classes to customize the style of processing queue used when consumers | ||
| 409 | /// choose to implement an internal buffer queue. Default type is a real-time queue with the default settings. | ||
| 410 | /// When overriding, use the <see cref="ParseQueuedBuffers"/> method for the <see cref="ProcessQueue{T}"/>) item | ||
| 411 | /// processing delegate. | ||
| 412 | /// </para> | ||
| 413 | /// <para> | ||
| 414 | /// Note that current design only supports serial processing - consumer overriding this method to return an asynchronous | ||
| 415 | /// process queue to process multiple items at once on separate threads will need to redesign the processing delegate. | ||
| 416 | /// </para> | ||
| 417 | /// </remarks> | ||
| 418 | /// <returns>New internal buffer processing queue (i.e., a new <see cref="ProcessQueue{T}"/>).</returns> | ||
| 419 | protected virtual AsyncDoubleBufferedQueue<SourceIdentifiableBuffer> CreateBufferQueue() | ||
| 420 | { | ||
| 421 | AsyncDoubleBufferedQueue<SourceIdentifiableBuffer> queue = new AsyncDoubleBufferedQueue<SourceIdentifiableBuffer>(); | ||
| 422 | queue.ProcessItemsFunction = ParseQueuedBuffers; | ||
| 423 | queue.ProcessException += ProcessExceptionHandler; | ||
| 424 | return queue; | ||
| 425 | } | ||
| 426 | |||
| 427 | /// <summary> | ||
| 428 | /// This method is used by the internal <see cref="ProcessQueue{T}"/> to process all queued data buffers. | ||
| 429 | /// </summary> | ||
| 430 | /// <param name="buffers">Identifiable buffers to process.</param> | ||
| 431 | /// <remarks> | ||
| 432 | /// This is the <see cref="SourceIdentifiableBuffer"/> processing delegate to use when overriding the <see cref="CreateBufferQueue"/> method. | ||
| 433 | /// </remarks> | ||
| 434 | protected virtual void ParseQueuedBuffers(IList<SourceIdentifiableBuffer> buffers) | ||
| 435 | { | 403 | { |
| 436 | try | 404 | if (Enabled) |
| 437 | { | 405 | { |
| 438 | // Process all queued data buffers... | 406 | try |
| 439 | foreach (SourceIdentifiableBuffer buffer in buffers) | ||
| 440 | { | 407 | { |
| 441 | // Track current buffer source | 408 | // Process all queued data buffers... |
| 442 | m_source = buffer.Source; | 409 | foreach (SourceIdentifiableBuffer buffer in buffers) |
| 410 | { | ||
| 411 | // Track current buffer source | ||
| 412 | m_source = buffer.Source; | ||
| 443 | 413 | ||
| 444 | // Check to see if this data source has been initialized | 414 | // Check to see if this data source has been initialized |
| 445 | if ((object)m_sourceInitialized != null) | 415 | if ((object)m_sourceInitialized != null) |
| 446 | StreamInitialized = m_sourceInitialized.GetOrAdd(m_source, true); | 416 | StreamInitialized = m_sourceInitialized.GetOrAdd(m_source, true); |
| 447 | 417 | ||
| 448 | // Restore any unparsed buffers for this data source, if any | 418 | // Restore any unparsed buffers for this data source, if any |
| 449 | UnparsedBuffer = m_unparsedBuffers.GetOrAdd(m_source, (byte[])null); | 419 | UnparsedBuffer = m_unparsedBuffers.GetOrAdd(m_source, (byte[])null); |
| 450 | 420 | ||
| 451 | // Start parsing sequence for this buffer - this will begin publication of new parsed outputs | 421 | // Start parsing sequence for this buffer - this will begin publication of new parsed outputs |
| 452 | base.Write(buffer.Buffer, 0, buffer.Count); | 422 | base.Write(buffer.Buffer, 0, buffer.Count); |
| 453 | 423 | ||
| 454 | // Track last unparsed buffer for this data source | 424 | // Track last unparsed buffer for this data source |
| 455 | m_unparsedBuffers[m_source] = UnparsedBuffer; | 425 | m_unparsedBuffers[m_source] = UnparsedBuffer; |
| 426 | } | ||
| 456 | } | 427 | } |
| 457 | } | 428 | finally |
| 458 | finally | ||
| 459 | { | ||
| 460 | // If user has attached to SourceDataParsed event, expose list of parsed data per source | ||
| 461 | if ((object)SourceDataParsed != null) | ||
| 462 | { | 429 | { |
| 463 | foreach (KeyValuePair<TSourceIdentifier, List<TOutputType>> parsedData in m_parsedSourceData) | 430 | // If user has attached to SourceDataParsed event, expose list of parsed data per source |
| 431 | if ((object)SourceDataParsed != null) | ||
| 464 | { | 432 | { |
| 465 | OnSourceDataParsed(parsedData.Key, parsedData.Value); | 433 | foreach (KeyValuePair<TSourceIdentifier, List<TOutputType>> parsedData in m_parsedSourceData) |
| 434 | { | ||
| 435 | OnSourceDataParsed(parsedData.Key, parsedData.Value); | ||
| 436 | } | ||
| 437 | |||
| 438 | // Clear parsed data dictionary for next pass | ||
| 439 | m_parsedSourceData.Clear(); | ||
| 466 | } | 440 | } |
| 467 | 441 | ||
| 468 | // Clear parsed data dictionary for next pass | ||
| 469 | m_parsedSourceData.Clear(); | ||
| 470 | } | 442 | } |
| 471 | |||
| 472 | } | 443 | } |
| 473 | 444 | ||
| 474 | // Dispose of source buffers - no rush | 445 | // Dispose of source buffers - no rush |