You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/mcop/object.h

391 lines
11 KiB

/*
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