Copyright (c) Hyperion Entertainment and contributors.

Difference between revisions of "Exec Named Memory"

From AmigaOS Documentation Wiki
Jump to navigation Jump to search
(Added the Function Reference section.)
 
(7 intermediate revisions by one other user not shown)
Line 1: Line 1:
= Introduction =
+
== Introduction ==
   
In a multi-tasking environment, it is often desirable to be able to share resources between two more more different Tasks or Processes. This can be done by passing memory pointers, but this is difficult since there is no defined "protocol" for this.
+
In a multi-tasking environment, it is often desirable to be able to share resources between two more more different [[Exec Tasks|Tasks]] or Processes. This can be done by passing memory pointers, but this is difficult since there is no defined "protocol" for this.
   
Exec V51 introduces a new concept called named memory. Instead of having to pass a pointer around, you decide on a name for your memory and have others (or yourself) access this memory by it's name. In addition, named memory can be organized into different namespaces. This allows for the same name to exist in different namespaces. All names in the same namespace must be unique.
+
Exec V51 introduces a new concept called ''named memory''. Instead of having to pass a pointer around, you decide on a name for your memory and have others (or yourself) access this memory by its name. In addition, named memory can be organized into different namespaces. This allows for the same name to exist in different namespaces. All names in the same namespace must be unique.
   
  +
== Creating Named Memory ==
= The "resident" Namespace =
 
   
  +
Named memory is first created using the AllocNamedMemory() function:
One namespace is predefined with a special functionality: ''resident''. This namespace and it's objects will be restored after reboot through ColdStart().
 
 
To ensure data integrity, it is possible to have the memory block automatically checksummed. The checksum is validated after reboot. If checksumming is enabled and the stored checksum and newly computed checksums match, the block is available to subsequent FindNamedMemory() calls. Otherwise, the block is discarded. If no checksumming is enabled for the block, the application must ensure data integrity.
 
 
= Creating Named Memory =
 
 
Named memory is first created using the AllocNamedMemory() function.
 
   
 
<syntaxhighlight>
 
<syntaxhighlight>
Line 34: Line 28:
 
In this example, the global namespace is being used and the name of the memory is ''MySharedData''.
 
In this example, the global namespace is being used and the name of the memory is ''MySharedData''.
   
= Sharing Named Memory =
+
== Sharing Named Memory ==
   
  +
Named memory is meant to be shared between two or more Tasks or Processes. As such, a strict protocol must be obeyed to ensure the shared data remains consistent.
= Freeing Named Memory =
 
   
Named memory should be freed when no longer in use. Any Task or Process may attempt to free named memory although it is advisable to have the same entity free it that created it.
+
In order to read from or write to the named memory, a Task or Process must first lock it. Here is an example of an exclusive lock which will block the caller. If some other entity has a lock on the data it will block the caller until that lock is released.
  +
  +
<syntaxhighlight>
  +
struct MySharedData *data = IExec->LockNamedMemory(NULL, "MySharedData");
  +
  +
if (data == NULL)
  +
IDOS->Printf("Shared data does not exist\n");
  +
else
  +
{
  +
data->value = 4;
  +
data->flag = TRUE;
  +
}
  +
</syntaxhighlight>
  +
  +
Named memory may disappear at any time so there is no guarantee that a call to LockNamedMemory() will succeed. Keep this in mind when designing your applications!
  +
  +
Sometimes it is not appropriate to block the caller if the shared data is not available. Here is an example of an exclusive lock which does not block the caller.
  +
  +
<syntaxhighlight>
  +
struct MySharedData *data = IExec->AttemptNamedMemory(NULL, "MySharedData");
  +
  +
if (data == NULL)
  +
IDOS->Printf("Shared data is locked; don't access it\n");
  +
else
  +
IDOS->Printf("value is %lu\n", data->value);
  +
</syntaxhighlight>
  +
  +
In either case, when a lock succeeds the caller (and only the caller) must unlock it when finished. This ensures the next Task or Process can access the data. Be careful to call UnlockNamedMemory() on the same context as you called LockNamedMemory() or AttemptNamedMemory().
  +
  +
<syntaxhighlight>
  +
IExec->UnlockNamedMemory(NULL, "MySharedData");
  +
</syntaxhighlight>
  +
  +
