|
|
|
/*
|
|
|
|
|
|
|
|
Copyright (C) 2000 Stefan Westerfeld
|
|
|
|
stefan@space.twc.de
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Library General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 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
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Library General Public License
|
|
|
|
along with this library; see the file COPYING.LIB. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02110-1301, USA.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OBJECT_H
|
|
|
|
#define OBJECT_H
|
|
|
|
|
|
|
|
#include "buffer.h"
|
|
|
|
#include "connection.h"
|
|
|
|
#include "notification.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <map>
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
#include "arts_export.h"
|
|
|
|
|
|
|
|
/*
|
|
|
|
* BC - Status (2002-03-08): Object_base, Object_skel, Object_stub
|
|
|
|
*
|
|
|
|
* All of them have to be kept binary compatible carefully, due to interaction
|
|
|
|
* with generated code. There are d ptrs in _skel and _stub, NOT TO BE USED
|
|
|
|
* NORMALLY. Normally, do use _internalData instead, as this is much faster
|
|
|
|
* than creating two d objects per MCOP implementation/stub. Handle with care.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
namespace Arts {
|
|
|
|
/* custom dispatching functions */
|
|
|
|
|
|
|
|
typedef void (*DispatchFunction)(void *object, Buffer *request, Buffer *result);
|
|
|
|
typedef void (*OnewayDispatchFunction)(void *object, Buffer *request);
|
|
|
|
typedef void (*DynamicDispatchFunction)(void *object, long methodID, Buffer *request, Buffer *result);
|
|
|
|
|
|
|
|
class ScheduleNode;
|
|
|
|
class Object_skel;
|
|
|
|
class Object_stub;
|
|
|
|
class FlowSystem;
|
|
|
|
class MethodDef;
|
|
|
|
class ObjectReference;
|
|
|
|
class WeakReferenceBase;
|
|
|
|
class Object;
|
|
|
|
class ObjectManager;
|
|
|
|
class DynamicSkeletonData;
|
|
|
|
class DynamicSkeletonBase;
|
|
|
|
|
|
|
|
class ARTS_EXPORT Object_base : public NotificationClient {
|
|
|
|
private:
|
|
|
|
friend class DynamicRequest;
|
|
|
|
friend class ObjectManager;
|
|
|
|
bool _deleteOk; // ensure that "delete" is not called manually
|
|
|
|
|
|
|
|
protected:
|
|
|
|
/**
|
|
|
|
* ObjectInternalData tqcontains private data structures for
|
|
|
|
* - Object_base
|
|
|
|
* - Object_stub
|
|
|
|
* - Object_skel
|
|
|
|
*
|
|
|
|
* This is an optimization over adding each of them private data pointers,
|
|
|
|
* which would lead to some more bloat.
|
|
|
|
*/
|
|
|
|
class ObjectInternalData *_internalData;
|
|
|
|
|
|
|
|
struct ObjectStreamInfo;
|
|
|
|
|
|
|
|
Object_base();
|
|
|
|
virtual ~Object_base();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* internal management for streams
|
|
|
|
*/
|
|
|
|
ScheduleNode *_scheduleNode;
|
|
|
|
std::list<ObjectStreamInfo *> _streamList;
|
|
|
|
|
|
|
|
virtual Object_skel *_skel();
|
|
|
|
virtual Object_stub *_stub();
|
|
|
|
|
|
|
|
enum ObjectLocation { objectIsLocal, objectIsRemote };
|
|
|
|
virtual ObjectLocation _location() const = 0;
|
|
|
|
|
|
|
|
long _objectID;
|
|
|
|
Connection *_connection;
|
|
|
|
std::string _internalObjectID; // two objects are "_isEqual" when these match
|
|
|
|
long _nextNotifyID;
|
|
|
|
long _refCnt; // reference count
|
|
|
|
static long _staticObjectCount;
|
|
|
|
|
|
|
|
void _destroy(); // use this instead of delete (takes care of
|
|
|
|
// properly removing flow system node)
|
|
|
|
public:
|
|
|
|
static unsigned long _IID; // interface ID
|
|
|
|
/**
|
|
|
|
* custom messaging: these can be used to send a custom data to other
|
|
|
|
* objects. Warning: these are *not* usable for local objects. You may
|
|
|
|
* only use these functions if you know that you are talking to a remote
|
|
|
|
* object. Use _allocCustomMessage to allocate a message. Put the data
|
|
|
|
* you want to send in the Buffer. After that, call _sendCustomMessage.
|
|
|
|
* Don't free the buffer - this will happen automatically.
|
|
|
|
*/
|
|
|
|
|
|
|
|
virtual Buffer *_allocCustomMessage(long handlerID);
|
|
|
|
virtual void _sendCustomMessage(Buffer *data);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* generic capabilities, which allow find out what you can do with an
|
|
|
|
* object even if you don't know it's interface
|
|
|
|
*/
|
|
|
|
virtual long _lookupMethod(const Arts::MethodDef &) = 0;
|
|
|
|
virtual std::string _interfaceName() = 0;
|
|
|
|
virtual class InterfaceDef _queryInterface(const std::string& name) = 0;
|
|
|
|
virtual class TypeDef _queryType(const std::string& name) = 0;
|
|
|
|
virtual class EnumDef _queryEnum(const std::string& name) = 0;
|
|
|
|
virtual std::string _toString() = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* stuff for streaming (put in a seperate interface?)
|
|
|
|
*/
|
|
|
|
virtual void calculateBlock(unsigned long cycles);
|
|
|
|
ScheduleNode *_node();
|
|
|
|
virtual FlowSystem _flowSystem() = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* reference counting
|
|
|
|
*/
|
|
|
|
virtual void _release() = 0;
|
|
|
|
virtual void _copyRemote() = 0;
|
|
|
|
virtual void _useRemote() = 0;
|
|
|
|
virtual void _releaseRemote() = 0;
|
|
|
|
|
|
|
|
// BC issue: added _cancelCopyRemote here to avoid virtual function
|
|
|
|
void _cancelCopyRemote();
|
|
|
|
|
|
|
|
void _addWeakReference(WeakReferenceBase *reference);
|
|
|
|
void _removeWeakReference(WeakReferenceBase *reference);
|
|
|
|
|
|
|
|
inline Object_base *_copy() {
|
|
|
|
assert(_refCnt > 0);
|
|
|
|
_refCnt++;
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Default I/O info
|
|
|
|
virtual std::vector<std::string> _defaultPortsIn() const;
|
|
|
|
virtual std::vector<std::string> _defaultPortsOut() const;
|
|
|
|
|
|
|
|
// cast operation
|
|
|
|
virtual void *_cast(unsigned long iid);
|
|
|
|
void *_cast(const std::string& interface);
|
|
|
|
|
|
|
|
// Run-time type compatibility check
|
|
|
|
virtual bool _isCompatibleWith(const std::string& interfacename) = 0;
|
|
|
|
|
|
|
|
// Aggregation
|
|
|
|
virtual std::string _addChild(Arts::Object child, const std::string& name) = 0;
|
|
|
|
virtual bool _removeChild(const std::string& name) = 0;
|
|
|
|
virtual Arts::Object _getChild(const std::string& name) = 0;
|
|
|
|
virtual std::vector<std::string> * _queryChildren() = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* when this is true, a fatal communication error has occurred (of course
|
|
|
|
* only possible for remote objects) - maybe your returncode is invalid,
|
|
|
|
* maybe your last invocation didn't succeed...
|
|
|
|
*/
|
|
|
|
virtual bool _error();
|
|
|
|
|
|
|
|
inline static long _objectCount() { return _staticObjectCount; }
|
|
|
|
inline long _mkNotifyID() { return _nextNotifyID++; }
|
|
|
|
|
|
|
|
// object creation
|
|
|
|
static Object_base *_create(const std::string& subClass = "Object");
|
|
|
|
|
|
|
|
// comparison
|
|
|
|
bool _isEqual(Object_base *object) const;
|
|
|
|
|
|
|
|
// static converter (from reference)
|
|
|
|
static Object_base *_fromString(const std::string& objectref);
|
|
|
|
static Object_base *_fromReference(class ObjectReference ref, bool needcopy);
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Dispatching
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Buffer;
|
|
|
|
class MethodDef;
|
|
|
|
|
|
|
|
|
|
|
|
class Object_skel_private;
|
|
|
|
class AnyConstRef;
|
|
|
|
class AttributeDef;
|
|
|
|
|
|
|
|
class ARTS_EXPORT Object_skel : virtual public Object_base {
|
|
|
|
private:
|
|
|
|
friend class Object_base;
|
|
|
|
friend class DynamicSkeletonData;
|
|
|
|
friend class DynamicSkeletonBase;
|
|
|
|
|
|
|
|
Object_skel_private *_d_skel;// do not use until there is a very big problem
|
|
|
|
|
|
|
|
// reference counting - remote object watching
|
|
|
|
|
|
|
|
long _remoteSendCount; // don't kill objects just sent to other server
|
|
|
|
bool _remoteSendUpdated; // timeout if they don't want the object
|
|
|
|
std::list<class Connection *> _remoteUsers; // who is using it?
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void _addMethod(DispatchFunction disp, void *object, const MethodDef& md);
|
|
|
|
void _addMethod(OnewayDispatchFunction disp, void *object,
|
|
|
|
const MethodDef& md);
|
|
|
|
void _addMethod(DynamicDispatchFunction disp, void *object,
|
|
|
|
const MethodDef& md);
|
|
|
|
void _initStream(const std::string& name, void *ptr, long flags);
|
|
|
|
|
|
|
|
/** stuff relative to attribute notifications **/
|
|
|
|
bool _initAttribute(const Arts::AttributeDef& attribute);
|
|
|
|
static bool _QueryInitStreamFunc(Object_skel *skel,const std::string& name);
|
|
|
|
bool _generateSlots(const std::string& name, const std::string& interface);
|
|
|
|
|
|
|
|
/** for DynamicSkeleton: **/
|
|
|
|
const MethodDef& _dsGetMethodDef(long methodID);
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void _defaultNotify(const Notification& notification);
|
|
|
|
void notify(const Notification& notification);
|
|
|
|
void _emit_changed(const char *stream, const AnyConstRef& value);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* custom messaging: this is used to install a custom data handler that
|
|
|
|
* can be used to receive non-standard messages
|
|
|
|
*/
|
|
|
|
long _addCustomMessageHandler(OnewayDispatchFunction handler, void *object);
|
|
|
|
|
|
|
|
Object_skel *_skel();
|
|
|
|
ObjectLocation _location() const;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Object_skel();
|
|
|
|
virtual ~Object_skel();
|
|
|
|
|
|
|
|
// reference counting connection drop
|
|
|
|
void _disconnectRemote(class Connection *connection);
|
|
|
|
void _referenceClean();
|
|
|
|
|
|
|
|
// synchronous & asynchronous dispatching
|
|
|
|
void _dispatch(Buffer *request, Buffer *result,long methodID);
|
|
|
|
void _dispatch(Buffer *request, long methodID);
|
|
|
|
long _lookupMethod(const MethodDef &);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* standard interface for every object skeleton
|
|
|
|
*/
|
|
|
|
static std::string _interfaceNameSkel();
|
|
|
|
virtual void _buildMethodTable();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* reference counting
|
|
|
|
*/
|
|
|
|
virtual void _release();
|
|
|
|
virtual void _copyRemote();
|
|
|
|
virtual void _useRemote();
|
|
|
|
virtual void _releaseRemote();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* streaming
|
|
|
|
*/
|
|
|
|
FlowSystem _flowSystem();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to inspect the (remote) object interface
|
|
|
|
*/
|
|
|
|
virtual std::string _interfaceName();
|
|
|
|
InterfaceDef _queryInterface(const std::string& name);
|
|
|
|
TypeDef _queryType(const std::string& name);
|
|
|
|
EnumDef _queryEnum(const std::string& name);
|
|
|
|
virtual std::string _toString();
|
|
|
|
|
|
|
|
// Run-time type compatibility check
|
|
|
|
bool _isCompatibleWith(const std::string& interfacename);
|
|
|
|
|
|
|
|
// Aggregation
|
|
|
|
std::string _addChild(Arts::Object child, const std::string& name);
|
|
|
|
bool _removeChild(const std::string& name);
|
|
|
|
Arts::Object _getChild(const std::string& name);
|
|
|
|
std::vector<std::string> * _queryChildren();
|
|
|
|
};
|
|
|
|
|
|
|
|
class Object_stub_private;
|
|
|
|
|
|
|
|
class ARTS_EXPORT Object_stub : virtual public Object_base {
|
|
|
|
private:
|
|
|
|
friend class Object_base;
|
|
|
|
|
|
|
|
Object_stub_private *_d_stub;// do not use until there is a very big problem
|
|
|
|
|
|
|
|
protected:
|
|
|
|
long _lookupCacheRandom;
|
|
|
|
|
|
|
|
Object_stub();
|
|
|
|
Object_stub(Connection *connection, long objectID);
|
|
|
|
virtual ~Object_stub();
|
|
|
|
|
|
|
|
virtual Object_stub *_stub();
|
|
|
|
ObjectLocation _location() const;
|
|
|
|
|
|
|
|
enum { _lookupMethodCacheSize = 337 };
|
|
|
|
static struct methodCacheEntry {
|
|
|
|
methodCacheEntry() : obj(NULL),method(NULL),ID(0) {} ;
|
|
|
|
Object_stub *obj;
|
|
|
|
const char *method;
|
|
|
|
long ID;
|
|
|
|
} *_lookupMethodCache;
|
|
|
|
|
|
|
|
long _lookupMethodFast(const char *method);
|
|
|
|
long _lookupMethod(const MethodDef &);
|
|
|
|
|
|
|
|
public:
|
|
|
|
/*
|
|
|
|
* custom messaging
|
|
|
|
*/
|
|
|
|
|
|
|
|
Buffer *_allocCustomMessage(long handlerID);
|
|
|
|
void _sendCustomMessage(Buffer *data);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* to inspect the (remote) object interface
|
|
|
|
*/
|
|
|
|
std::string _interfaceName();
|
|
|
|
InterfaceDef _queryInterface(const std::string& name);
|
|
|
|
TypeDef _queryType(const std::string& name);
|
|
|
|
EnumDef _queryEnum(const std::string& name);
|
|
|
|
std::string _toString();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* streaming
|
|
|
|
*/
|
|
|
|
FlowSystem _flowSystem();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* reference counting
|
|
|
|
*/
|
|
|
|
virtual void _release();
|
|
|
|
virtual void _copyRemote();
|
|
|
|
virtual void _useRemote();
|
|
|
|
virtual void _releaseRemote();
|
|
|
|
|
|
|
|
// Run-time type compatibility check
|
|
|
|
bool _isCompatibleWith(const std::string& interfacename);
|
|
|
|
|
|
|
|
// Aggregation
|
|
|
|
std::string _addChild(Arts::Object child, const std::string& name);
|
|
|
|
bool _removeChild(const std::string& name);
|
|
|
|
Arts::Object _getChild(const std::string& name);
|
|
|
|
std::vector<std::string> * _queryChildren();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* communication error? this is true when your connection to the remote
|
|
|
|
* object is lost (e.g. when the remote server crashed) - your return
|
|
|
|
* values are then undefined, so check this before relying too much
|
|
|
|
* on some invocation
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool _error();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* global cleanup
|
|
|
|
*/
|
|
|
|
static void _cleanupMethodCache();
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|
|
|
|
#endif
|