diff options
author | Erik De Rijcke <Erik.De.Rijcke@prodatamobility.com> | 2015-03-23 15:34:52 +0100 |
---|---|---|
committer | Erik De Rijcke <Erik.De.Rijcke@prodatamobility.com> | 2015-03-23 15:34:52 +0100 |
commit | 60e1719f672bd34898cdfa2f78a6823978a86c07 (patch) | |
tree | 9bc722b82351fd21c7e3b8d9dfaa7ff919ac3469 | |
parent | 3ec8814ef819b83d14ed07373ebfdb3c2f85daa8 (diff) |
gc event handlers when event source goes out of scope
-rw-r--r-- | stubs/src/main/java/org/freedesktop/wayland/server/EventLoop.java | 222 | ||||
-rw-r--r-- | stubs/src/main/java/org/freedesktop/wayland/server/EventSource.java | 26 |
2 files changed, 94 insertions, 154 deletions
diff --git a/stubs/src/main/java/org/freedesktop/wayland/server/EventLoop.java b/stubs/src/main/java/org/freedesktop/wayland/server/EventLoop.java index 48cf2a6..d63d2c6 100644 --- a/stubs/src/main/java/org/freedesktop/wayland/server/EventLoop.java +++ b/stubs/src/main/java/org/freedesktop/wayland/server/EventLoop.java @@ -18,12 +18,16 @@ import org.freedesktop.wayland.HasNative; import org.freedesktop.wayland.server.jna.*; import org.freedesktop.wayland.util.ObjectCache; +import java.awt.*; import java.util.HashMap; import java.util.Map; +import java.util.WeakHashMap; public class EventLoop implements HasNative<Pointer> { - private static final Map<Pointer, Object> HANDLER_REFS = new HashMap<Pointer, Object>(); + private static final Map<Pointer, Object> HANDLER_REFS = new WeakHashMap<Pointer, Object>(); + //this map is used to link handler object lifecycle to an event source + private static final Map<EventSource, Pointer> EVENT_SOURCE_HANDLER_REFS = new WeakHashMap<EventSource, Pointer>(); private static final wl_event_loop_fd_func_t WL_EVENT_LOOP_FD_FUNC = new wl_event_loop_fd_func_t() { @Override @@ -31,8 +35,33 @@ public class EventLoop implements HasNative<Pointer> { final int mask, final Pointer data) { final FileDescriptorEventHandler handler = (FileDescriptorEventHandler) HANDLER_REFS.get(data); - return handler.handle(fd, - mask); + return handler.handle(fd, + mask); + } + }; + + private static final wl_event_loop_timer_func_t WL_EVENT_LOOP_TIMER_FUNC = new wl_event_loop_timer_func_t() { + @Override + public int apply(final Pointer data) { + final TimerEventHandler handler = (TimerEventHandler) HANDLER_REFS.get(data); + return handler.handle(); + } + }; + + private static final wl_event_loop_signal_func_t WL_EVENT_LOOP_SIGNAL_FUNC = new wl_event_loop_signal_func_t() { + @Override + public int apply(final int signalNumber, + final Pointer data) { + final SignalEventHandler handler = (SignalEventHandler) HANDLER_REFS.get(data); + return handler.handle(signalNumber); + } + }; + + private static final wl_event_loop_idle_func_t WL_EVENT_LOOP_IDLE_FUNC = new wl_event_loop_idle_func_t() { + @Override + public void apply(final Pointer data) { + final IdleHandler handler = (IdleHandler) HANDLER_REFS.get(data); + handler.handle(); } }; @@ -69,169 +98,62 @@ public class EventLoop implements HasNative<Pointer> { public EventSource addFileDescriptor(final int fd, final int mask, final FileDescriptorEventHandler handler) { -// static struct wl_event_source * -// add_source(struct wl_event_loop *loop, -// struct wl_event_source *source, uint32_t mask, void *data) -// { -// struct epoll_event ep; -// -// if (source->fd < 0) { -// free(source); -// return NULL; -// } -// -// source->loop = loop; -// source->data = data; -// wl_list_init(&source->link); -// -// memset(&ep, 0, sizeof ep); -// if (mask & WL_EVENT_READABLE) -// ep.events |= EPOLLIN; -// if (mask & WL_EVENT_WRITABLE) -// ep.events |= EPOLLOUT; -// ep.data.ptr = source; -// -// if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) { -// close(source->fd); -// free(source); -// return NULL; -// } -// -// return source; -// } -// -// WL_EXPORT struct wl_event_source * -// wl_event_loop_add_fd(struct wl_event_loop *loop, -// int fd, uint32_t mask, -// wl_event_loop_fd_func_t func, -// void *data) -// { -// struct wl_event_source_fd *source; -// -// source = malloc(sizeof *source); -// if (source == NULL) -// return NULL; -// -// source->base.interface = &fd_source_interface; -// source->base.fd = fcntl(fd, F_DUPFD_CLOEXEC, 0); -// source->func = func; -// source->fd = fd; -// -// return add_source(loop, &source->base, mask, data); -// } final Pointer handlerRef = Pointer.createConstant(handler.hashCode()); - //FIXME memleak: handler will never be garbage collected + //handler will be garbage collected once event source is collected. HANDLER_REFS.put(handlerRef, handler); - final Pointer wlEventSource = WaylandServerLibrary.INSTANCE() - .wl_event_loop_add_fd(getNative(), - fd, - mask, - WL_EVENT_LOOP_FD_FUNC, - handlerRef); - - return EventSource.create(wlEventSource); + final EventSource eventSource = EventSource.create(WaylandServerLibrary.INSTANCE() + .wl_event_loop_add_fd(getNative(), + fd, + mask, + WL_EVENT_LOOP_FD_FUNC, + handlerRef)); + EVENT_SOURCE_HANDLER_REFS.put(eventSource, + handlerRef); + return eventSource; } public EventSource addTimer(final TimerEventHandler handler) { -// struct wl_event_source_timer *source; -// -// source = malloc(sizeof *source); -// if (source == NULL) -// return NULL; -// -// source->base.interface = &timer_source_interface; -// source->base.fd = timerfd_create(CLOCK_MONOTONIC, -// TFD_CLOEXEC | TFD_NONBLOCK); -// source->func = func; -// -// return add_source(loop, &source->base, WL_EVENT_READABLE, data); - //FIXME use better callback mechanism to avoid memory leaks - - final wl_event_loop_timer_func_t nativeCallback = new wl_event_loop_timer_func_t() { - @Override - public int apply(final Pointer data) { - return handler.handle(); - } - }; - //this call is equivalent to + final Pointer handlerRef = Pointer.createConstant(handler.hashCode()); + //handler will be garbage collected once event source is collected. + HANDLER_REFS.put(handlerRef, + handler); final EventSource eventSource = EventSource.create(WaylandServerLibrary.INSTANCE() - .wl_event_loop_add_timer(getNative(), - nativeCallback, - Pointer.NULL)); - this.HANDLER_REFS.put(eventSource, - nativeCallback); + .wl_event_loop_add_timer(getNative(), + WL_EVENT_LOOP_TIMER_FUNC, + handlerRef)); + EVENT_SOURCE_HANDLER_REFS.put(eventSource, + handlerRef); return eventSource; } public EventSource addSignal(final int signalNumber, final SignalEventHandler handler) { - // struct wl_event_source_signal *source; -// sigset_t mask; -// -// source = malloc(sizeof *source); -// if (source == NULL) -// return NULL; -// -// source->base.interface = &signal_source_interface; -// source->signal_number = signal_number; -// -// sigemptyset(&mask); -// sigaddset(&mask, signal_number); -// source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC); -// sigprocmask(SIG_BLOCK, &mask, NULL); -// -// source->func = func; -// -// return add_source(loop, &source->base, WL_EVENT_READABLE, data); - final wl_event_loop_signal_func_t nativeCallback = new wl_event_loop_signal_func_t() { - @Override - public int apply(final int signal_number, - final Pointer data) { - return handler.handle(signalNumber); - } - }; - final Pointer wlEventSource = WaylandServerLibrary.INSTANCE() - .wl_event_loop_add_signal(getNative(), - signalNumber, - nativeCallback, - Pointer.NULL); - final EventSource eventSource = EventSource.create(wlEventSource); - this.HANDLER_REFS.put(eventSource, - nativeCallback); + final Pointer handlerRef = Pointer.createConstant(handler.hashCode()); + //handler will be garbage collected once event source is collected. + HANDLER_REFS.put(handlerRef, + handler); + final EventSource eventSource = EventSource.create(WaylandServerLibrary.INSTANCE() + .wl_event_loop_add_signal(getNative(), + signalNumber, + WL_EVENT_LOOP_SIGNAL_FUNC, + handlerRef)); + EVENT_SOURCE_HANDLER_REFS.put(eventSource, + handlerRef); return eventSource; } public EventSource addIdle(final IdleHandler handler) { -// struct wl_event_source_idle *source; -// -// source = malloc(sizeof *source); -// if (source == NULL) -// return NULL; -// -// source->base.interface = &idle_source_interface; -// source->base.loop = loop; -// source->base.fd = -1; -// -// source->func = func; -// source->base.data = data; -// -// wl_list_insert(loop->idle_list.prev, &source->base.link); -// -// return &source->base; - final wl_event_loop_idle_func_t nativeCallback = new wl_event_loop_idle_func_t() { - @Override - public void apply(final Pointer data) { - handler.handle(); - } - }; - final Pointer wlEventSource = WaylandServerLibrary.INSTANCE() - .wl_event_loop_add_idle(getNative(), - nativeCallback, - Pointer.NULL); - final EventSource eventSource = EventSource.create(wlEventSource); - this.HANDLER_REFS.put(eventSource, - nativeCallback); + final Pointer handlerRef = Pointer.createConstant(handler.hashCode()); + //handler will be garbage collected once event source is collected. + HANDLER_REFS.put(handlerRef, + handler); + final EventSource eventSource = EventSource.create(WaylandServerLibrary.INSTANCE() + .wl_event_loop_add_idle(getNative(), + WL_EVENT_LOOP_IDLE_FUNC, + handlerRef)); + EVENT_SOURCE_HANDLER_REFS.put(eventSource, + handlerRef); return eventSource; } diff --git a/stubs/src/main/java/org/freedesktop/wayland/server/EventSource.java b/stubs/src/main/java/org/freedesktop/wayland/server/EventSource.java index ba979c1..960405e 100644 --- a/stubs/src/main/java/org/freedesktop/wayland/server/EventSource.java +++ b/stubs/src/main/java/org/freedesktop/wayland/server/EventSource.java @@ -16,15 +16,22 @@ package org.freedesktop.wayland.server; import com.sun.jna.Pointer; import org.freedesktop.wayland.HasNative; import org.freedesktop.wayland.server.jna.WaylandServerLibrary; +import org.freedesktop.wayland.util.ObjectCache; public class EventSource implements HasNative<Pointer> { + private final Pointer pointer; + private boolean valid; + protected EventSource(final Pointer pointer) { this.pointer = pointer; + this.valid = true; + ObjectCache.store(getNative(), + this); } - protected static EventSource create(final Pointer pointer) { + public static EventSource create(final Pointer pointer) { return new EventSource(pointer); } @@ -41,8 +48,13 @@ public class EventSource implements HasNative<Pointer> { } public int remove() { - return WaylandServerLibrary.INSTANCE() - .wl_event_source_remove(getNative()); + if(this.valid) { + this.valid = false; + ObjectCache.remove(getNative()); + return WaylandServerLibrary.INSTANCE() + .wl_event_source_remove(getNative()); + } + return 0; } public void check() { @@ -77,6 +89,12 @@ public class EventSource implements HasNative<Pointer> { @Override public boolean isValid() { //no way to track event source lifecycle, so it's always valid to us. - return true; + return this.valid; + } + + @Override + protected void finalize() throws Throwable { + remove(); + super.finalize(); } } |