== The "resident" Namespace ==
  +
  +
One namespace is predefined with a special functionality: ''resident''. This namespace and its objects will be restored after reboot through ColdStart().
  +
  +
To ensure data integrity, it is possible to have the memory block automatically checksummed. The checksum is validated after reboot. If checksumming is enabled and the stored checksum and newly computed checksums match, the block is available to subsequent FindNamedMemory() calls. Otherwise, the block is discarded. If no checksumming is enabled for the block, the application must ensure data integrity.
  +
  +
The checksum may also be recalculated explicitly by using the UpdateNamedMemory() function. This may be needed in cases where the data initially failed the checksum.
  +
  +
The FindNamedMemory() function is used to access resident blocks of memory if you already know the name of the block.
  +
  +
The ScanNamedMemory() function is used to discover what named memory blocks are available. ScanNamedMemory() may also be used to scan just the namespaces.
  +
  +
<syntaxhighlight>
  +
uint32 myMemScanHook(struct Hook *hook, APTR userdata, struct SNMMessage *scanMsg)
  +
{
  +
IDOS->Printf("Object %s in namespace %s at address %p\n",
  +
scanMsg->Name, scanMsg->Namespace, scanMsg->Memory);
  +
  +
return 0;
  +
}
  +
  +
struct Hook *scanHook = IExec->AllocSysObjectTags(ASOT_HOOK,
  +
ASOHOOK_Entry, myMemScanHook,
  +
TAG_END);
  +
  +
uint32 result = IExec->ScanNamedMemory(scanHook, 0, NULL);
  +
</syntaxhighlight>
  +
  +
== Freeing Named Memory ==
  +
  +
Named memory should be freed when no longer in use. Any Task or Process may attempt to free named memory but it is advisable to follow some kind of protocol regardless.
   
 
<syntaxhighlight>
 
<syntaxhighlight>
Line 49: Line 106:
 
The boolean return value needs to be checked to verify whether the memory is now free or not. It is possible another Task or Process has a lock on the named memory at the same time it is being freed. This is why it is so important to establish a protocol when using shared memory.
 
The boolean return value needs to be checked to verify whether the memory is now free or not. It is possible another Task or Process has a lock on the named memory at the same time it is being freed. This is why it is so important to establish a protocol when using shared memory.
   
  +
== Function Reference ==
= To be documented =
 
   
  +
The following table gives a brief description of the Exec functions that control named memory. See the SDK/Autodocs for more details about each call.
<syntaxhighlight>
 
  +
UpdateNamedMemory()
 
  +
{| class="wikitable"
AttemptNamedMemory()
 
  +
! Function
FindNamedMemory()
 
  +
! Description
UnlockNamedMemory()
 
  +
|-
ScanNamedMemory()
 
  +
| AllocNamedMemory()
LockNamedMemory()
 
  +
| Allocate a named memory object.
</syntaxhighlight>
 
  +
|-
  +
| AttemptNamedMemory()
  +
| Try to obtain access to named memory.
  +
|-
  +
| FindNamedMemory()
  +
| Search for a named memory object.
  +
|-
  +
| FreeNamedMemory()
  +
| Free a named memory object.
  +
|-
  +
| LockNamedMemory()
  +
| Lock a named memory object for exclusive access.
  +
|-
  +
| ScanNamedMemory()
  +
| Scan through existing named memory objects and/or namespaces.
  +
|-
  +
| UnlockNamedMemory()
  +
| Unlock a named memory object.
  +
|-
  +
| UpdateNamedMemory()
  +
| Recalculate the checksum for a named memory object.
  +
|}

Latest revision as of 13:22, 2 April 2015

Introduction

In a multi-tasking environment, it is often desirable to be able to share resources between two more more different Tasks or Processes. This can be done by passing memory pointers, but this is difficult since there is no defined "protocol" for this.

Exec V51 introduces a new concept called named memory. Instead of having to pass a pointer around, you decide on a name for your memory and have others (or yourself) access this memory by its name. In addition, named memory can be organized into different namespaces. This allows for the same name to exist in different namespaces. All names in the same namespace must be unique.

Creating Named Memory

Named memory is first created using the AllocNamedMemory() function:

struct MySharedData {
  uint32 value;
  BOOL flag;
  uint8 eggs[12];
};
 
