Skip to content

Commit 093a101

Browse files
committed
Add publisher liveliness lost event (osrf#9)
* Create LivelinessLostEvent Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Fix linking issue Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Rename disposeEventHandler to removeEventHandler Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Use synchronized methods in EventHandlerImpl Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Use createEventHandler instead of registerEventHanlder Signed-off-by: Ivan Santiago Paunovic <[email protected]> * nit Signed-off-by: Ivan Santiago Paunovic <[email protected]> * Clarify ownership of the event handle Signed-off-by: Ivan Santiago Paunovic <[email protected]>
1 parent cc1bacf commit 093a101

15 files changed

+358
-56
lines changed

rcljava/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ set(${PROJECT_NAME}_jni_sources
6060
"src/main/cpp/org_ros2_rcljava_contexts_ContextImpl.cpp"
6161
"src/main/cpp/org_ros2_rcljava_executors_BaseExecutor.cpp"
6262
"src/main/cpp/org_ros2_rcljava_events_EventHandlerImpl.cpp"
63+
"src/main/cpp/org_ros2_rcljava_events_publisher_statuses_LivelinessLost.cpp"
6364
"src/main/cpp/org_ros2_rcljava_node_NodeImpl.cpp"
6465
"src/main/cpp/org_ros2_rcljava_publisher_PublisherImpl.cpp"
6566
"src/main/cpp/org_ros2_rcljava_service_ServiceImpl.cpp"
@@ -129,6 +130,9 @@ set(${PROJECT_NAME}_sources
129130
"src/main/java/org/ros2/rcljava/events/EventHandler.java"
130131
"src/main/java/org/ros2/rcljava/events/EventHandlerImpl.java"
131132
"src/main/java/org/ros2/rcljava/events/EventStatus.java"
133+
"src/main/java/org/ros2/rcljava/events/PublisherEventStatus.java"
134+
"src/main/java/org/ros2/rcljava/events/SubscriptionEventStatus.java"
135+
"src/main/java/org/ros2/rcljava/events/publisher_statuses/LivelinessLost.java"
132136
"src/main/java/org/ros2/rcljava/executors/AnyExecutable.java"
133137
"src/main/java/org/ros2/rcljava/executors/BaseExecutor.java"
134138
"src/main/java/org/ros2/rcljava/executors/Executor.java"

rcljava/include/org_ros2_rcljava_events_EventHandlerImpl.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ extern "C" {
2727
* Signature: (J)V
2828
*/
2929
JNIEXPORT void
30-
JNICALL Java_org_ros2_rcljava_events_EventHandlerImpl_nativeDispose(JNIEnv *, jclass, jlong event_handle);
30+
JNICALL Java_org_ros2_rcljava_events_EventHandlerImpl_nativeDispose(
31+
JNIEnv *, jclass, jlong event_handle);
3132

3233
/*
3334
* Class: org_ros2_rcljava_events_EventHandlerImpl
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright 2020 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include <jni.h>
16+
/* Header for class org_ros2_rcljava_events_publisher_statuses_LivelinessLost */
17+
18+
#ifndef ORG_ROS2_RCLJAVA_EVENTS_PUBLISHER_STATUSES_LIVELINESSLOST_H_
19+
#define ORG_ROS2_RCLJAVA_EVENTS_PUBLISHER_STATUSES_LIVELINESSLOST_H_
20+
#ifdef __cplusplus
21+
extern "C" {
22+
#endif
23+
24+
/*
25+
* Class: org_ros2_rcljava_events_publisher_statuses_LivelinessLost
26+
* Method: nativeAllocateRCLStatusEvent
27+
* Signature: ()J
28+
*/
29+
JNIEXPORT jlong JNICALL
30+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeAllocateRCLStatusEvent(
31+
JNIEnv *, jclass);
32+
33+
/*
34+
* Class: org_ros2_rcljava_events_publisher_statuses_LivelinessLost
35+
* Method: nativeDeallocateRCLStatusEvent
36+
* Signature: (J)V
37+
*/
38+
JNIEXPORT void JNICALL
39+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeDeallocateRCLStatusEvent(
40+
JNIEnv *, jclass, jlong);
41+
42+
/*
43+
* Class: org_ros2_rcljava_events_publisher_statuses_LivelinessLost
44+
* Method: nativeFromRCLEvent
45+
* Signature: (J)V
46+
*/
47+
JNIEXPORT void JNICALL
48+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeFromRCLEvent(
49+
JNIEnv *, jobject, jlong);
50+
51+
/*
52+
* Class: org_ros2_rcljava_events_publisher_statuses_LivelinessLost
53+
* Method: nativeGetPublisherEventType
54+
* Signature: ()I
55+
*/
56+
JNIEXPORT jint JNICALL
57+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeGetPublisherEventType(
58+
JNIEnv *, jclass);
59+
60+
#ifdef __cplusplus
61+
}
62+
#endif
63+
#endif // ORG_ROS2_RCLJAVA_EVENTS_PUBLISHER_STATUSES_LIVELINESSLOST_H_

rcljava/include/org_ros2_rcljava_publisher_PublisherImpl.h

+9
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ JNIEXPORT void
3838
JNICALL Java_org_ros2_rcljava_publisher_PublisherImpl_nativeDispose(
3939
JNIEnv *, jclass, jlong, jlong);
4040

41+
/*
42+
* Class: org_ros2_rcljava_publisher_PublisherImpl
43+
* Method: nativeCreateEvent
44+
* Signature: (JJ)J
45+
*/
46+
JNIEXPORT jlong
47+
JNICALL Java_org_ros2_rcljava_publisher_PublisherImpl_nativeCreateEvent(
48+
JNIEnv *, jclass, jlong, jint);
49+
4150
#ifdef __cplusplus
4251
}
4352
#endif

rcljava/src/main/cpp/org_ros2_rcljava_events_EventHandlerImpl.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ Java_org_ros2_rcljava_events_EventHandlerImpl_nativeDispose(
4747
}
4848

4949
JNIEXPORT void JNICALL
50-
Java_org_ros2_rcljava_events_EventHandlerImpl_nativeTake(JNIEnv *env, jclass, jlong event_handle, jlong event_status_handle)
50+
Java_org_ros2_rcljava_events_EventHandlerImpl_nativeTake(
51+
JNIEnv * env, jclass, jlong event_handle, jlong event_status_handle)
5152
{
5253
auto * event = reinterpret_cast<rcl_event_t *>(event_handle);
5354
if (!event) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// Copyright 2020 Open Source Robotics Foundation, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "org_ros2_rcljava_events_publisher_statuses_LivelinessLost.h"
16+
17+
#include <jni.h>
18+
#include <stdlib.h>
19+
20+
#include "rmw/events_statuses/liveliness_lost.h"
21+
#include "rcl/event.h"
22+
#include "rcljava_common/exceptions.hpp"
23+
24+
using rcljava_common::exceptions::rcljava_throw_exception;
25+
26+
JNIEXPORT jlong JNICALL
27+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeAllocateRCLStatusEvent(
28+
JNIEnv * env, jclass)
29+
{
30+
void * p = malloc(sizeof(rmw_liveliness_lost_status_t));
31+
if (!p) {
32+
rcljava_throw_exception(
33+
env, "java/lang/OutOfMemoryError", "failed to allocate liveliness lost status");
34+
}
35+
return reinterpret_cast<jlong>(p);
36+
}
37+
38+
JNIEXPORT void JNICALL
39+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeDeallocateRCLStatusEvent(
40+
JNIEnv *, jclass, jlong handle)
41+
{
42+
free(reinterpret_cast<void *>(handle));
43+
}
44+
45+
JNIEXPORT void JNICALL
46+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeFromRCLEvent(
47+
JNIEnv * env, jobject self, jlong handle)
48+
{
49+
auto * p = reinterpret_cast<rmw_liveliness_lost_status_t *>(handle);
50+
if (!p) {
51+
rcljava_throw_exception(
52+
env, "java/lang/IllegalArgumentException", "passed rmw object handle is NULL");
53+
}
54+
// TODO(ivanpauno): class and field lookup could be done at startup time
55+
jclass clazz = env->GetObjectClass(self);
56+
jfieldID total_count_fid = env->GetFieldID(clazz, "total_count", "I");
57+
if (env->ExceptionCheck()) {
58+
return;
59+
}
60+
jfieldID total_count_change_fid = env->GetFieldID(clazz, "total_count_change", "I");
61+
if (env->ExceptionCheck()) {
62+
return;
63+
}
64+
env->SetIntField(self, total_count_fid, p->total_count);
65+
env->SetIntField(self, total_count_change_fid, p->total_count_change);
66+
}
67+
68+
JNIEXPORT jint JNICALL
69+
Java_org_ros2_rcljava_events_publisher_1statuses_LivelinessLost_nativeGetPublisherEventType(
70+
JNIEnv *, jclass)
71+
{
72+
return RCL_PUBLISHER_LIVELINESS_LOST;
73+
}

rcljava/src/main/cpp/org_ros2_rcljava_publisher_PublisherImpl.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <string>
2121

2222
#include "rcl/error_handling.h"
23+
#include "rcl/event.h"
2324
#include "rcl/node.h"
2425
#include "rcl/rcl.h"
2526
#include "rmw/rmw.h"
@@ -29,6 +30,7 @@
2930

3031
#include "org_ros2_rcljava_publisher_PublisherImpl.h"
3132

33+
using rcljava_common::exceptions::rcljava_throw_exception;
3234
using rcljava_common::exceptions::rcljava_throw_rclexception;
3335
using rcljava_common::signatures::convert_from_java_signature;
3436
using rcljava_common::signatures::destroy_ros_message_signature;
@@ -90,3 +92,31 @@ Java_org_ros2_rcljava_publisher_PublisherImpl_nativeDispose(
9092
rcljava_throw_rclexception(env, ret, msg);
9193
}
9294
}
95+
96+
JNIEXPORT jlong JNICALL
97+
Java_org_ros2_rcljava_publisher_PublisherImpl_nativeCreateEvent(
98+
JNIEnv * env, jclass, jlong publisher_handle, jint event_type)
99+
{
100+
auto * publisher = reinterpret_cast<rcl_publisher_t *>(publisher_handle);
101+
if (!publisher) {
102+
rcljava_throw_exception(
103+
env, "java/lang/IllegalArgumentException", "passed rcl_publisher_t handle is NULL");
104+
return 0;
105+
}
106+
auto * event = static_cast<rcl_event_t *>(malloc(sizeof(rcl_event_t)));
107+
if (!event) {
108+
rcljava_throw_exception(env, "java/lang/OutOfMemoryError", "failed to allocate rcl_event_t");
109+
return 0;
110+
}
111+
*event = rcl_get_zero_initialized_event();
112+
rcl_ret_t ret = rcl_publisher_event_init(
113+
event, publisher, static_cast<rcl_publisher_event_type_t>(event_type));
114+
if (RCL_RET_OK != ret) {
115+
std::string msg = "Failed to create event: " + std::string(rcl_get_error_string().str);
116+
rcl_reset_error();
117+
rcljava_throw_rclexception(env, ret, msg);
118+
free(event);
119+
return 0;
120+
}
121+
return reinterpret_cast<jlong>(event);
122+
}

rcljava/src/main/java/org/ros2/rcljava/events/EventHandler.java

-10
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,6 @@
2929
* @param <ParentT> The parent class type.
3030
*/
3131
public interface EventHandler<T extends EventStatus, ParentT extends Disposable> extends Disposable {
32-
/**
33-
* @return The event status type.
34-
*/
35-
Class<T> getEventStatusType();
36-
37-
/**
38-
* @return The parent entity type.
39-
*/
40-
Class<ParentT> getParentType();
41-
4232
/**
4333
* @return A weak reference to the parent.
4434
*/

rcljava/src/main/java/org/ros2/rcljava/events/EventHandlerImpl.java

+13-42
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import java.lang.ref.WeakReference;
1818
import java.lang.reflect.InvocationTargetException;
19+
import java.util.function.Supplier;
1920

2021
import org.ros2.rcljava.common.JNIUtils;
2122
import org.ros2.rcljava.consumers.Consumer;
@@ -53,48 +54,28 @@ public class EventHandlerImpl<
5354
/**
5455
* Constructor.
5556
*
56-
* @param parentType The <code>Class</code> type of the parent.
57-
* It can be either a @{link org.ros2.rcljava.Publisher} or a
58-
* @{link org.ros2.rcljava.Subscription} class.
5957
* @param parentReference A {@link java.lang.ref.WeakReference} to the
6058
* @{link org.ros2.rcljava.Publisher} or @{link org.ros2.rcljava.Subscription}
6159
* that created this event handler.
6260
* @param handle A pointer to the underlying ROS 2 event structure, as an integer.
6361
* Must not be zero.
64-
* @param eventStatusType The <code>Class</code> of the messages that this
65-
* subscription will receive. We need this because of Java's type erasure,
66-
* which doesn't allow us to use the generic parameter of
67-
* @{link org.ros2.rcljava.Subscription} directly.
62+
* Ownership of the passed `handle` is taken, and this object is responsible
63+
* of disposing it. That can be done using @{link EventHandler#dispose()}.
64+
* @param eventStatusFactory Factory of an event status.
6865
* @param callback The callback function that will be called when the event
6966
* is triggered.
7067
*/
7168
public EventHandlerImpl(
72-
final Class<ParentT> parentType,
7369
final WeakReference<ParentT> parentReference,
7470
final long handle,
75-
final Class<T> eventStatusType,
71+
final Supplier<T> eventStatusFactory,
7672
final Consumer<T> callback) {
77-
this.parentType = parentType;
7873
this.parentReference = parentReference;
7974
this.handle = handle;
80-
this.eventStatusType = eventStatusType;
75+
this.eventStatusFactory = eventStatusFactory;
8176
this.callback = callback;
8277
}
8378

84-
/**
85-
* {@inheritDoc}
86-
*/
87-
public final Class<T> getEventStatusType() {
88-
return this.eventStatusType;
89-
}
90-
91-
/**
92-
* {@inheritDoc}
93-
*/
94-
public final Class<ParentT> getParentType() {
95-
return this.parentType;
96-
}
97-
9879
/**
9980
* {@inheritDoc}
10081
*/
@@ -120,8 +101,10 @@ public final long getHandle() {
120101
/**
121102
* {@inheritDoc}
122103
*/
123-
public final void dispose() {
124-
nativeDispose(this.handle);
104+
public synchronized final void dispose() {
105+
if (this.handle != 0) {
106+
nativeDispose(this.handle);
107+
}
125108
this.handle = 0;
126109
}
127110

@@ -137,28 +120,16 @@ public final void dispose() {
137120
/**
138121
* {@inheritDoc}
139122
*/
140-
public final void executeCallback() {
141-
T eventStatus = null;
142-
try {
143-
eventStatus = this.eventStatusType.getDeclaredConstructor().newInstance();
144-
} catch (NoSuchMethodException nme) {
145-
nme.printStackTrace();
146-
} catch (InvocationTargetException ite) {
147-
ite.printStackTrace();
148-
} catch (InstantiationException ie) {
149-
ie.printStackTrace();
150-
} catch (IllegalAccessException iae) {
151-
iae.printStackTrace();
152-
}
123+
public synchronized final void executeCallback() {
124+
T eventStatus = eventStatusFactory.get();
153125
long nativeEventStatusHandle = eventStatus.allocateRCLStatusEvent();
154126
nativeTake(this.handle, nativeEventStatusHandle);
155127
eventStatus.fromRCLEvent(nativeEventStatusHandle);
156128
eventStatus.deallocateRCLStatusEvent(nativeEventStatusHandle);
157129
callback.accept(eventStatus);
158130
}
159131

160-
private final Class<T> eventStatusType;
161-
private final Class<ParentT> parentType;
132+
private final Supplier<T> eventStatusFactory;
162133
private final WeakReference<ParentT> parentReference;
163134
private long handle;
164135
private final Consumer<T> callback;

rcljava/src/main/java/org/ros2/rcljava/events/PublisherEventStatus.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ public interface PublisherEventStatus extends EventStatus {
2424
/**
2525
* @return The status event type.
2626
*/
27-
int get_publisher_event_type();
27+
int getPublisherEventType();
2828
}

rcljava/src/main/java/org/ros2/rcljava/events/SubscriptionEventStatus.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ public interface SubscriptionEventStatus extends EventStatus {
2424
/**
2525
* @return The status event type.
2626
*/
27-
int get_subscription_event_type();
27+
int getSubscriptionEventType();
2828
}

0 commit comments

Comments
 (0)