🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.os.os2.programmer.misc
Article #244

Re: Thread-specific variables?

#244
From: Q
Date: Mon, 04 Oct 1993 12:13
102 lines
5166 bytes
In <28ins7$fvv@tinman.dev.prodigy.com> bob@tinman.dev.prodigy.com (Bob Dedrick) writes:

>In article <28efue$478@access.digex.net> kbennett@access.digex.net (Keith R. Bennett) writes:
>>
>>I have a question about thread programming.  Is there any way to make
>>a given variable specific to an instance of a thread?
>>
>>[...]

>There is no way (that I know of) to make a *global* variable specific to
>a thread.  However, since each thread has its own stack, any variables
>allocated on the stack (as automatics or using _alloca()) will be thread-
>specific.

After having to deal with this kind of crap since version 1.(1 or 2, I can't
remember), I can say that after designing/implementing many different inter-
thread communication mechanisms, I find that the easiest to use is the
following:

1)  Define two user messages

    #define MYM_STARTTHREAD (WM_USER)
    #define MYM_ENDTHREAD (WM_USER+1)

2)  For every type of asynchronous action needed, allocation 1 bit out of
    a total of 32 for it and define a constant for it.  E.g.,

    #define ASYNC_OPEN 0x00000001L
    #define ASYNC_PRINT 0x00000002L

    For each window class, create a ULONG field in the instance data to
    hold the bits corresponding to the threads started by windows of this
    class.

3)  Also, for each action, define a structure containing all variables to
    be *sent* to the thread and all variables to be *returned* from the
    thread.  The first field *MUST* be a ULONG containing the size of the
    structure for the purposes of communicating to PM the amount of memory
    to thunk, should that be required in a system call.

    You might want to also create a common THREADINFO structure containing
    fields that all threads will have, to save you some typing.

4)  Whenever a window needs to perform some lengthy processing, it sends
    itself a MYM_STARTTHREAD with LONGFROMMP(mpParm1) specifying the type
    of thread required and PVOIDFROMMP(mpParm2) pointing to an *already
    initialized* thread structure (see step 3) to be passed to the thread.

    The message processing can first cast this pointer to PTHREADINFO
    (assuming you typedef'd one as recommended) to initialize the common
    fields (one that is needed is the window handle of the "owning" thread).
    It then switch's on the thread type in order to: malloc() a block to
    copy this thread-specific structure into, in case the pointer passed in
    pointed to an automatic variable, and also to determine the procedure for
    the thread.  Finally, it calls _beginthread to start the thread,
    specifying the pointer to the malloc()'d block as the parameter to the
    thread.

    The thread receives this pointer, does its stuff, sets the variables to
    be communicated back to the window in the structure and executes the
    following code (assuming the definitions at the beginning):

    VOID _Optlink mythread(PMYTHREADINFO pmtiInfo)
    {
        :
       WinPostMsg(pmtiInfo->hwndOwner,
                  MYM_ENDTHREAD,
                  MPFROMLONG(ASYNC_SOMETHING),
                  MPFROMP(pmtiInfo);
       DosEnterCritSec();
       pmtiInfo->bThreadDead=TRUE;
    }

    The owning window resets the bit in its ULONG to specify that the
    thread is no longer active and free()'s the memory (after executing
    the following loop to insure that the thread is dead)
   
    while (!pmtiInfo->bThreadDead) DosSleep(0);

    Of course, any return codes from the thread (via the structure) are
    checked, etc.

What are the advantages of this method?

1)  Look Ma, no global variables!

2)  The procedure of the owning window can intercept the WM_MOUSEMOVE and
    WM_CONTROLPOINTER messages and return the appropriate value to specify
    SPTR_WAIT should the ULONG ulAsync variable in its instance data be
    non-zero.  This provides excellent user-feedback.  Additionally, the
    WM_INITMENU can be intercepted and any menu items needed can be
    disabled depending on which threads are active.

Any questions can be directed to me either through the conference or email.

Cheers,
Q
-- 
Have you read this month's EDM/2?  It's available via anonymous FTP to
ftp.cdrom.com in the /pub/os2/2_x/program/newsltr directory.  New articles,
comments, suggestions, and Q&A questions are always welcome!  Send all to
os2man@panix.com .
Technical Details
Message-ID: <28p41g$k3s@panix.com>
Path: arc1-ca.pugleaf.net!gmd.de!newsserver.jvnc.net!darwin.sura.net!emory!swrinde!cs.utexas.edu!uunet!panix!not-for-mail
References: <28efue$478@access.digex.net> <28ins7$fvv@tinman.dev.prodigy.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 11307a,b690185ddc355787
X-Google-Attributes: gid11307a,public
X-Google-Thread: 10cd94,b690185ddc355787
X-Google-Attributes: gid10cd94,public
X-Google-ArrivalTime: 1993-10-04 05:22:57 PST
Path: arc1-ca.pugleaf.net!gmd.de!newsserver.jvnc.net!darwin.sura.net!emory!swrinde!cs.utexas.edu!uunet!panix!not-for-mail
From: os2man@panix.com (Q)
Newsgroups: comp.os.os2.programmer.misc,bit.listserv.os2-l
Subject: Re: Thread-specific variables?
Date: 4 Oct 1993 08:13:36 -0400
Organization: PANIX Public Access Internet and Unix, NYC
Lines: 102
Message-ID: <28p41g$k3s@panix.com>
References: <28efue$478@access.digex.net> <28ins7$fvv@tinman.dev.prodigy.com>
NNTP-Posting-Host: panix.com