uint32 error;
 
APTR mem = IExec->AllocNamedMemoryTags(sizeof(struct MySharedData), NULL, "MySharedData",
  ANMT_Error, &error,
  TAG_END);
 
if (mem == NULL)
  IDOS->Printf("Allocation failed, error code %lu\n", error);

In this example, the global namespace is being used and the name of the memory is MySharedData.

Sharing Named Memory

Named memory is meant to be shared between two or more Tasks or Processes. As such, a strict protocol must be obeyed to ensure the shared data remains consistent.

In order to read from or write to the named memory, a Task or Process must first lock it. Here is an example of an exclusive lock which will block the caller. If some other entity has a lock on the data it will block the caller until that lock is released.

struct MySharedData *data = IExec->LockNamedMemory(NULL, "MySharedData");
 
if (data == NULL)
  IDOS->Printf("Shared data does not exist\n");
else
{
  data->value = 4;
  data->flag  = TRUE;
}

Named memory may disappear at any time so there is no guarantee that a call to LockNamedMemory() will succeed. Keep this in mind when designing your applications!

Sometimes it is not appropriate to block the caller if the shared data is not available. Here is an example of an exclusive lock which does not block the caller.

struct MySharedData *data = IExec->AttemptNamedMemory(NULL, "MySharedData");
 
if (data == NULL)
  IDOS->Printf("Shared data is locked; don't access it\n");
else
  IDOS->Printf("value is %lu\n", data->value);

In either case, when a lock succeeds the caller (and only the caller) must unlock it when finished. This ensures the next Task or Process can access the data. Be careful to call UnlockNamedMemory() on the same context as you called LockNamedMemory() or AttemptNamedMemory().

IExec->UnlockNamedMemory(NULL, "MySharedData");

The "resident" Namespace

One namespace is predefined with a special functionality: resident. This namespace and its objects will be restored after reboot through ColdStart().

To ensure data integrity, it is possible to have the memory block automatically checksummed. The checksum is validated after reboot. If checksumming is enabled and the stored checksum and newly computed checksums match, the block is available to subsequent FindNamedMemory() calls. Otherwise, the block is discarded. If no checksumming is enabled for the block, the application must ensure data integrity.

The checksum may also be recalculated explicitly by using the UpdateNamedMemory() function. This may be needed in cases where the data initially failed the checksum.

The FindNamedMemory() function is used to access resident blocks of memory if you already know the name of the block.

The ScanNamedMemory() function is used to discover what named memory blocks are available. ScanNamedMemory() may also be used to scan just the namespaces.

uint32 myMemScanHook(struct Hook *hook, APTR userdata, struct SNMMessage *scanMsg)
{
  IDOS->Printf("Object %s in namespace %s at address %p\n",
    scanMsg->Name, scanMsg->Namespace, scanMsg->Memory);
 
  return 0;
}
 
struct Hook *scanHook = IExec->AllocSysObjectTags(ASOT_HOOK,
  ASOHOOK_Entry, myMemScanHook,
  TAG_END);
 
uint32 result = IExec->ScanNamedMemory(scanHook, 0, NULL);

Freeing Named Memory

Named memory should be freed when no longer in use. Any Task or Process may attempt to free named memory but it is advisable to follow some kind of protocol regardless.

BOOL success = IExec->FreeNamedMemory(NULL, "MySharedData");
 
if (!success)
  IDOS->Printf("MySharedData cannot be freed\n");

The boolean return value needs to be checked to verify whether the memory is now free or not. It is possible another Task or Process has a lock on the named memory at the same time it is being freed. This is why it is so important to establish a protocol when using shared memory.

Function Reference

The following table gives a brief description of the Exec functions that control named memory. See the SDK/Autodocs for more details about each call.

Function Description
AllocNamedMemory() Allocate a named memory object.
AttemptNamedMemory() Try to obtain access to named memory.
FindNamedMemory() Search for a named memory object.
FreeNamedMemory() Free a named memory object.
LockNamedMemory() Lock a named memory object for exclusive access.
ScanNamedMemory() Scan through existing named memory objects and/or namespaces.
UnlockNamedMemory() Unlock a named memory object.
UpdateNamedMemory() Recalculate the checksum for a named memory object.