From bb66a49ec16b8d7b1c49830c089d3e84aad524cc Mon Sep 17 00:00:00 2001 From: Dirk Zimoch Date: Mon, 6 Aug 2018 17:40:49 +0200 Subject: [PATCH] documentation update --- documentation/businterface.html | 162 +++++++++++++++-------------- documentation/formatconverter.html | 78 +++++++++++--- documentation/index.html | 44 +++++++- documentation/nav.html | 9 ++ 4 files changed, 195 insertions(+), 98 deletions(-) diff --git a/documentation/businterface.html b/documentation/businterface.html index 31cd9e0..2598636 100644 --- a/documentation/businterface.html +++ b/documentation/businterface.html @@ -19,7 +19,7 @@ href="http://www.aps.anl.gov/epics/modules/soft/asyn/"> asynDriver. You should first try to implement your bus driver compatible to -asynDriver. +asynOctet. Then it can be used by StreamDevice automatically. Only if that does not work, write your own bus interface.

@@ -68,17 +68,13 @@ class MyInterface : StreamBusInterface // StreamBusInterface virtual methods bool lockRequest(unsigned long lockTimeout_ms); bool unlock(); - bool writeRequest(const void* output, size_t size, - unsigned long writeTimeout_ms); - bool readRequest(unsigned long replyTimeout_ms, - unsigned long readTimeout_ms, - long expectedLength, bool async); + bool writeRequest(const void* output, size_t size, unsigned long writeTimeout_ms); + bool readRequest(unsigned long replyTimeout_ms, unsigned long readTimeout_ms, long expectedLength, bool async); bool supportsAsyncRead(); bool supportsEvent(); - bool acceptEvent(unsigned long mask, - unsigned long replytimeout_ms); - bool connectRequest(unsigned long connecttimeout_ms); - bool disconnect(); + bool acceptEvent(unsigned long mask, unsigned long timeout_ms); + bool connectRequest(unsigned long timeout_ms); + bool disconnectRequest(); void finish(); public: @@ -132,13 +128,13 @@ bool supportsEvent();
bool acceptEvent(unsigned long mask, - unsigned long replytimeout_ms); + unsigned long timeout_ms);
-bool connectRequest(unsigned long connecttimeout_ms); +bool connectRequest(unsigned long timeout_ms);
-bool disconnect(); +bool disconnectRequest();
void finish(); @@ -157,24 +153,24 @@ callback methods which must be called in response to the above request methods (most probably from another thread):

-void lockCallback(StreamIoStatus status); +void lockCallback(StreamIoStatus status = StreamIoSuccess);
-void writeCallback(StreamIoStatus status); +void writeCallback(StreamIoStatus status = StreamIoSuccess);
-long readCallback(StreamIoStatus status, - const void* input = NULL, - long size = 0); +ssize_t readCallback(StreamIoStatus status, + const void* buffer = NULL, + size_t size = 0);
-void eventCallback(StreamIoStatus status); +void eventCallback(StreamIoStatus status = StreamIoSuccess);
-void connectCallback(StreamIoStatus status); +void connectCallback(StreamIoStatus status = StreamIoSuccess);
-void disconnectCallback(StreamIoStatus status); +void disconnectCallback(StreamIoStatus status = StreamIoSuccess);

Other provided methods, attibutes, and types

@@ -197,6 +193,9 @@ const char* getInTerminator(size_t& length);
enum StreamIoStatus {StreamIoSuccess, StreamIoTimeout, StreamIoNoReply, StreamIoEnd, StreamIoFault};
+
+const char* ::toStr(StreamIoStatus); +

Theory of Operation

@@ -276,34 +275,47 @@ correct.

Connecting and disconnecting

-bool connectRequest(unsigned long connecttimeout_ms); +bool connectRequest(unsigned long timeout_ms);
-bool disconnect(); +bool disconnectRequest();
-void connectCallback(IoStatus status); +void connectCallback(IoStatus status = StreamIoSuccess);
-void disconnectCallback(IoStatus status); +void disconnectCallback(IoStatus status = StreamIoSuccess);

