0b77c89fa7
Any Collection can now be streamed. You can send Collections.emptyMap() back to a client, for example. (It will unstream as a HashMap on the other side.) This actually streams everything to the exact same bytes as before. Using specific classes is discouraged: ArrayList, StreamableArrayList... If a Streamer is created for a class that has a field of that type, a warning will be generated, urging you to change the field definition to the interface. Also: that setup is now deferred until needed, because in clyde/projectx there are a number of Streamable classes that have fields of specific classes, like ArrayIntSet for example, but don't use standard streaming to transmit them. In that case it's totally cool for them to have a more specific type. Since that setup is potentially deferred, one change may be observed for a class that uses custom readObject() and writeObject() methods but still calls defaultReadObject(). The field marshallers will now be configured a little later in the game than before. But, we're actually saving a bit of memory by not setting up those marshallers for streamable classes that never use them. Woo. Please let me know if this causes any space shuttle explosions or spikes the punch at your quinceanera. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@6348 542714f4-19e9-0310-aa3c-eee0fc999fb1
193 lines
5.4 KiB
Java
193 lines
5.4 KiB
Java
//
|
|
// $Id$
|
|
//
|
|
// Narya library - tools for developing networked games
|
|
// Copyright (C) 2002-2010 Three Rings Design, Inc., All Rights Reserved
|
|
// http://code.google.com/p/narya/
|
|
//
|
|
// This library is free software; you can redistribute it and/or modify it
|
|
// under the terms of the GNU Lesser General Public License as published
|
|
// by the Free Software Foundation; either version 2.1 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
package com.threerings.presents.dobj;
|
|
|
|
import java.util.List;
|
|
|
|
import com.google.common.collect.Lists;
|
|
|
|
import com.threerings.presents.net.Transport;
|
|
|
|
/**
|
|
* Used to manage and submit groups of events on a collection of distributed objects in a single
|
|
* transaction.
|
|
*
|
|
* @see DObject#startTransaction
|
|
*/
|
|
public class CompoundEvent extends DEvent
|
|
{
|
|
/**
|
|
* Constructs a blank compound event in preparation for unserialization.
|
|
*/
|
|
public CompoundEvent ()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* Constructs a compound event and prepares it for operation.
|
|
*/
|
|
public CompoundEvent (DObject target, DObjectManager omgr)
|
|
{
|
|
super(target.getOid());
|
|
|
|
// sanity check
|
|
if (omgr == null) {
|
|
String errmsg = "Must receive non-null object manager reference";
|
|
throw new IllegalArgumentException(errmsg);
|
|
}
|
|
|
|
_omgr = omgr;
|
|
_target = target;
|
|
_events = Lists.newArrayList();
|
|
}
|
|
|
|
/**
|
|
* Posts an event to this transaction. The event will be delivered as part of the entire
|
|
* transaction if it is committed or discarded if the transaction is cancelled.
|
|
*/
|
|
public void postEvent (DEvent event)
|
|
{
|
|
_events.add(event);
|
|
}
|
|
|
|
/**
|
|
* Returns the list of events contained within this compound event.
|
|
*
|
|
* Don't mess with it.
|
|
*/
|
|
public List<DEvent> getEvents ()
|
|
{
|
|
return _events;
|
|
}
|
|
|
|
/**
|
|
* Commits this transaction by posting this event to the distributed object event queue. All
|
|
* participating dobjects will have their transaction references cleared and will go back to
|
|
* normal operation.
|
|
*/
|
|
public void commit ()
|
|
{
|
|
// first clear our target
|
|
clearTarget();
|
|
|
|
// then post this event onto the queue (but only if we actually
|
|
// accumulated some events)
|
|
int size = _events.size();
|
|
switch (size) {
|
|
case 0: // nothing doing
|
|
break;
|
|
case 1: // no point in being compound
|
|
_omgr.postEvent(_events.get(0));
|
|
break;
|
|
default: // now we're talking
|
|
_transport = _events.get(0).getTransport();
|
|
for (int ii = 1; ii < size; ii++) {
|
|
_transport = _events.get(ii).getTransport().combine(_transport);
|
|
}
|
|
_omgr.postEvent(this);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Cancels this transaction. All events posted to this transaction will be discarded.
|
|
*/
|
|
public void cancel ()
|
|
{
|
|
// clear our target
|
|
clearTarget();
|
|
// clear our event queue in case someone holds onto us
|
|
_events.clear();
|
|
}
|
|
|
|
@Override
|
|
public void setSourceOid (int sourceOid)
|
|
{
|
|
super.setSourceOid(sourceOid);
|
|
|
|
// we need to propagate our source oid to our constituent events
|
|
int ecount = _events.size();
|
|
for (int ii = 0; ii < ecount; ii++) {
|
|
_events.get(ii).setSourceOid(sourceOid);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setTargetOid (int targetOid)
|
|
{
|
|
super.setTargetOid(targetOid);
|
|
|
|
// we need to propagate our target oid to our constituent events
|
|
int ecount = _events.size();
|
|
for (int ii = 0; ii < ecount; ii++) {
|
|
_events.get(ii).setTargetOid(targetOid);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void setTransport (Transport transport)
|
|
{
|
|
super.setTransport(transport);
|
|
for (int ii = 0, nn = _events.size(); ii < nn; ii++) {
|
|
_events.get(ii).setTransport(transport);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean applyToObject (DObject target)
|
|
throws ObjectAccessException
|
|
{
|
|
// nothing to apply here
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Calls out to our target object, clearing its transaction reference.
|
|
*/
|
|
protected void clearTarget ()
|
|
{
|
|
if (_target != null) {
|
|
_target.clearTransaction();
|
|
_target = null;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void toString (StringBuilder buf)
|
|
{
|
|
buf.append("COMPOUND:");
|
|
super.toString(buf);
|
|
for (int ii = 0, nn = _events.size(); ii < nn; ii++) {
|
|
buf.append(", ").append(_events.get(ii));
|
|
}
|
|
}
|
|
|
|
/** The object manager that we'll post ourselves to when we're committed. */
|
|
protected transient DObjectManager _omgr;
|
|
|
|
/** The object for which we're managing a transaction. */
|
|
protected transient DObject _target;
|
|
|
|
/** A list of the events associated with this compound event. */
|
|
protected List<DEvent> _events;
|
|
}
|