Announcement

Collapse
No announcement yet.

PBCC V5.04 THREADCOUNT Issue?

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • PBCC V5.04 THREADCOUNT Issue?

    Hi all,
    Not sure if this is just me or has anyone else found any issues with THREADCOUNT since upgrading to PBCC V5.04.

    I have a console program which has been running for several years, compiled under PBCC V5.02. I have recently upgraded to V5.04, missed V5.03 completely, but the same program with no source changes at all will no longer close!!!

    I have a small section at the end of the program which loops & waits for all running threads to terminate, I use THREADCOUNT=1 as the loop exit condition, on exit from the loop and following a little tidy up, I simply exit the program, the console window closes, all done. BUT ...

    Since compiling the same program on V5.04, the console window stays open and the program appears to hang. I found through trial and error that by simply including the line 'i=THREADCOUNT' just prior to exit, everything now works as it should

    I happy to leave this fix in place, since it gets around the problem, but I was just wondering if anyone else has had any similar issues

    Thanks
    Richard

  • #2
    Code:
       WaitforMultipleObjects _ 
           Number_of_addl_threads, _ 
           Ptr_to_array_of_thread_handles, _
          %TRUE, _                    ' yes wait for all 
           %INFINITE                  ' RMWI
    Michael Mattias
    Tal Systems (retired)
    Port Washington WI USA
    [email protected]
    http://www.talsystems.com

    Comment


    • #3
      I use THREADCOUNT=1 as the loop exit condition
      DO UNTIL THREADCOUNT = 1 (correct)
      DO WHILE THREADCOUNT = 1 (wrong)

      Tested with earlier versions and current version.

      Code:
      FUNCTION PBMAIN () AS LONG
        LOCAL x AS LONG, hThread AS LONG
        THREAD CREATE TEST(x) TO hThread
        SLEEP 50 'very important to give thread time to allocate
        DO UNTIL THREADCOUNT = 1:? "THREADCOUNT" + STR$(THREADCOUNT):SLEEP 10:LOOP
        THREAD CLOSE hThread TO hThread
      END FUNCTION
      THREAD FUNCTION TEST(BYVAL x AS LONG) AS LONG
        ? "IN THREAD AND THREADCOUNT" + STR$(THREADCOUNT)
        SLEEP 500
      END FUNCTION




      Does this work? (or please post some test code)
      How long is an idea?

      Comment


      • #4
        I found through trial and error that by simply including the line 'i=THREADCOUNT' just prior to exit, everything now works as it should
        Upon further review... I can't say I am surprised by this.

        When you type (this if course is a guess since allegedly failing code not shown)...
        Code:
        WHILE THREADCOUNT > 1
          SLEEP 100
        WEND
        .. the compiler will expand this into many many instructions, after any of which the O/S can interrupt your loop to process other threads of execution... some of which may start or end those or other threads of execution, changing the value of THREADCOUNT.

        By assigning THREADCOUNT to a variable, you force the THREADCOUNT function to complete before it is tested against the value one (1). (It may do that anyway, but by its very nature THREADCOUNT is perforce dynamic).

        That said, this is a really esoteric explanation (see also: Spin Doctoring). I think I'd look at other parts of your program for some funkiness for which you were forgiven in prior versions of the compiler (said forgiveness would have been pure serendipity,).

        MCM
        Michael Mattias
        Tal Systems (retired)
        Port Washington WI USA
        [email protected]
        http://www.talsystems.com

        Comment


        • #5
          Thanks for the pointers to the potential problem, non of which make any difference by the way!

          My existing code uses several threads, these are created and their handle released straight away:-

          Code:
                THREAD CREATE MyThread1(0) TO ThreadHandle
                THREAD CLOSE ThreadHandle TO ThreadResult
          This allows them to run until task completion where upon they end.

          Each thread is a self contained tight loop of code which does a certain task, as part of the loop, they check a global variable 'ProgramRunning' which is set TRUE by the main program prior to the threads being started and is cleared by the main program as it closes (see below), this allows the threads to terminate prior to the main program exiting.

          Code:
          j=100 / THREADCOUNT                               'Scale of running threads
          CALL InterlockedDecrement(ProgramRunning)  'Stop all running threads
          DO
            i=100-(THREADCOUNT * j)                        'Percentage done
            ProgressBoxUpdate i                                 'Show progress
            SLEEP 100
          LOOP WHILE THREADCOUNT > 1                   'Wait for all active threads to terminate 
          i=THREADCOUNT                                        '**FIXES PROBLEM**
          I use a 'ConsolTools' progress bar to show the threads terminating, hence the percentage calculation using THREADCOUNT.

          ----------------------

          As a side issue, I have also found that other sections of code which use a call to 'InterLockedExchange' are also no longer working correctly, they cause the program to crash & burn with no error message of any kind. By commenting out the calls, the program continues to run or if I remove the calls and wrap the affected sections in a 'Critical-Section', then this also fixes the problem?

          So I am wondering if (whatever it is that has canged) has also affected the call to 'InterlockedDecrement' in the shutdown section shown above, preventing the threads from terminating. But that said, adding the i=THREADCOUNT statement after the shutdown loop would not have the desired effect if this were the case?
          Richard

          Comment


          • #6
            Well, you are simply going to have to come up with a better and more realistic demonstration code. There are just too many inconsistencies here.

            My existing code uses several threads, these are created and their handle released straight away.... This allows them to run until task completion where upon they end
            The fact a handle is open on a thread has nothing to do with the execution of its thread function. Those functions run until they reach their "END FUNCTION" regardless.

            Code:
            CALL InterlockedDecrement(ProgramRunning)  'Stop all running threads
            Unless your thread functions are testing the 'ProgramRunning' variable, calling InterlockedDecrement() does not "stop" a thread. However, that makes no sense to code like that... since you are checking for "any thread function still executing" via THREADCOUNT maintaining your own 'count' variable is redundant at best.

            As long as you build array of thread handles anyway, why don't you try "wait for all to complete" using the WaitForMultipleObjects() code in Post #2? Get that loop on THREADCOUNT out of there, forget about the "programrunning" variable, just do it nice and clean.

            Once you find you real problem (I am now convinced your error is elsewhere in your program) you can work on getting your progress bar working.

            BTW, re the Interlocked*() function behavior? . check your Win32API.INC file looking for changes in the DECLAREs. That can cause some weird things to happen... for that matter, it can cause your exact problem if those changes are resulting in changes to the value of one of your control variables.

            Also, note that the targets of the interlocked*() functions must be 32-bit aligned under certain conditions:

            The variable pointed to by the lpAddend parameter must be aligned on a 32-bit boundary; otherwise, this function will fail on multiprocessor x86 systems and any non-x86 systems.
            Code/Conditions not shown.

            Lastly, am going to renege a little on my prior explanation re why adding "i=Threadcount" "fixes" (quotes deliberate) the problem. A while back Mr. Zale gave a fairly lengthy explanation of how adding one line here or subtracting one line there changes a lot of different compiled output... I don't recall the details, but it distilled down to something like "when you have an error in your program, adding or subtracting lines does not solve the problem, it merely changes the type of the error and the point in your program where the error manifests itself."

            As I said above, I am now convinced your error is elsewhere, and your added line of code has simply relocated its manifestation.

            MCM
            Last edited by Michael Mattias; 7 Jun 2010, 09:28 AM.
            Michael Mattias
            Tal Systems (retired)
            Port Washington WI USA
            [email protected]
            http://www.talsystems.com

            Comment


            • #7
              We have no code to look at.
              You might try putting EXIT FUNCTION as the first line of each function until the program exits properly.
              How long is an idea?

              Comment


              • #8
                You might try changing

                Code:
                i = threadcount
                to one of the following

                Code:
                i = 1 ' Same as threadcount; threadcount will always = 1 when this line of code is executed. 
                i = 0 
                i = 1000 ' or any other number
                i = i 
                
                or s = "ABCD"  ' Use a 4 byte string, then try 3 bytes, and so on and see if it crashes or is ok. 
                
                You may want to print out S and I before the application exits. Is it the value you expect or has it been modified?
                It does not make sense that adding i = threadcount would "fix" the application. I think any extra line of code would "fix the application". It is possible the issue might be an Out of bounds on an array? or some other bounds issue the thread functions.

                You may want to post an example of code with the failure. I find just creating the sample solution leads to the solution. If not resolved, I and others are happy to review the failing code. Without the failing code I and others are just guessing at the issue and most likely sending you on a wild goose chase.

                Comment


                • #9
                  I would love to be able to share the whole thing with you guys and get some useful tips & pointers, but the program is subject to my customer’s intellectual property rights and I’m sure he would take a dim view of me posting his source code on the web for all to see. However, I don’t see any problem with sharing snippets, but I’m sure it’s not going to give enough info on which to base an accurate diagnosis.

                  Here goes, basic concepts. One large program which spawns approximately 8 other threads. The main program sets a global long variable called ‘ProgramRunning’=1 at startup, then proceeds to spawn the threads using the following technique:-

                  Code:
                        THREAD CREATE Thread1(0) TO ThreadHandle
                        THREAD CLOSE ThreadHandle TO ThreadResult
                  
                        THREAD CREATE Thread2(0) TO ThreadHandle
                        THREAD CLOSE ThreadHandle TO ThreadResult
                  A typical thread will look something like this, (but with the working code removed)….

                  Code:
                       FUNCTION Thread1(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                  
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                  
                  	Do some stuff here …
                  
                            
                          SLEEP 1                       'Give some time to other threads & processes
                          WEND
                          FUNCTION=0
                        END FUNCTION

                  As you can see, this thread (and all others, structure is the same) will run indefinitely until such time as the global variable ‘ProgramRunning’=0, this is cleared by the main program when it exits, see below.


                  Code:
                  ExitProg:
                  ProgressBoxShow %NOCANCEL,0,%CONSOLE_CENTER,%CONSOLE_CENTER, _
                                  "Waiting For Running Tasks To Terminate", _
                                  "Exit Program",0
                  
                  j=100 / THREADCOUNT                       'Scale of running threads
                  CALL InterlockedDecrement(ProgramRunning) 'Stop all running threads
                  DO
                    i=100-(THREADCOUNT * j)         'Percentage done
                    ProgressBoxUpdate i             'Show progress
                    SLEEP 100
                  LOOP WHILE THREADCOUNT > 1        'Wait for all active threads to terminate
                  
                  A bit more code tidying up goes here …. Then
                  
                  i=THREADCOUNT                         'Since PBCC V5.04, appear to need another call to threadcount
                                                        'in order to get the console window to close????
                  
                  END FUNCTION
                  So, the line prior to end function allows the console to close as it always used to do, just out of interest, I tried changing this line to ‘i=1’ (no called to THREADCOUNT) and it had exactly the same effect, which I’m afraid to say only reinforces what Michael said ..

                  As I said above, I am now convinced your error is elsewhere, and your added line of code has simply relocated its manifestation.
                  But given the nature of the beast and unfortunately very little time to go hunting, the mystery may have to remain unresolved… Thanks anyway.
                  Richard

                  Comment


                  • #10
                    Richard,

                    I'm not sure if it has any relevance but if ProgramRunning is a global
                    variable then why are you passing it to InterlockedDecrement ? Is that
                    supposed to set it to zero? Maybe you should check the global variable
                    right after that call.

                    Just a thought.

                    Comment


                    • #11
                      I made the snippets into a compilable program and it works fine.

                      It must be something in the DO some stuff here.

                      I recommend commenting out all threads DO stuff code and run the application.
                      Uncomment the code to thread1. Run it, see that it works (or doesn't). Then comment it out again and uncomment thread2. Try running with each thread independently.

                      By doing this you will find the thread that is causing the issue.
                      If not, the issue is with multiple threads running and you will have to try threads in combination to find the issue. Try uncommenting Thread1, Thread2, thread3 until the problem. Then comment Thread1 and see if the issue goes away.

                      Another idea is to comment out one thread at a time. Comment out Thead1 and run it. Uncomment thread1 and comment out thread2 and so on. This will always have 7 of the 8 threads running. This might actually be the better approach to finding the thread with the issue.

                      I'll say it again. If you can simplify and show failing code. It would help us help you. It doesn't have to do the same thing your application does. Make an example that has the error. Instead of performing X (intellectual property), perform something different. By just trying to create a simplified failing code I usually find the error.

                      At least now you know that the scaffolding isn't the issue. The issue is in what stuff your doing.

                      Code:
                      #COMPILE EXE
                      #DIM ALL
                      
                      #INCLUDE ONCE "win32api.inc"
                      GLOBAL ProgramRunning AS LONG
                      
                      FUNCTION Thread1(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                              
                          FUNCTION=0
                              
                      END FUNCTION
                      
                      FUNCTION Thread2(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                      
                          FUNCTION=0
                      
                      END FUNCTION
                      
                      FUNCTION Thread3(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                      
                          FUNCTION=0
                      
                      END FUNCTION
                      
                      FUNCTION Thread4(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                      
                          FUNCTION=0
                      
                      END FUNCTION
                                      
                      FUNCTION Thread5(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                      
                          FUNCTION=0
                      
                      END FUNCTION
                                                      
                      FUNCTION Thread6(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                      
                          FUNCTION=0
                      
                      END FUNCTION
                                      
                      FUNCTION Thread7(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                      
                          FUNCTION=0
                      
                      END FUNCTION
                      
                      FUNCTION Thread8(BYVAL Dummy AS LONG) AS LONG
                          LOCAL ins AS INTEGER
                          LOCAL prt1 AS LONG,prt2 AS LONG
                      
                          WHILE (ISTRUE ProgramRunning)   'Execute this thread while main prog runs
                      
                              'Do some stuff here …
                      
                              SLEEP RND(1,5) * 1000                       'Give some time to other threads & processes
                          WEND
                      
                          FUNCTION=0
                      
                      END FUNCTION
                                      
                                                      
                      
                      FUNCTION PBMAIN () AS LONG
                      
                          LOCAL threadHandle AS LONG
                          LOCAL threadResult AS LONG
                      
                          programRunning = %true
                          THREAD CREATE Thread1(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                      
                          THREAD CREATE Thread2(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                      
                          THREAD CREATE Thread3(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                      
                          THREAD CREATE Thread4(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                      
                          THREAD CREATE Thread5(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                      
                          THREAD CREATE Thread6(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                      
                          THREAD CREATE Thread7(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                      
                          THREAD CREATE Thread8(0) TO ThreadHandle
                          THREAD CLOSE ThreadHandle TO ThreadResult
                          
                          
                          
                      '    ProgressBoxShow %NOCANCEL,0,%CONSOLE_CENTER,%CONSOLE_CENTER, _
                      '    "Waiting For Running Tasks To Terminate", _
                      '    "Exit Program",0
                          LOCAL j AS LONG
                          j=100 / THREADCOUNT                       'Scale of running threads
                          CALL InterlockedDecrement(ProgramRunning) 'Stop all running threads
                      
                          LOCAL i AS LONG
                          DO
                            i=100-(THREADCOUNT * j)         'Percentage done
                            ? i             'Show progress
                            SLEEP 100
                          LOOP WHILE THREADCOUNT > 1        'Wait for all active threads to terminate
                      
                      '    A bit more code tidying up goes here …. Then
                      
                      '    i=THREADCOUNT                         'Since PBCC V5.04, appear to need another call to threadcount
                                                                    'in order to get the console window to close????
                          ? "Done"
                          WAITKEY$
                      
                      END FUNCTION
                      Last edited by Brian Chirgwin; 8 Jun 2010, 10:23 AM. Reason: Fixed Code tags. - Thanks Mike

                      Comment


                      • #12
                        >It must be something in the DO some stuff here.

                        Checkmark.


                        BTW.. if you go to the WFMO (vs THREADCOUNT loop) approach, probably the easiest way to get the progress bar in there is to run that progress bar in its own thread of execution, a thread on which you are NOT waiting, as demo'd here...

                        Progress Bar Dialog for PB/CC programs October 24, 2002
                        (Ignore the "PB/CC" in the thread title. This will work in a GUI program exactly the same way).

                        ..and applied thus (in pseudocode):
                        Code:
                        FUNCTION WinMain
                        
                            FOR N = 1 TO Num_worker_threads   
                               THREAD CREATE ThreadFunctionN TO hthread(N) 
                           ENDFOR
                           CreateProgressWindowThread  to hWnd
                           WaitForMultipleObjects ( hThread() array) 
                           ' ------------------------------------------------------------------ 
                           ' when you get here, all the "THREADFUNCTION-N" have completed
                           ' ------------------------------------------------------------------ 
                           Send WM_CLOSE to Progress Window
                           WaitForSingleObject  on  Progress Window Thread 
                           ' I think I give you a thread handle  as well as a window handle; if 
                           ' not, call GetWindowThreadProcessID to get a thread ID, and open that 
                          '  thread ID with OpenThread() to get a handle you can wait on. 
                        
                        END WinMain
                        MCM
                        Last edited by Michael Mattias; 8 Jun 2010, 08:55 AM.
                        Michael Mattias
                        Tal Systems (retired)
                        Port Washington WI USA
                        [email protected]
                        http://www.talsystems.com

                        Comment


                        • #13
                          OK I admit defeat; sometimes you can’t win the war, so you just have to settle for winning the battle. Having made several tests on my existing program under PBCC5.04 and suffered numerous unexplained problems and out right program crashes, I gave in and rolled my compiler back to V5.02, everything now works as it should, a rock steady program with no crashes and no problems.

                          I know that my program is carrying some excess baggage since it is very old and was ported over from PBDOS, but I would love to know what differences PB has made since V5.02, knowing this information may make the task of trawling through in excess of 25,000 lines of code a little more practical.

                          Moaning done now, I think I’ll have to stick with V5.02 and hope PB don’t introduce too many new goodies that I can’t live without!

                          Thanks for all your comments and help. :wave:
                          Richard

                          Comment


                          • #14
                            Did you try putting EXIT FUNCTION as the first line of the thread functions until the program exits properly?
                            You can also write a program to insert a trace statement with exit into each function to isolate it.
                            How long is an idea?

                            Comment


                            • #15
                              > but I would love to know what differences PB has made since V5.02,

                              Probably nothing that would affect any of this stuff.

                              Far more likely is, you have had errors in your program since day one and some quirk of the compiler resulted in total forgiveness of those sins.

                              However, if you are convinced otherwise, ZIP up a package of everything needed to run the program (source, executable, data files, etc) and send to to PB Support. They'll run it and if there is something wrong they will find it.

                              It may turn out that the problem is an error 1 (programmer error). In this case you have to be ready to pay for consulting time to find it. I 'assume' if the problem eventually traces back to a compiler issue you'd get your money back. But you can talk to them first and come to some arrangement.

                              Or, you can engage someone else to find the problem. In this case there is no way you will get your money back if the problem does trace back to a compiler issue.

                              Yes, the PB products sometimes ship with bugs, but they are few and far between.

                              MCM
                              Michael Mattias
                              Tal Systems (retired)
                              Port Washington WI USA
                              [email protected]
                              http://www.talsystems.com

                              Comment


                              • #16
                                FWIW...
                                I was intrigued as to how THREADCOUNT() was implemented.

                                I was kind of hoping for an "enumthreads(hProcess) " or something like that but I could not find anything close.

                                Only way I could find to get a thread count other than using THREADCOUNT() was to take a snapshot of the process (CreateToolHelp32Snapshot) and count the threads with Thread32First/Next.

                                So... between checking imports of programs compliled with/without this function and drawing some inferences reading the doc, it appears THREADCOUNT is implemented wholly within the PB runtime library, which suggests it only counts threads created with the THREAD CREATE statement executed from the current module.

                                MCM
                                Michael Mattias
                                Tal Systems (retired)
                                Port Washington WI USA
                                [email protected]
                                http://www.talsystems.com

                                Comment


                                • #17
                                  Wouldn't be surprised. It would tend to be a bad idea, in general, to create threads in PowerBASIC without using the THREAD statements. Threads are very handy and very dangerous. The compiler tends to need to know what you're doing with them. There are exceptions but, unless you know exactly what you're doing, you'd better consider them loopholes. That is, "don't do that." Use the provided mechanisms.

                                  That's a conservative impulse for people who don't know what a thread is to begin with. There are probably obvious exceptions that don't occur to me right now. Threads are too useful to ignore, unfortunately. They do tend to complicate programming far more than you ever imagined.

                                  Comment


                                  • #18
                                    Wouldn't be surprised. It would tend to be a bad idea, in general, to create threads in PowerBASIC without using the THREAD statements
                                    Oh, I agree with that, but..

                                    Supposin' I am creating additional TOEs using THREAD CREATE in a function residing in a DLL?

                                    If the THREADCOUNT() function *is* implemented thru the RTL, then when called from the "main" executable module the returned value would not include such threads. That is, if I'm waiting for all my worker threads to complete by looping on THREADCOUNT() in WinMain, I could EXIT whilst one or more worker thread functions have not yet completed.

                                    Sure seems like the kind of thing which should appear in the documentation somewhere.

                                    That is, "assuming" I have made a good guess. I suppose I could test it and see what happens, but that test would only tell me how it behaves in the current version of the compiler.

                                    In this (BBS) thread, we haven't seen any code... for all we know the "Do Something" is calling functions in DLLs, functions which create additional TOEs. That would explain inconsistent behavior generally, although it would not explain specific inconsistencies across compiler versions.

                                    MCM
                                    Michael Mattias
                                    Tal Systems (retired)
                                    Port Washington WI USA
                                    [email protected]
                                    http://www.talsystems.com

                                    Comment


                                    • #19
                                      http://www.powerbasic.com/support/pb...ad.php?t=41675

                                      Supposin' I am creating additional TOEs using THREAD CREATE in a function residing in a DLL?

                                      If the THREADCOUNT() function *is* implemented thru the RTL, then when called from the "main" executable module the returned value would not include such threads. That is, if I'm waiting for all my worker threads to complete by looping on THREADCOUNT() in WinMain, I could EXIT whilst one or more worker thread functions have not yet completed.



                                      Code:
                                      FUNCTION PBTHREADCOUNT EXPORT AS LONG
                                        FUNCTION = THREADCOUNT
                                      END FUNCTION
                                      Last edited by Mike Doty; 12 Jun 2010, 12:04 PM.
                                      How long is an idea?

                                      Comment


                                      • #20
                                        It would seem in PB/WIn 9.03 THREADCOUNT() *IS* Implented via the RTL...

                                        Code:
                                        ' test_threadcountDLL
                                        #COMPILE DLL
                                        #DIM ALL
                                        
                                        FUNCTION StartSomeThreadsInDLL ALIAS "F001"  (nThread AS LONG) EXPORT AS LONG
                                        
                                         LOCAL Z AS LONG, hThread AS LONG
                                         
                                         FOR Z = 1 TO nThread
                                             THREAD CREATE ThreadFunc(Z) TO hThread
                                             THREAD CLOSE hThread TO hThread
                                         NEXT
                                         
                                            
                                        END FUNCTION
                                        
                                        FUNCTION StartSomeThreadsInDLLNoClose ALIAS "F002"  (nThread AS LONG) EXPORT AS LONG
                                            
                                         
                                         LOCAL Z AS LONG, hThread() AS LONG
                                         
                                         REDIM hThread (nThread-1)
                                        
                                         FOR Z = 1 TO nThread
                                             THREAD CREATE ThreadFunc(Z) TO hThread(Z-1)
                                         NEXT
                                         
                                         
                                        END FUNCTION
                                        
                                        
                                        FUNCTION ThreadFunc (BYVAL ThreadNo AS LONG) PRIVATE AS LONG
                                            
                                            MSGBOX USING$("Welcome to ThreadFunc #", Threadno)
                                            
                                        END FUNCTION
                                        Code:
                                        #COMPILE EXE
                                        #DIM ALL
                                        
                                        DECLARE FUNCTION StartmeUp LIB "Test_ThreadCountDLL.DLL" ALIAS "F001" (nThread AS LONG) AS LONG
                                        
                                        DECLARE FUNCTION StartmeUpNoClose LIB "Test_ThreadCountDLL.DLL" ALIAS "F002" (nThread AS LONG) AS LONG
                                        
                                        FUNCTION PBMAIN () AS LONG
                                            
                                          LOCAL tc AS LONG, nt AS LONG
                                          
                                          LET nt = 5
                                            
                                          CALL StartMeUp (nt)   ' starts nt threads, closes handled and returns
                                          
                                          tc = THREADCOUNT
                                          
                                          MSGBOX USING$ ("THREADCOUNT with handles closed  reports # TOEs", tc)
                                          
                                          CALL StartMeUpNoClose (nt)   ' starts nt threads leaving handles open and returns
                                        
                                          tc = THREADCOUNT
                                        
                                          MSGBOX USING$ ("THREADCOUNT with handles left open  reports # TOEs", tc)
                                        
                                        END FUNCTION
                                        I think I'll check to see of the doc has been updated in "dot-oh-four" and if not send in yet another "documentation improvement suggestion."

                                        MCM
                                        Michael Mattias
                                        Tal Systems (retired)
                                        Port Washington WI USA
                                        [email protected]
                                        http://www.talsystems.com

                                        Comment

                                        Working...
                                        X