-Connection should be handled automatically. -If the device is disconnected, each attempt to access the -device should try to (re-)connect. +Whenever possible connection should be handled automatically. +The interface should call connectCallback() when +the device has connected and disconnectCallback() when +the device has disconnected. +These callbacks can be called asynchronously at any time. +

+

+If the device is disconnected, an attempt to access the +device should try to reconnect. Normally, the interface should not try to disconnect unless -the device does so. +the device does so automatically.

However, sometimes the client wants to connect or -disconnect explicitely. +disconnect explicitly. To connect, the client calls connectRequest(). -This function should return true immediately -or false if the request cannot be accepted or connection +This function should set up things to reconnect but should not block +waiting. +Instead it should immediately return true if +it expects that connection can be established soon, or +false if the request cannot be accepted or connection handling is not supported. -The interface should call connectCallback(StreamIoSuccess) +The interface should call connectCallback() once the bus could be connected. -If the bus cannot be connected within connecttimeout_ms +If the device can connect immediately without waiting, it may also call +connectCallback() directly from connectRequest(). +

+

+If the bus cannot be connected within timeout_ms milliseconds, the bus interface should call connectCallback(StreamIoTimeout).

@@ -313,11 +325,11 @@ something wrong with the I/O hardware, connectCallback(StreamIoFault) may be called.

-To disconnect, the client calls disconnectRequest(); +To disconnect explicitly, the client calls disconnectRequest(); This function should return true immediately or false if the request cannot be accepted or connection handling is not supported. -The interface should call connectCallback(StreamIoSuccess) +The interface should call connectCallback() once the bus is disconnected. There is no timeout for this operation. If disconnecting is impossible, the interface should call connectCallback(StreamIoFault). @@ -326,10 +338,10 @@ If disconnecting is impossible, the interface should call

Bus locking

-bool lockRequest(unsigned long lockTimeout_ms); +bool lockRequest(unsigned long timeout_ms);
-void lockCallback(IoStatus status); +void lockCallback(IoStatus status = StreamIoSuccess);
bool unlock(); @@ -348,7 +360,7 @@ or false if the request cannot be accepted. If the device is already locked, the bus interface should add itself to a queue, sorted by priority(). As soon as the device is available, the bus interface should call -lockCallback(StreamIoSuccess). +lockCallback(). If the bus cannot be locked within lockTimeout_ms milliseconds, the bus interface should call lockCallback(StreamIoTimeout). @@ -369,7 +381,7 @@ locked the device. When the protocol ends and the device is locked, the client calls unlock(). If other bus interfaces are in the lock queue, the next one should -call lockCallback(StreamIoSuccess) now. +call lockCallback() now.

The client calls finish() when the protocol ends. @@ -385,7 +397,7 @@ bool writeRequest(const void* output, size_t size, unsigned long writeTimeout_ms);

-void writeCallback(IoStatus status); +void writeCallback(IoStatus status = StreamIoSuccess);
const char* getOutTerminator(size_t& length); @@ -404,7 +416,7 @@ The function should arrange transmission of size bytes of or false if the request cannot be accepted. It must not block until output has completed. After all output has been successfully transmitted, but not earlier, the -interface should call writeCallback(StreamIoSuccess). +interface should call writeCallback().

If output blocks for writeTimeout_ms milliseconds, @@ -417,14 +429,15 @@ something wrong with the I/O hardware, writeCallback(StreamIoFault) may be called.

-The interface must transmit excactly the size bytes -from output. -It must not change anything and it should not assume that -any bytes have a special meaning. +The interface must send excactly the size bytes +from output, not less. +It should not change anything unless the bus needs some special +formatting (e.g. added header, escaped bytes) and it should not +assume that any bytes have a special meaning. In particular, a null byte does not terminate output.

