Skip to content

Commit bbb569a

Browse files
hidmicahcorde
authored andcommitted
Update publishing API documentation. (#270)
Signed-off-by: Michel Hidalgo <michel@ekumenlabs.com>
1 parent 6705b72 commit bbb569a

File tree

1 file changed

+254
-51
lines changed

1 file changed

+254
-51
lines changed

rmw/include/rmw/rmw.h

+254-51
Original file line numberDiff line numberDiff line change
@@ -352,23 +352,54 @@ RMW_WARN_UNUSED
352352
rmw_ret_t
353353
rmw_destroy_publisher(rmw_node_t * node, rmw_publisher_t * publisher);
354354

355-
/// Borrow a loaned message.
355+
/// Borrow a loaned ROS message.
356356
/**
357-
* The memory allocated for the ros message belongs to the middleware and must not be deallocated.
358-
* A call to \sa rmw_publish_loned_message as well as \sa rmw_return_loaned_message_from_publisher`
359-
* will return ownership of the loaned message back to the middleware.
360-
*
361-
* In order to react to failures, the ros message is passed by pointer as an output parameter.
362-
* Therefore, the pointer to the ros message has to be `null` and not previously allocated or
363-
* else that memory is lost.
364-
*
365-
* \param[in] publisher Publisher to which the allocated message is associated.
366-
* \param[in] type_support Typesupport to which the internal ros message is allocated.
367-
* \param[out] ros_message The pointer to be filled with a valid ros message by the middleware.
368-
* \return `RMW_RET_OK` if the ros message was correctly initialized, or
369-
* \return `RMW_RET_INVALID_ARGUMENT` if an argument other than the ros message is null, or
370-
* \return `RMW_RET_BAD_ALLOC` if the ros message could not be correctly created, or
371-
* \return `RMW_RET_UNSUPPORTED` if the rmw_implementation does not support loaned_message, or
357+
* This ROS message is owned by the middleware, that will keep it alive (i.e. in valid
358+
* memory space) until the caller publishes it using rmw_publish_loaned_message() or
359+
* returns it using rmw_return_loaned_message_from_publisher().
360+
*
361+
* <hr>
362+
* Attribute | Adherence
363+
* ------------------ | -------------
364+
* Allocates Memory | Maybe
365+
* Thread-Safe | Yes
366+
* Uses Atomics | Maybe [1]
367+
* Lock-Free | Maybe [1]
368+
*
369+
* <i>[1] implementation defined, check implementation documentation.</i>
370+
*
371+
* \par Runtime behavior
372+
* To borrow a ROS message is a synchronous operation.
373+
* It is also non-blocking, but it is not guaranteed to be lock-free.
374+
* Generally speaking, implementations may synchronize access to internal resources using
375+
* locks but are not allowed to wait for events with no guaranteed time bound (barring
376+
* the effects of starvation due to OS scheduling).
377+
*
378+
* \par Memory allocation
379+
* It is implementation defined whether memory will be allocated on borrow or not.
380+
* Check the implementation documentation to learn about memory allocation
381+
* guarantees when using ROS message loaning support.
382+
*
383+
* \par Thread-safety
384+
* Publishers are thread-safe objects, and so are all operations on them except for finalization.
385+
* Therefore, it is safe to borrow ROS messages from the same publisher concurrently.
386+
*
387+
* \pre Given `publisher` must be a valid publisher, as returned by rmw_create_publisher().
388+
* \pre Given `type_support` must be a valid `rosidl` message type support, matching the
389+
* one registered with the `publisher` on creation.
390+
*
391+
* \param[in] publisher Publisher to which the loaned ROS message will be associated.
392+
* \param[in] type_support Message type support of the loaned ROS message.
393+
* \param[out] ros_message Pointer to type erased ROS message loaned by the middleware.
394+
* \return `RMW_RET_OK` if successful, or
395+
* \return `RMW_RET_BAD_ALLOC` if memory allocation fails, or
396+
* \return `RMW_RET_INVALID_ARGUMENT` if `publisher` is NULL, or
397+
* \return `RMW_RET_INVALID_ARGUMENT` if `type_support` is NULL, or
398+
* \return `RMW_RET_INVALID_ARGUMENT` if `ros_message` is NULL, or
399+
* \return `RMW_RET_INVALID_ARGUMENT` if `*ros_message` is not NULL (to prevent leaks), or
400+
* \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if `publisher` implementation identifier
401+
* does not match this implementation, or
402+
* \return `RMW_RET_UNSUPPORTED` if the implementation does not support ROS message loaning, or
372403
* \return `RMW_RET_ERROR` if an unexpected error occured.
373404
*/
374405
RMW_PUBLIC
@@ -379,17 +410,52 @@ rmw_borrow_loaned_message(
379410
const rosidl_message_type_support_t * type_support,
380411
void ** ros_message);
381412

382-
/// Return a loaned message previously borrow from a publisher.
413+
/// Return a loaned message previously borrowed from a publisher.
383414
/**
384-
* The ownership of the passed in ros message will be transferred back to the middleware.
385-
* The middleware might deallocate and destroy the message so that the pointer is no longer
386-
* guaranteed to be valid after this call.
415+
* Tells the middleware that a borrowed ROS message is no longer needed by the caller.
416+
* Ownership of the ROS message is given back to the middleware.
417+
* If this function fails early due to a logical error, such as an invalid argument,
418+
* the loaned ROS message will be left unchanged.
419+
* Otherwise, ownership of the ROS message will be given back to the middleware.
420+
* It is up to the middleware what will be made of the returned ROS message.
421+
* It is undefined behavior to use a loaned ROS message after returning it.
422+
*
423+
* <hr>
424+
* Attribute | Adherence
425+
* ------------------ | -------------
426+
* Allocates Memory | No
427+
* Thread-Safe | Yes
428+
* Uses Atomics | Maybe [1]
429+
* Lock-Free | Maybe [1]
430+
*
431+
* <i>[1] implementation defined, check implementation documentation.</i>
432+
*
433+
* \par Runtime behavior
434+
* To return a ROS message is a synchronous operation.
435+
* It is also non-blocking, but it is not guaranteed to be lock-free.
436+
* Generally speaking, implementations may synchronize access to internal resources using
437+
* locks but are not allowed to wait for events with no guaranteed time bound (barring
438+
* the effects of starvation due to OS scheduling).
387439
*
388-
* \param[in] publisher Publisher to which the loaned message is associated.
389-
* \param[in] loaned_message Loaned message to be returned.
440+
* \par Thread-safety
441+
* Publishers are thread-safe objects, and so are all operations on them except for finalization.
442+
* Therefore, it is safe to return borrowed ROS messages to the same publisher concurrently.
443+
* However, since ownership of the loaned ROS message is given back to the middleware and
444+
* this transfer is not synchronized, it is not safe to return the same loaned ROS message
445+
* concurrently.
446+
*
447+
* \pre Given `publisher` must be a valid publisher, as returned by rmw_create_publisher().
448+
* \pre Given `loaned_message` must have been previously borrowed from the same publisher
449+
* using rmw_borrow_loaned_message().
450+
*
451+
* \param[in] publisher Publisher to which the loaned ROS message is associated.
452+
* \param[in] loaned_message Type erased loaned ROS message to be returned.
390453
* \return `RMW_RET_OK` if successful, or
391-
* \return `RMW_RET_INVALID_ARGUMENT` if an argument is null, or
392-
* \return `RMW_RET_UNSUPPORTED` if the rmw_implementation does not support loaned_message, or
454+
* \return `RMW_RET_INVALID_ARGUMENT` if `publisher` is NULL, or
455+
* \return `RMW_RET_INVALID_ARGUMENT` if `loaned_message` is NULL, or
456+
* \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if `publisher` implementation identifier
457+
* does not match this implementation, or
458+
* \return `RMW_RET_UNSUPPORTED` if the implementation does not support ROS message loaning, or
393459
* \return `RMW_RET_ERROR` if an unexpected error occurs and no message can be initialized.
394460
*/
395461
RMW_PUBLIC
@@ -399,15 +465,62 @@ rmw_return_loaned_message_from_publisher(
399465
const rmw_publisher_t * publisher,
400466
void * loaned_message);
401467

402-
/// Publish a given ros_message
468+
/// Publish a ROS message.
403469
/**
404-
* Publish a given ROS message via a publisher.
470+
* Send a ROS message to all subscriptions with matching QoS policies using the given publisher.
471+
*
472+
* <hr>
473+
* Attribute | Adherence
474+
* ------------------ | -------------
475+
* Allocates Memory | Maybe
476+
* Thread-Safe | Yes
477+
* Uses Atomics | Maybe [1]
478+
* Lock-Free | Maybe [1]
479+
*
480+
* <i>[1] implementation defined, check implementation documentation.</i>
481+
*
482+
* \par Runtime behavior
483+
* It is implementation defined whether to publish a ROS message is a
484+
* synchronous or asynchronous, blocking or non-blocking operation.
485+
* However, asynchronous implementations are not allowed to access the
486+
* given ROS message after this function returns.
487+
* Check the implementation documentation to learn about publish behavior.
488+
*
489+
* \par Memory allocation
490+
* It is implementation defined whether memory will be allocated on publish or not.
491+
* For instance, implementations that serialize ROS messages to send it over the
492+
* wire may need to perform additional memory allocations when dealing with
493+
* unbounded (dynamically-sized) fields.
494+
* A publisher allocation, if provided, may or may not be used.
495+
* Check the implementation documentation to learn about memory allocation
496+
* guarantees when publishing ROS messages with and without publisher allocations.
497+
*
498+
* \par Thread-safety
499+
* Publishers are thread-safe objects, and so are all operations on them except for finalization.
500+
* Therefore, it is safe to publish using the same publisher concurrently.
501+
* However, when publishing regular ROS messages:
502+
* - Access to the ROS message is read-only but it is not synchronized.
503+
* Concurrent `ros_message` reads are safe, but concurrent reads and writes are not.
504+
* - Access to the publisher allocation is not synchronized, unless specifically stated
505+
* otherwise by the implementation.
506+
* Thus, it is generally not safe to read or write `allocation` while rmw_publish() uses it.
507+
* Check the implementation documentation to learn about publisher allocations' thread-safety.
508+
*
509+
* \pre Given `publisher` must be a valid publisher, as returned by rmw_create_publisher().
510+
* \pre Given `ros_message` must be a valid message, whose type matches the message type
511+
* support the `publisher` was registered with on creation.
512+
* \pre If not NULL, given `allocation` must be a valid publisher allocation, initialized
513+
* with rmw_publisher_allocation_init() with a message type support that matches the
514+
* one registered with `publisher` on creation.
405515
*
406516
* \param[in] publisher Publisher to be used to send message.
407-
* \param[in] ros_message Message to be sent.
408-
* \param[in] allocation Specify preallocated memory to use (may be NULL).
517+
* \param[in] ros_message Type erased ROS message to be sent.
518+
* \param[in] allocation Pre-allocated memory to be used. May be NULL.
409519
* \return `RMW_RET_OK` if successful, or
410-
* \return `RMW_RET_INVALID_ARGUMENT` if publisher or ros_message is null, or
520+
* \return `RMW_RET_INVALID_ARGUMENT` if `publisher` is NULL, or
521+
* \return `RMW_RET_INVALID_ARGUMENT` if `ros_message` is NULL, or
522+
* \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if `publisher` implementation
523+
* identifier does not match this implementation, or
411524
* \return `RMW_RET_ERROR` if an unexpected error occurs.
412525
*/
413526
RMW_PUBLIC
@@ -418,23 +531,69 @@ rmw_publish(
418531
const void * ros_message,
419532
rmw_publisher_allocation_t * allocation);
420533

421-
/// Publish a loaned ros_message.
534+
/// Publish a loaned ROS message.
422535
/**
423-
* Publish a loaned ROS message via a publisher and return ownership of the loaned message
424-
* back to the middleware.
536+
* Send a previously borrowed ROS message to all subscriptions with matching QoS policies
537+
* using the given publisher, then return ROS message ownership to the middleware.
538+
*
539+
* If this function fails early due to a logical error, such as an invalid argument,
540+
* the loaned ROS message will be left unchanged.
541+
* Otherwise, ownership of the ROS message will be given back to the middleware.
542+
* It is up to the middleware what will be made of the returned ROS message.
543+
* It is undefined behavior to use a loaned ROS message after publishing it.
544+
*
545+
* <hr>
546+
* Attribute | Adherence
547+
* ------------------ | -------------
548+
* Allocates Memory | Maybe
549+
* Thread-Safe | Yes
550+
* Uses Atomics | Maybe [1]
551+
* Lock-Free | Maybe [1]
425552
*
426-
* In contrast to \sa `rmw_publish` the ownership of the ros message is being transferred to the
427-
* middleware which might deallocate the memory for it.
428-
* Similar to \sa `rmw_return_loaned_message_from_publisher` the passed in ros message might
429-
* not be valid after this call and thus should only be called with messages previously loaned with
430-
* a call to \sa `rmw_borrow_loaned_message`.
553+
* <i>[1] implementation defined, check the implementation documentation.</i>
554+
*
555+
* \par Runtime behavior
556+
* It is implementation defined whether to publish a loaned ROS message is a
557+
* synchronous or asynchronous, blocking or non-blocking operation.
558+
* Check the implementation documentation to learn about publish behavior.
559+
*
560+
* \par Memory allocation
561+
* It is implementation defined whether memory will be allocated on publish or not.
562+
* For instance, implementations that serialize ROS messages to send it over the
563+
* wire may need to perform additional memory allocations when dealing with
564+
* unbounded (dynamically-sized) fields.
565+
* A publisher allocation, if provided, may or may not be used.
566+
* Check the implementation documentation to learn about memory allocation
567+
* guarantees when publishing loaned ROS messages with and without publisher allocations.
568+
*
569+
* \par Thread-safety
570+
* Publishers are thread-safe objects, and so are all operations on them except for finalization.
571+
* Therefore, it is safe to publish using the same publisher concurrently.
572+
* However, when publishing loaned ROS messages:
573+
* - Ownership of the loaned ROS message is given back to the middleware.
574+
* This transfer is not synchronized, and thus it is not safe to publish the
575+
* same loaned ROS message concurrently.
576+
* - Access to the publisher allocation is not synchronized, unless specifically stated
577+
* otherwise by the implementation.
578+
* Thus, it is generally not safe to read or write `allocation` while rmw_publish() uses it.
579+
* Check the implementation documentation to learn about publisher allocations' thread-safety.
580+
*
581+
* \pre Given `publisher` must be a valid publisher, as returned by rmw_create_publisher().
582+
* \pre Given `ros_message` must be a valid message, borrowed from the same publisher using
583+
* rmw_borrow_loaned_message().
584+
* \pre If not NULL, given `allocation` must be a valid publisher allocation, initialized
585+
* with rmw_publisher_allocation_init() with a message type support that matches the
586+
* one registered with `publisher` on creation.
431587
*
432588
* \param[in] publisher Publisher to be used to send message.
433-
* \param[in] ros_message Message to be sent.
434-
* \param[in] allocation Specify preallocated memory to use (may be NULL).
589+
* \param[in] ros_message Loaned type erased ROS message to be sent.
590+
* \param[in] allocation Pre-allocated memory to be used. May be NULL.
435591
* \return `RMW_RET_OK` if successful, or
436-
* \return `RMW_RET_INVALID_ARGUMENT` if publisher or ros_message is null, or
437-
* \return `RMW_RET_UNSUPPORTED` if the rmw_implementation does not support loaned_message, or
592+
* \return `RMW_RET_INVALID_ARGUMENT` if `publisher` is NULL, or
593+
* \return `RMW_RET_INVALID_ARGUMENT` if `ros_message` is NULL, or
594+
* \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if `publisher` implementation
595+
* identifier does not match this implementation, or
596+
* \return `RMW_RET_UNSUPPORTED` if the implementation does not support ROS message loaning, or
438597
* \return `RMW_RET_ERROR` if an unexpected error occurs.
439598
*/
440599
RMW_PUBLIC
@@ -512,18 +671,62 @@ rmw_publisher_get_actual_qos(
512671
const rmw_publisher_t * publisher,
513672
rmw_qos_profile_t * qos);
514673

515-
/// Publish an already serialized message.
674+
/// Publish a ROS message as a byte stream.
516675
/**
517-
* The publisher must already be registered with the correct message type
518-
* support so that it can send serialized data corresponding to that type.
519-
* This function sends the serialized byte stream directly over the wire without
520-
* having to serialize the message first.
521-
* A ROS message can be serialized manually using the rmw_serialize() function.
522-
*
523-
* \param[in] publisher The publisher object registered to send the message.
524-
* \param[in] serialized_message The serialized message holding the byte stream.
525-
* \param[in] allocation Specify preallocated memory to use (may be NULL).
676+
* Send a ROS message serialized as a byte stream to all subscriptions with
677+
* matching QoS policies using the given publisher.
678+
* A ROS message can be serialized manually using rmw_serialize().
679+
*
680+
* <hr>
681+
* Attribute | Adherence
682+
* ------------------ | -------------
683+
* Allocates Memory | Maybe
684+
* Thread-Safe | Yes
685+
* Uses Atomics | Maybe [1]
686+
* Lock-Free | Maybe [1]
687+
*
688+
* <i>[1] implementation defined, check the implementation documentation.</i>
689+
*
690+
* \par Runtime behavior
691+
* It is implementation defined whether to publish a loaned ROS message is a
692+
* synchronous or asynchronous, blocking or non-blocking operation.
693+
* However, asynchronous implementations are not allowed to access the
694+
* given byte stream after this function returns.
695+
* Check the implementation documentation to learn about publish behavior.
696+
*
697+
* \par Memory allocation
698+
* It is implementation defined whether memory will be allocated on publish or not.
699+
* Even if a publisher allocation is provided, an implementation may ignore it.
700+
* Check the implementation documentation to learn about memory allocation
701+
* guarantees when publishing serialized messages with and without publisher allocations.
702+
*
703+
* \par Thread-safety
704+
* Publishers are thread-safe objects, and so are all operations on them except for finalization.
705+
* Therefore, it is safe to publish using the same publisher concurrently.
706+
* However, when publishing serialized ROS messages:
707+
* - Access to the byte stream is read-only but it is not synchronized.
708+
* Concurrent `serialized_message` reads are safe, but concurrent reads and writes are not.
709+
* - Access to the publisher allocation is not synchronized, unless specifically stated
710+
* otherwise by the implementation.
711+
* Thus, it is generally not safe to read or write `allocation` while rmw_publish() uses it.
712+
* Check the implementation documentation to learn about publisher allocations' thread-safety.
713+
*
714+
* \pre Given `publisher` must be a valid publisher, as returned by rmw_create_publisher().
715+
* \pre Given `serialized_message` must be a valid serialized message, initialized by
716+
* rmw_serialized_message_init() and containing the serialization of a ROS message whose
717+
* type matches the message type support the `publisher` was registered with on creation.
718+
* \pre If not NULL, given `allocation` must be a valid publisher allocation, initialized
719+
* with rmw_publisher_allocation_init() with a message type support that matches the
720+
* one registered with `publisher` on creation.
721+
*
722+
* \param[in] publisher Publisher to be used to send message.
723+
* \param[in] ros_message Serialized ROS message to be sent.
724+
* \param[in] allocation Pre-allocated memory to be used. May be NULL.
526725
* \return `RMW_RET_OK` if successful, or
726+
* \return `RMW_RET_INVALID_ARGUMENT` if `publisher` is NULL, or
727+
* \return `RMW_RET_INVALID_ARGUMENT` if `serialized_message` is NULL, or
728+
* \return `RMW_RET_INCORRECT_RMW_IMPLEMENTATION` if `publisher` implementation
729+
* identifier does not match this implementation, or
527730
* \return `RMW_RET_ERROR` if an unexpected error occurs.
528731
*/
529732
RMW_PUBLIC

0 commit comments

Comments
 (0)