From: atif@infotec.ch
Subject: Minimizing Lock and Unlock Calls in Protected Mode
Keywords: GlobalLock,GlobalUnlock,Memory,Protected Mode,GlobalFree,Allocation
Organization: Infotec S.A.
Distribution: comp
Date: Wed, 7 Oct 1992 16:44:40 GMT

I was browsing through the "programming tips" provided with 
Microsoft's SDK for Windows 3.1 and found the following article:

----------------------------------------------------------------
Minimizing Lock and Unlock Calls in Protected Mode

Summary

In protected mode (win /2, win /3), the selector of a GlobalAlloc
movable memory block does not change even though Windows may move
the block in physical (standard mode, enhanced mode) or linear
(enhanced mode) memory.

Applications that restrict themselves to running only in protected
mode can take advantage of this behavior to minimize the number of
GlobalLock and GlobalUnlock calls.

More Information

To allocate a global memory object:


  HANDLE hMem;
  LPSTR lpstr;

  if ((hMem = GlobalAlloc(GMEM_MOVEABLE,cb)) != NULL)
     if ((lpstr = GlobalLock(hMem)) != (LPSTR) NULL)
        {
        //... use the memory
        }


To free the global object allocated above:


  if (GlobalUnlock(hMem) != (HANDLE) NULL)
     GlobalFree(hMem);


There is no memory consumption penalty for leaving movable global
objects locked.

This technique is not appropriate for an application that runs in
real mode (win /r) because there is a limited amount of memory
(less than 640K) available in real mode, and GlobalLock locks the
global object in memory. Locked objects in real mode make it harder
to create large free blocks, since Windows cannot move locked objects
around (compaction). Hence, an application that must run in real mode
should keep an object locked only while the object is actually being
used. 
----------------------------------------------------------------

I've tried using the proposed method, but found that the GlobalFree
function never gets executed because GlobalUnlock return FALSE.
However, if I decided to replace...

  if (GlobalUnlock(hMem) != (HANDLE) NULL)
     GlobalFree(hMem);

simply with a call to GlobalFree, as in...

  GlobalFree(hMem);
  
then the memory object gets freed anyway without using the 'if'
condition and a call to GloabalUnlock. Although this works, I'd
like to understand why exactly why the article choses to call
GlobalUnlock before the the GlobalFree function. How is it meant
to help? If anybody has a greater in-depth understanding of the
matter, then I'd very much appreciate if they could shed some
light on this problem.

Before I leave you to ponder, I'd like to also state my own
reasoning behind why the article's method doesn't work. If I am
correct, please tell me so (this will also save you some time and
writing).

The article states that the lock counter is not influenced by
GlobalLock and GlobalUnlock functions under protected mode. Since
GlobalLock does not increase the usage counter of the memory object
the first time, it does not decrease it either when GlobalUnlock
is called. The return value of GlobalUnlock is only TRUE when
the lock counter settles down to zero (indicating that the object
is once again moveable in memory). However, it chooses to return
FALSE because the lock counter never changes in protected mode
(except, of course, when the memory object is also discardable;
but then this is not the case in the article).

Thanks in advance.

---------------------------------------------------------------
 ATIF AZIZ         |  Infotec S.A., Geneva, SWITZERLAND.  
 Software Engineer |  "Imagination is better than knowledge."   
 atif@infotec.ch   |             - Albert Einstien. 
---------------------------------------------------------------
Newsgroups: comp.os.ms-windows.programmer.misc