All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.objectfabric.Notifier Maven / Gradle / Ivy
/**
* This file is part of ObjectFabric (http://objectfabric.org).
*
* ObjectFabric is licensed under the Apache License, Version 2.0, the terms
* of which may be found at http://www.apache.org/licenses/LICENSE-2.0.html.
*
* Copyright ObjectFabric Inc.
*
* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
* WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
package org.objectfabric;
import java.util.concurrent.Executor;
import org.objectfabric.Actor.Message;
import org.objectfabric.TObject.Transaction;
import org.objectfabric.ThreadAssert.AllowSharedRead;
import org.objectfabric.ThreadAssert.SingleThreaded;
import org.objectfabric.Workspace.Granularity;
/**
* Invokes listeners which are registered on transactional objects, and raise callbacks
* for asynchronous operations. The notifier maintains ordering, and executes all
* callbacks on the notification executor. If the executor maintains order too, listeners
* are invoked in the same order as transactions that made those changes were committed.
*/
@SuppressWarnings({ "serial", "rawtypes" })
@SingleThreaded
class Notifier extends Dispatcher {
@AllowSharedRead
private final Run _run;
private Transaction _committed, _previous;
Notifier(Workspace workspace) {
super(workspace, false);
_run = new Run(workspace.callbackExecutor());
}
final void start() {
workspace().register(this, _run);
init(true, false);
if (Debug.THREADS)
ThreadAssert.exchangeGive(_run, this);
_run.onStarted();
}
final Run run() {
return _run;
}
final class Run extends Actor implements Runnable {
private final Executor _executor;
Run(Executor executor) {
_executor = executor;
}
@Override
protected void enqueue() {
_executor.execute(this);
}
@Override
public void run() {
if (Debug.ENABLED)
ThreadAssert.resume(this, false);
if (Debug.THREADS)
ThreadAssert.exchangeTake(this);
onRunStarting();
runMessages();
walk();
if (Debug.ENABLED)
ThreadAssert.suspend(this);
onRunEnded();
}
}
//
static final class CustomExecutorListener {
final Object Listener;
final Executor Executor;
CustomExecutorListener(Object listener, Executor executor) {
Listener = listener;
Executor = executor;
}
@Override
public int hashCode() {
return Listener.hashCode() ^ Executor.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
CustomExecutorListener other = (CustomExecutorListener) obj;
return Listener.equals(other.Listener) && Executor.equals(other.Executor);
}
}
final void addListener(TObject object, Object listener) {
_run.addAndRun(new AddListener(object, listener));
}
final void removeListener(TObject object, Object listener) {
_run.addAndRun(new RemoveListener(object, listener));
}
final void raiseFieldListener(TObject object, int fieldIndex) {
_run.addAndRun(new RaiseIndexListener(object, fieldIndex));
}
final void raisePropertyListener(TObject object, String propertyName) {
_run.addAndRun(new RaisePropertyListener(object, propertyName));
}
//
@Override
Action onVisitingMap(int mapIndex) {
Action action = super.onVisitingMap(mapIndex);
if (action == Action.VISIT && workspace().granularity() == Granularity.ALL) {
VersionMap map = snapshot().getVersionMaps()[mapIndex];
if (Debug.ENABLED) {
Debug.assertion(map.getTransaction().getVersionMap() == map);
Debug.assertion(map.getTransaction().getSnapshot().last() == map);
}
_committed = map.getTransaction();
_previous = workspace().transaction();
workspace().setTransaction(_committed);
}
return action;
}
@Override
final void releaseSnapshot(int start, int end) {
if (workspace().granularity() == Granularity.ALL) {
VersionMap map = snapshot().getVersionMaps()[start];
if (Debug.ENABLED) {
Debug.assertion(_committed == map.getTransaction());
Debug.assertion(workspace().transaction() == _committed);
}
workspace().setTransaction(_previous);
_committed = null;
_previous = null;
}
super.releaseSnapshot(start, end);
}
@Override
final Action onVisitingTObject(TObject object) {
Action action = super.onVisitingTObject(object);
if (action == Action.VISIT)
if (object.listeners() == null)
return Action.SKIP;
return action;
}
//
private static abstract class Invocation {
abstract void run(Object listener);
}
private static void invoke(TObject object, final Invocation invocation) {
for (Object listener : object.listeners()) {
if (listener instanceof CustomExecutorListener) {
final CustomExecutorListener cel = (CustomExecutorListener) listener;
cel.Executor.execute(new Runnable() {
@Override
public void run() {
invocation.run(cel.Listener);
}
});
} else {
try {
invocation.run(listener);
} catch (Exception e) {
Log.userCodeException(e);
}
}
}
}
/*
* Indexed.
*/
@Override
protected final void onIndexedRead(TObject object, int index) {
}
@Override
protected final void onIndexedWrite(TObject object, final int index) {
if (object.listeners() != null) {
invoke(object, new Invocation() {
@Override
void run(Object listener) {
((IndexListener) listener).onSet(index);
}
});
}
}
/*
* TKeyed.
*/
@Override
protected final void onKeyedRead(TObject object, Object key) {
// TODO
}
@SuppressWarnings("unchecked")
@Override
protected final void onKeyedPut(TObject object, final Object key, Object value) {
if (object.listeners() != null) {
invoke(object, new Invocation() {
@Override
void run(Object listener) {
((KeyListener) listener).onPut(key);
}
});
}
}
@SuppressWarnings("unchecked")
@Override
protected final void onKeyedRemoval(TObject object, final Object key) {
if (object.listeners() != null) {
invoke(object, new Invocation() {
@Override
void run(Object listener) {
((KeyListener) listener).onRemove(key);
}
});
}
}
@Override
protected final void onKeyedClear(TObject object) {
if (object.listeners() != null) {
invoke(object, new Invocation() {
@Override
void run(Object listener) {
((KeyListener) listener).onClear();
}
});
}
}
/*
* Resources.
*/
@Override
protected final void onResourcePut(final TObject object) {
if (object.listeners() != null) {
invoke(object, new Invocation() {
@Override
void run(Object listener) {
((ResourceListener) listener).onSet();
}
});
}
}
@Override
protected final void onResourceDelete(final TObject object) {
if (object.listeners() != null) {
invoke(object, new Invocation() {
@Override
void run(Object listener) {
((ResourceListener) listener).onDelete();
}
});
}
}
//
private final class AddListener extends Message {
TObject _object;
Object _listener;
AddListener(TObject object, Object listener) {
_object = object;
_listener = listener;
}
@Override
void run(Actor actor) {
if (_object.listeners() == null)
_object.listeners(new PlatformSet());
_object.listeners().add(_listener);
}
}
private final class RemoveListener extends Message {
TObject _object;
Object _listener;
RemoveListener(TObject object, Object listener) {
_object = object;
_listener = listener;
}
@Override
void run(Actor actor) {
if (_object.listeners() != null) {
_object.listeners().remove(_listener);
if (_object.listeners().isEmpty())
_object.listeners(null);
}
}
}
private final class RaiseIndexListener extends Message {
TObject _object;
int _index;
RaiseIndexListener(TObject object, int index) {
_object = object;
_index = index;
}
@Override
void run(Actor actor) {
if (_object instanceof TIndexed) {
if (_object.listeners() != null) {
invoke(_object, new Invocation() {
@Override
void run(Object listener) {
if (listener instanceof IndexListener)
((IndexListener) listener).onSet(_index);
}
});
}
}
}
}
private final class RaisePropertyListener extends Message {
TObject _object;
String _propertyName;
RaisePropertyListener(TObject object, String propertyName) {
_object = object;
_propertyName = propertyName;
}
@Override
void run(Actor actor) {
if (_object instanceof TIndexed) {
if (_object.listeners() != null) {
invoke(_object, new Invocation() {
@Override
void run(Object listener) {
if (listener instanceof PropertyListener)
((PropertyListener) listener).onPropertyChanged(_propertyName);
}
});
}
}
}
}
}