-A call to getOutTerminator tells the interface which +A call to getOutTerminator() tells the interface which terminator has already been added to the output. If NULL was returned, the client is not aware of a terminator (no outTerminator was defined in the protocol). @@ -450,9 +463,9 @@ bool readRequest(unsigned long replyTimeout_ms, long expectedLength, bool async);

-long readCallback(IoStatus status, - const void* input = NULL, - long size = 0); +ssize_t readCallback(IoStatus status, + const void* buffer = NULL, + size_t size = 0);
const char* getInTerminator(size_t& length); @@ -487,11 +500,11 @@ The client copies its contents. It does not modify or free it. It is not necessary to wait until all data has been received. The bus interface can call n=readCallback() after any amount of input has been received. -If the client needs more input, readCallback() +If the client expects more input, readCallback() returns a non-zero value. -A positive n means, the client needs another +A positive n means, the client expects another n bytes of input. -A negative n means, the client needs an unspecified +A negative n means, the client expects an unspecified amount of additional input.

@@ -559,46 +572,43 @@ something wrong with the I/O hardware, readCallback(StreamIoFault) may be called.

-If the async flag is true, the client -wants to read input asyncronously without any timeout. -That means, the bus interface should call readCallback() -even if the input was requested by another client. -

-

-If a client wishes to receive asynchonous input, it first calls +Sometimes a client wishes to get any input received at any time, even +when requested by another client. +If a client wishes to receive such asynchronous input, it first calls supportsAsyncRead(). The default implementation of this method always returns false. -A bus interface may overwrite this method to return true -and eventually prepare for asynchonous input. +If a bus interface supports asynchronous input, it should overwrite +this method to set up everything needed to receive asynchronous input +and then return true. The client is then allowed to call readRequest() with the async==true. -This means that the client is interested in any input. +This means that the client is now interested in asynchronous input. It should receive a readCallback() of all input which came -in response to a synchonous (async==false) request from -another client (which of course should receive the input, too). -The interface should also receive asynchonous input when no +in response to any synchonous (async==false) request from +another client (which should receive the input, too). +The interface should also receive asynchronous input when no synchonous client is active at the moment. -Many asynchonous readRequest() calls from different clients +Many asynchronous readRequest() calls from different clients may be active at the same time. All of them should receive the same input.

-For asynchonous requests, replyTimeout_ms has a different +For asynchronous requests, replyTimeout_ms has a different meaning: If the bus interface has to poll the bus for input, it may take replyTimeout_ms as a hint for the poll period. -If many asynchonous requests are active at the same time, it should poll +If many asynchronous requests are active at the same time, it should poll with the shortest period of all clients. -An asynchonous request does not time out. +An asynchronous request does not time out. It stays active until the next input arrives. The client may reissue the asynchronous readRequest() from within the readCallback() if it wants to continue -receiving asynchonous input. +receiving asynchronous input.

If the client calls finish() at any time, the bus interface should cancel all outstanding requests, including -asynchonous read requests. +asynchronous read requests.

Handling events

@@ -606,10 +616,10 @@ asynchonous read requests. bool supportsEvent();
-bool acceptEvent(unsigned long mask, unsigned long replytimeout_ms); +bool acceptEvent(unsigned long mask, unsigned long timeout_ms);
-void eventCallback(StreamIoStatus status); +void eventCallback(StreamIoStatus status = StreamIoSuccess);

An event is a sort of input from a device which is not part of @@ -627,9 +637,9 @@ If true is returned, the client is allowed to call If mask is illegal, acceptEvent() should return false. The call to acceptEvent() must not block. -It should arrange to call eventCallback(StreamIoSuccess) +It should arrange to call eventCallback() when the event matching mask arrives within -replytimeout_ms milliseconds. +timeout_ms milliseconds. If no such event arrives within this time, the bus interface should call eventCallback(StreamIoTimeout).

