I need help to understand the correct way of using Clone() method in order tor clone interfaces.
What the Clone() method should do in his implementation?
How should be obtained or released a cloned interface?
Thanks.
Alfredo
Interfaces: correct way of using Clone() method
- AlfredOne
- Beta Tester
- Posts: 135
- Joined: Wed Dec 22, 2010 11:45 pm
- Location: Terlizzi (BA) , Italy
- Contact:
Interfaces: correct way of using Clone() method
Amiga500 Kickstart1.3
AmigaONE XE G4 833MHz - 2GB RAM - Radeon9200 256MB
AmigaONE X1000 - 2GB RAM
AmigaONE XE G4 833MHz - 2GB RAM - Radeon9200 256MB
AmigaONE X1000 - 2GB RAM
- Radeon R9-280X 3GB
- Radeon HIS4670 1GB DDR3
- Radeon RX550
Re: Interfaces: correct way of using Clone() method
Hi,
Clone() is expected to build a new interface (by means of MakeInterface()), flag it as IFLF_CLONED, initialize its private data and return a pointer to it.
In this case, Expunge() shall also be implemented in order to undo what was done in Clone() (free memory, etc...).
Such interfaces are also supposed to perform garbage collecting in Release() when their usage counter reach 0 (i.e. call DeleteInterface() on themselves if the IFLF_CLONED flag is set).
Clone() is automatically used by the system (namely GetInterface()) for interfaces declared as IFLF_PRIVATE. In this case a clone of the private interface is returned on each call. I suppose you could also use it as a real copy constructor on an existing interface like it is suggested in the SDK...
Note that this usage only makes sense for libraries that export interfaces in an object oriented fashion (that is, hardly any but application.library dockies and expansion.library pci devices). Most libraries only export a single shared interface which is just a function table (but if you ask the question you probably already know that...).
Clone() is expected to build a new interface (by means of MakeInterface()), flag it as IFLF_CLONED, initialize its private data and return a pointer to it.
In this case, Expunge() shall also be implemented in order to undo what was done in Clone() (free memory, etc...).
Such interfaces are also supposed to perform garbage collecting in Release() when their usage counter reach 0 (i.e. call DeleteInterface() on themselves if the IFLF_CLONED flag is set).
Clone() is automatically used by the system (namely GetInterface()) for interfaces declared as IFLF_PRIVATE. In this case a clone of the private interface is returned on each call. I suppose you could also use it as a real copy constructor on an existing interface like it is suggested in the SDK...
Note that this usage only makes sense for libraries that export interfaces in an object oriented fashion (that is, hardly any but application.library dockies and expansion.library pci devices). Most libraries only export a single shared interface which is just a function table (but if you ask the question you probably already know that...).
- Hans-Joerg Frieden
- AmigaOS Core Developer
- Posts: 223
- Joined: Wed Dec 08, 2010 3:52 pm
Re: Interfaces: correct way of using Clone() method
What centaurz said. Also, here's an example Clone() implementation I use in Gallium:AlfredOne wrote:What the Clone() method should do in his implementation?
How should be obtained or released a cloned interface?
Code: Select all
struct Interface * _EGL_Clone(struct EGLIFace *Self)
{
uint32 size = Self->Data.PositiveSize + Self->Data.NegativeSize;
uint8 *newInterface = IExec->AllocVecTags(size, TAG_DONE);
struct Interface *retValue = NULL;
if (newInterface)
{
retValue = (struct Interface *)(newInterface + Self->Data.NegativeSize);
uint8 *base = ((uint8 *)Self) - Self->Data.NegativeSize;
IExec->CopyMem(base, newInterface, size);
retValue -> Data.Flags = IFLF_CLONED;
retValue -> Data.RefCount = 0;
((eglinstance_t *)newInterface)->ITLS = (struct TLSIFace *)IExec->GetInterfaceTags(TLSBase, "main", 1, NULL);
((eglinstance_t *)newInterface)->eglGlobalData = NULL;
((eglinstance_t *)newInterface)->importTable = NULL;
((eglinstance_t *)newInterface)->patchStart = NULL;
((eglinstance_t *)newInterface)->patchEnd = NULL;
((eglinstance_t *)newInterface)->FuncData = NULL;
((eglinstance_t *)newInterface)->resolveFunc = NULL;
((eglinstance_t *)newInterface)->unloadFunc = NULL;
((eglinstance_t *)newInterface)->_eglModules = NULL;
((eglinstance_t *)newInterface)->eglModuleMutex = IExec->AllocSysObjectTags(ASOT_MUTEX,
ASOMUTEX_Recursive, TRUE,
TAG_DONE);
}
return retValue;
}
Not necessarily. In this case, I made the interface private and cloned it because it requires a per-task/thread-local data. In this case, OpenGL and EGL require task-specific data (like the current error and such) so the library keeps track of that through a private interface. There is nothing "object oriented" about this, in fact, since egl functions are supposed to be called like "eglXXXX()" without an interface, the caller will not even notice that there is anything like that going oncentaurz wrote:Note that this usage only makes sense for libraries that export interfaces in an object oriented fashion (that is, hardly any but application.library dockies and expansion.library pci devices). Most libraries only export a single shared interface which is just a function table (but if you ask the question you probably already know that...).
NOTICE: If you want to contact me, use E-Mail. I cannot be contacted via the forum/private messages anymore