[futurebasic] Re: [FB] String Storage Question (long)

Message: < previous - next > : Reply : Subscribe : Cleanse
Home   : July 2004 : Group Archive : Group : All Groups

From: Jay Reeve <jayreeve@...>
Date: Sun, 25 Jul 2004 21:59:55 -0500
On Sunday, July 25, 2004, at 06:54  PM, tedd wrote:

>>> The storing of these pointers should be pretty simple, namely get 
>>> the text from the edit field; determine the length of the text, set 
>>> the length in the respective structure, allocate memory for text, 
>>> place text in the allocation, and store the pointer for that memory 
>>> in the array structure under the record number index. All of that is 
>>> pretty simple.
>> Simple until you have to change an entry. (It's still the same 
>> problem Jonathan noted.) Say you need to enlarge a field. Your 
>> choices are to move all the subsequent data (as you would in my 
>> scenario, anyway), then change every subsequent pointer (workable, 
>> but fairly complex and time consuming), or to abandon the old entry, 
>> adding a new one at the end, thereby fragmenting your data and 
>> requiring periodic garbage collection.
>
> No, I guess that I didn't explain myself well enough OR I don't 
> understand the way a record and pointers work.  (pointers and handles 
> herein are interchangeable)
>
> If an entry is changed, then the only thing that changes is the 
> pointer to the new data. The old data and its pointer is killed.
>
> The data cycle is:
>
> 1. The Edit Fields get its data from the user.
>
> 2. Pointers (or handles) are then created to store the Edit Field data.
>
> 3. The pointer is assigned to it's place in the struct array record.
>
> 4. When the edit fields are shown again, then the struct dumps the 
> contents of the respective pointer into the its edit field.
>
> 5. If the user changes the edit field, then the old data and it's 
> pointer is killed and a new pointer is created containing the new > data.
>
> For example, imagine a tree:
>
>    | record (i)
>    |----- field 1   <-- pointer(handle) nnn ---> data
>    |----- field 2   <-- pointer(handle) zzz ---> data
>    |----- field 3   <-- pointer(handle) xxx---> data
>    |----- field 4   <-- pointer(handle) mmm --> data
>    |
>
> If the user changes edit field 3, then pointer (at memory location 
> xxx) is killed and the new data is taken from edit field 3 and a new 
> pointer (at memory location yyy) is created and assigned to 
> thirdFieldPtr& like so:
>
>    | record (i)
>    |----- field 1   <-- pointer(handle) nnn ---> data
>    |----- field 2   <-- pointer(handle) zzz ---> data
>    |----- field 3   <-- pointer(handle) yyy---> data
>    |----- field 4   <-- pointer(handle) mmm ---> data
>
> Memory location yyy has no bearing on memory locations zzz or mmm -- 
> it (and they) could be anywhere.
>
> Doesn't this work?

In theory, it could. In practice, you're asking incredible things from 
the memory manager. You seem to be talking about putting each and every 
field of every record into its own handle. (okay, in X they're called 
pointers, but it's still the same thing.) My understanding is that each 
call to newHandle (or newPointer) creates a 4,096-byte allocation of 
virtual memory, plus at least a 64-byte header. The memory manager has 
tricks that let unused portions of one "block" overlap with others, but 
I can't even imagine the gyrations it must go through to do that.

I won't tell you not to pursue it. You've figured it out and understand 
  it, so you'll probably be able to make it work. There are certainly 
other programs that create thousands of separate handles, without major 
problems. Basically what you're doing, though, is abdicating all 
responsibility for memory management to the MM. It has to do all the 
shuffling and reshuffling that would otherwise make your programming 
more difficult. It's VERY good at it, so maybe that's not such a bad 
idea. I think I would do it differently. (I'll send you my 20-handle 
version shortly.)

A couple of notes (probably obvious) in case you go ahead:

Whenever a field is blank, you can kill (or not create) its handle, 
setting it to zero and potentially conserving some memory.

You don't really need to maintain the length field with you handle 
list. I would either store the length at the beginning of the handle, 
or keep the handle correctly sized, so you can get the length from FN 
getHandleSize. (Substitute pointer in X as you prefer.)

A good compromise might be one handle for each record, walking the 
offsets to find the 20 fields. That would reduce the handles by up to 
95%.

As you noted, saving and loading would not be too major. I would keep a 
2-dimensional array for the handles to simplify access:
DYNAMIC  DBHandles&(9999,19)
When saving I would XREF it to a one-D array, and set  a bit for each 
handle to be loaded--then write that bitmap before anything else. When 
you read it back in, you just get the bit map first, then load a handle 
for each set bit, and skip one for each zero bit. I could write that fn 
in a few minutes, so  let me know if you want it.

I'm sending my INDEX$ version separately as requested. It is 
operational, but the SAVE has a bug, and I didn't finish the search 
fns. Forgive me, but I think it's very neat, considering how few hours 
I spent on it. The 20-array version will follow shortly.

  e-e
  =J= a  y
   "

--
To unsubscribe, send ANY message to: futurebasic-unsubscribe@...