diff --git a/documentation/formatconverter.html b/documentation/formatconverter.html index a598238..9f72916 100644 --- a/documentation/formatconverter.html +++ b/documentation/formatconverter.html @@ -44,7 +44,7 @@ class MyConverter : public StreamFormatConverter { int parse(const StreamFormat&, StreamBuffer&, const char*&, bool); bool printLong(const StreamFormat&, StreamBuffer&, long); - int scanLong(const StreamFormat&, const char*, long&); + ssize_t scanLong(const StreamFormat&, const char*, long&); }; RegisterConverter(MyConverter,"Q"); @@ -73,17 +73,17 @@ Provide multiple classes, that's more efficient.

Parsing

-int parse (const StreamFormat& fmt, StreamBuffer& info, +int parse(const StreamFormat& fmt, StreamBuffer& info, const char*& source, bool scanFormat);
struct StreamFormat { char conv; StreamFormatType type; -unsigned char flags; -short prec; -unsigned short width; -unsigned short infolen; +unsigned short flags; +long prec; +unsigned long width; +unsigned long infolen; const char* info; };
@@ -124,12 +124,12 @@ flags set:

It is not necessary that these flags have exactly the same meaning in your -formats, but a similar and intuitive meaning helpful for the user. +formats, but a similar and intuitive meaning is helpful for the user.

There are two additional flags, default_flag indicating a ? and compare_flag indicating a = -int the format, that are handled internally by StreamDevice and +in the format, that are handled internally by StreamDevice and are not of interest to the converter class.

@@ -163,13 +163,13 @@ This will probably be necessary if you have parsed additional characters from the format string as in the above example

-Return long_format, double_format, -string_format, or enum_format depending on the +Return unsigned_format, signed_format, +double_format, string_format, or +enum_format depending on the datatype associated with the conversion character. It is not necessary to return the same value for print and for scan formats. -You can even return different values depending on the format string, -but I can't imagine why anyone should do that. +You can even return different values depending on the format string.

If the format is not a real data conversion but does other things with @@ -178,7 +178,8 @@ return pseudo_format.

Return false if there is any parse error or if print or scan -is requested but not supported by this conversion. +is requested but not supported by this conversion or flags are used that +are not supported by this conversion.

@@ -191,7 +192,45 @@ That method is called whenever the conversion appears in an output or input, respectively. You only need to implement the flavour of print and/or scan suitable for the datatype returned by parse(). +Both unsigned_format and signed_format will use +the Long flavour.

+

+The possible interface methods are: +

+
+bool printLong(const StreamFormat& fmt, + StreamBuffer& output, long value); +
+
+bool printDouble(const StreamFormat& fmt, + StreamBuffer& output, double value); +
+
+bool printString(const StreamFormat& fmt, + StreamBuffer& output, const char* value); +
+
+bool printPseudo(const StreamFormat& fmt, + StreamBuffer& output); +
+
+ssize_t scanLong(const StreamFormat& fmt, + const char* input, long& value); +
+
+ssize_t scanDouble(const StreamFormat& fmt, + const char* input, double& value); +
+
+ssize_t scanString(const StreamFormat& fmt, + const char* input, char* value, size_t& size); +
+
+ssize_t scanPseudo(const StreamFormat& fmt, + StreamBuffer& inputLine, size_t& cursor); +
+

Now, fmt.type contains the value returned by parse(). With fmt.info() get access to the string you have written to @@ -203,16 +242,21 @@ The length of the info string can be found in fmt.infolen.

In print*(), append the converted value to output. Do not modify what is already in output (unless you really know what you're -doing). +doing, e.g. some printPseudo methods). Return true on success, false on failure.

In scan*(), read the value from input and return the number of -consumed bytes. -In the string version, don't write more bytes than maxlen! +consumed bytes or -1 on failure. If the skip_flag is set, you don't need to write to value, since the value will be discarded anyway. -Return -1 on failure. +In scanString(), don't write more bytes than +maxlen to value and set size to the +actual string length, which may be different to the number of bytes consumed +(e.g. if leading spaces are skipped). +In scanPseudo(), cursor is the index of the first +byte in inputLine to consider, which may be larger than +0.

Format Converter API +
+ Converter Class + Theory of Operation +
+ Registration + Parsing + Printing and Scanning +
+
Operating System API