⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mthread.gml

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 GML
📖 第 1 页 / 共 2 页
字号:
#define STACK_SIZE      32768

.code break
static void a_thread( void *arglist )
/***********************************/
{
    while( HoldThreads ) {
        DosSleep( 1 );
    }
    printf( "Hi from thread %d\n", *_threadid );
    DosEnterCritSec();
    --NumThreads;
    DosExitCritSec();
    _endthread();
}

.code break
int main( void )
/**************/
{
    int         i;

    printf( "Initial thread id = %d\n", *_threadid );
    NumThreads = 0;
    HoldThreads = 1;
    /* initial thread counts as 1 */
    for( i = 2; i <= NUM_THREADS; ++i ) {
        if( _beginthread( a_thread, NULL, STACK_SIZE, NULL ) == -1 ) {
            printf( "creation of thread %d failed\n", i );
        } else {
            ++NumThreads;
        }
    }
.code break
    HoldThreads = 0;
    while( NumThreads != 0 ) {
        DosSleep( 1 );
    }
    return( 0 );
}
.code end
.do end
.autonote Note:
.note
In the &function
.id a_thread,
.id DosEnterCritSec
and
.id DosExitCritSec
are called when we modify the variable
.id NumThreads.
This ensures that the action of extracting the value of
.id NumThreads
from memory, incrementing the value, and storing the new result into
memory, occurs without interruption.
If these functions were not called, it would be possible for two
threads to extract the value of
.id NumThreads
from memory before an update occurred.
.endnote
.do end
.*
.if '&targetos' eq 'Windows NT' .do begin
.if '&lang' eq 'FORTRAN 77' .do begin
The source code for this example can be found in
.fi &pathnam.\samples\fortran\win32.
.code begin
* MTHREAD.FOR

*$pragma aux (__stdcall) Sleep parm( value )
*$pragma aux (__stdcall) InitializeCriticalSection parm( reference )
*$pragma aux (__stdcall) DeleteCriticalSection parm( reference )
*$pragma aux (__stdcall) EnterCriticalSection parm( reference )
*$pragma aux (__stdcall) LeaveCriticalSection parm( reference )

        structure /RTL_CRITICAL_SECTION/
            integer*4 DebugInfo
            integer*4 LockCount
            integer*4 RecursionCount
            integer*4 OwningThread
            integer*4 LockSemaphore
            integer*4 Reserved
        end structure

.code break
        integer NumThreads
        logical HoldThreads
        volatile HoldThreads, NumThreads
        record /RTL_CRITICAL_SECTION/ CriticalSection
        common NumThreads, HoldThreads, CriticalSection

        integer STACK_SIZE
        parameter (STACK_SIZE=8192)
        integer NUM_THREADS
        parameter (NUM_THREADS=5)

        integer i, threadid, beginthread
        external a_thread

.code break
        print '(''main thread id = '',i4)', threadid()
        NumThreads = 0
        HoldThreads = .true.
        ! main thread counts as 1
        call InitializeCriticalSection( CriticalSection )
        do i = 2, NUM_THREADS
            if( beginthread( a_thread, STACK_SIZE ) .eq. -1 )then
                print '(''creation of thread'',i4,''failed'')', i
            else
                NumThreads = NumThreads + 1
            end if
        end do
.code break
        HoldThreads = .false.
        while( NumThreads .ne. 0 ) do
            call Sleep( 1 )
        end while
        call DeleteCriticalSection( CriticalSection )
        end

.code break
        subroutine a_thread()

        structure /RTL_CRITICAL_SECTION/
            integer*4 DebugInfo
            integer*4 LockCount
            integer*4 RecursionCount
            integer*4 OwningThread
            integer*4 LockSemaphore
            integer*4 Reserved
        end structure

.code break
        integer NumThreads
        logical HoldThreads
        volatile HoldThreads
        record /RTL_CRITICAL_SECTION/ CriticalSection
        common NumThreads, HoldThreads, CriticalSection

        integer threadid

.code break
        while( HoldThreads ) do
            call Sleep( 1 )
        end while
.code break
        print '(''Hi from thread '', i4)', threadid()
        call EnterCriticalSection( CriticalSection )
        NumThreads = NumThreads - 1
        call LeaveCriticalSection( CriticalSection )
        call endthread()
        end
.code end
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
.code begin
#include <process.h>
#include <stdio.h>
#include <stddef.h>
#include <windows.h>

static  volatile int    NumThreads;
static  volatile int    HoldThreads;

CRITICAL_SECTION CriticalSection;

#define NUM_THREADS     5
#define STACK_SIZE      8192

.code break
static void a_thread( void *arglist )
/***********************************/
{
    while( HoldThreads ) {
        Sleep( 1 );
    }
    printf( "Hi from thread %d\n", *_threadid );
    EnterCriticalSection( &CriticalSection );
    --NumThreads;
    LeaveCriticalSection( &CriticalSection );
    _endthread();
}

