feat(tcp): TCPStreamer DataSources, in-process TCPStreamService, stream multiplexing and TCPStreamJoin
Add TCPStreamer/TCPStreamerClient (TCP transport behind the UDPSServerI/UDPSClientI seam), an optional single in-process TCPStreamService serving many streams over worker threads, multiplexed SUBSCRIBE (comma list, stream index in fragmentIdx), and TCPStreamJoin, which merges several streams into one sample-and-hold stream paced by a master. StreamHub takes a comma list of streams over one connection. Includes GTests, E2E scenarios s58-s73 and docs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
5562877c99
commit
50d85363a3
79 files changed
+12348
-138
No files matched your search
@@ -0,0 +1,139 @@
|
||||
#ifndef TCPSTREAMJOIN_H_
|
||||
#define TCPSTREAMJOIN_H_
|
||||
|
||||
/**
|
||||
* @file TCPStreamJoin.h
|
||||
* @brief Publishes one new stream of a TCPStreamService that merges several other
|
||||
* streams of the same service.
|
||||
*
|
||||
* @code
|
||||
* +Svc = { Class = TCPStreamService Port = 44500 }
|
||||
* +Join = { Class = TCPStreamJoin Service = "Svc" StreamName = "all"
|
||||
* Sources = "fast,slow" Master = "fast" }
|
||||
* @endcode
|
||||
* Declare the join after the service. Consumers subscribe to "all" like to any stream.
|
||||
*
|
||||
* The merged stream is emitted at the pace of the Master source: each Master DATA frame
|
||||
* produces one merged frame holding the Master's signals and the last values received
|
||||
* from every other source (sample-and-hold). Nothing is emitted until every source has
|
||||
* delivered one DATA frame. No thread is added: the merged frame is built and queued on
|
||||
* the Master producer's thread.
|
||||
*
|
||||
* @par CONFIG
|
||||
* Concatenation of the source descriptors in Sources order, named
|
||||
* "<stream>_<signal>" (at most 63 characters), time-signal indexes rebased, publish mode
|
||||
* Strict. All sources must share the same HRT frequency (an unknown one matches any).
|
||||
*
|
||||
* @par DATA
|
||||
* [master timestamp][source0 body][source1 body]... where a body is that source's last
|
||||
* DATA payload without its 8-byte timestamp. A held value is therefore stamped with the
|
||||
* Master's time unless the source carries its own time signal.
|
||||
*
|
||||
* @par Limits
|
||||
* Only Strict and Decimate sources are accepted (Accumulate batches have varying
|
||||
* length); a source whose frame size changes without a new CONFIG is ignored; the merged
|
||||
* frame must fit MaxPayloadSize. The output stream is registered while every source is
|
||||
* registered and removed as soon as one leaves; it is rebuilt when a source re-registers
|
||||
* or changes its CONFIG.
|
||||
*
|
||||
* @par Parameters
|
||||
* | Parameter | Type | Default | Description |
|
||||
* |----------------|--------|-------------|-------------|
|
||||
* | Service | string | (required) | Name of the TCPStreamService object. |
|
||||
* | StreamName | string | object name | Name of the merged stream. |
|
||||
* | Sources | string | (required) | Comma separated source stream names (1..16). |
|
||||
* | Master | string | first source| Source whose frames pace the merged stream. |
|
||||
* | MaxPayloadSize | uint32 | 60000 | Largest merged frame payload. |
|
||||
*
|
||||
* @par Locking
|
||||
* Producer-side: source tapMutex, then the join mutex, then the output stream mutex, then
|
||||
* the connection queue mutex. Service notifications run outside its topology lock and
|
||||
* are serialised.
|
||||
*/
|
||||
|
||||
#include "FastPollingMutexSem.h"
|
||||
#include "Object.h"
|
||||
#include "ReferenceT.h"
|
||||
#include "StreamString.h"
|
||||
#include "StructuredDataI.h"
|
||||
#include "TCPSServiceStream.h"
|
||||
#include "TCPSStreamTapI.h"
|
||||
#include "TCPStreamService.h"
|
||||
|
||||
namespace MARTe {
|
||||
|
||||
class TCPStreamJoin : public Object, public TCPSStreamTapI, public TCPSStreamObserverI {
|
||||
public:
|
||||
CLASS_REGISTER_DECLARATION()
|
||||
|
||||
/** Most source streams one join can merge. */
|
||||
static const uint32 TCPSJ_MAX_SOURCES = 16u;
|
||||
|
||||
TCPStreamJoin();
|
||||
virtual ~TCPStreamJoin();
|
||||
|
||||
virtual bool Initialise(StructuredDataI &data);
|
||||
|
||||
virtual void OnTapConfig(TCPSServiceStream *source, const uint8 *payload, uint32 payloadSize);
|
||||
virtual void OnTapData(TCPSServiceStream *source, uint32 counter, const uint8 *payload,
|
||||
uint32 payloadSize);
|
||||
virtual void OnStreamRegistered(TCPSServiceStream *stream);
|
||||
virtual void OnStreamUnregistered(TCPSServiceStream *stream);
|
||||
|
||||
/** @return true while the merged stream is registered with the service. */
|
||||
bool IsActive() const;
|
||||
/** @return true once a merged CONFIG has been published for the current sources. */
|
||||
bool HasConfig() const;
|
||||
/** @return merged DATA frames emitted. */
|
||||
uint64 GetFramesEmitted() const;
|
||||
uint32 GetNumSources() const;
|
||||
|
||||
private:
|
||||
struct Source {
|
||||
Source();
|
||||
~Source();
|
||||
StreamString name;
|
||||
TCPSServiceStream *stream; ///< non-NULL while registered and tapped
|
||||
bool configOk;
|
||||
uint8 *cfg;
|
||||
uint32 cfgBytes;
|
||||
uint32 numSigs;
|
||||
uint64 hrt;
|
||||
uint8 *body;
|
||||
uint32 bodyCap;
|
||||
uint32 bodySize;
|
||||
bool haveBody;
|
||||
};
|
||||
|
||||
int32 FindByName(const char8 *name) const;
|
||||
int32 FindByStream(const TCPSServiceStream *s) const;
|
||||
bool AllRegistered() const;
|
||||
void Evaluate();
|
||||
void PublishConfigLocked();
|
||||
bool ParseConfig(Source &s, const uint8 *payload, uint32 n);
|
||||
|
||||
ReferenceT<TCPStreamService> service;
|
||||
TCPSServiceStream *out;
|
||||
bool observing;
|
||||
StreamString outName;
|
||||
Source *src;
|
||||
uint32 numSrc;
|
||||
uint32 master;
|
||||
uint32 maxPayload;
|
||||
|
||||
FastPollingMutexSem mtx;
|
||||
bool active;
|
||||
bool configPublished;
|
||||
bool sizeLogged;
|
||||
uint32 outCounter;
|
||||
volatile uint64 emitted;
|
||||
uint8 *scratch;
|
||||
uint32 scratchCap;
|
||||
|
||||
TCPStreamJoin(const TCPStreamJoin &);
|
||||
TCPStreamJoin &operator=(const TCPStreamJoin &);
|
||||
};
|
||||
|
||||
} // namespace MARTe
|
||||
|
||||
#endif // TCPSTREAMJOIN_H_
|
||||
Reference in new issue
Block a user