.code break
int main( void )
/**************/
{
    int         i;

    printf( "Initial thread id = %d\n", *_threadid );
    NumThreads = 0;
    HoldThreads = 1;
    InitializeCriticalSection( &CriticalSection );
    /* initial thread counts as 1 */
    for( i = 2; i <= NUM_THREADS; ++i ) {
        if( _beginthread( a_thread, STACK_SIZE, NULL ) == -1 ) {
            printf( "creation of thread %d failed\n", i );
        } else {
            ++NumThreads;
        }
    }
.code break
    HoldThreads = 0;
    while( NumThreads != 0 ) {
        Sleep( 1 );
    }
    DeleteCriticalSection( &CriticalSection );
    return( 0 );
}
.code end
.do end
.autonote Note:
.note
In the &function
.id a_thread,
.id EnterCriticalSection
and
.id LeaveCriticalSection
are called when we modify the variable
.id NumThreads.
This ensures that the action of extracting the value of
.id NumThreads
from memory, incrementing the value, and storing the new result into
memory, occurs without interruption.
If these functions were not called, it would be possible for two
threads to extract the value of
.id NumThreads
from memory before an update occurred.
.endnote
.do end
.np
Let us assume that the file
.fi &tgtfile..&langsuff
contains the above example.
Before compiling the file, make sure that the
.ev &pathvarup.
environment variable is set to the directory in which you installed
&product..
.if '&lang' eq 'FORTRAN 77' .do begin
Also, the
.ev FINCLUDE
environment variable must contain the
.if '&targetos' eq 'OS/2 2.x' .do begin
.fi &pathnam\src\fortran\os2
.do end
.el .do begin
.fi &pathnam\src\fortran
.do end
directory where "&pathnamup" is the name of the directory in which you
installed &product..
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
Also, the
.ev INCLUDE
environment variable must include the
.if '&targetos' eq 'OS/2 2.x' .do begin
.fi &pathnam\h\os2
.do end
.el .do begin
.fi &pathnam\h\nt
.do end
and
.fi &pathnam\h
directories
("&pathnamup" is the directory in which &product was installed).
.do end
.np
We can now compile and link the application by issuing the following
command.
.millust begin
&prompt.&wclcmd &tgtopts &sw.l=&tgtosname &tgtfile
.millust end
.np
The "bm" option must be specified since we are creating a
multi-threaded application.
If your multi-threaded application contains more than one module, each
module must be compiled using the "bm" switch.
.np
The "l" option specifies the target system for which the application
is to be linked.
The system name
.id &tgtosname
is defined in the file
.fi wlsystem.lnk
which is located in the "BINW" subdirectory of the directory in which you
installed &product..
.np
The multi-threaded application is now ready to be run.
.*
.if '&targetos' eq 'OS/2 2.x' .do begin
.section Thread Limits
.*
.np
.ix 'thread limits' '&targetos.'
There is a limit to the number of threads an application can create
under 16-bit OS/2.
The default limit is 32.
.if '&lang' eq 'FORTRAN 77' .do begin
This limit can be adjusted by defining the integer function
.id __getmaxthreads
which returns the new thread limit.
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
This limit can be adjusted by statically initializing the unsigned
global variable
.id __MaxThreads.
.do end
.np
Under 32-bit OS/2, there is no limit to the number of threads an
application can create.
However, due to the way in which multiple threads are supported in the
&company libraries, there is a small performance penalty once the number
of threads exceeds the default limit of 32 (this number includes the
initial thread).
If you are creating more than 32 threads and wish to avoid this
performance penalty, you can redefine the threshold value of 32.
You can statically initialize the global variable
.id __MaxThreads.
.np
.if '&lang' eq 'FORTRAN 77' .do begin
This limit can be adjusted by defining the integer function
.id __getmaxthreads
which returns the new thread limit.
By defining
.id __getmaxthreads
as follows, the new threshold value will be set to 48.
.millust begin
integer function __getmaxthreads()
__getmaxthreads = 48
end
.millust end
.np
This version of
.id __getmaxthreads
will replace the default function that is included in the run-time
library.
The default function simply returns the current value of the internal
variable
.id __MaxThreads.
Your version of this function will return a new value for this
variable.
Internally, the run-time system executes code similar to the
following:
.millust begin
    .
    .
    .
    __MaxThreads = __getmaxthreads()
    .
    .
    .
.millust end
.np
Thus, the default
.id __getmaxthreads
function does not alter the value of
.id __MaxThreads
but your version will.
.do end
.if '&lang' eq 'C' or '&lang' eq 'C/C++' .do begin
By adding the following line to your multi-threaded application, the
new threshold value will be set to 48.
.millust begin
unsigned __MaxThreads = { 48 };
.millust end
.do end
.*
.do end
.*
:set symbol="prompt"     value=&oprompt.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -