Hello Przemek
Is it possible in Harbour that if the code below is executed on a multi cpu
machine,
we could see the multiple PIDs in the task manager. I mean is is possible to
execute threads on
multiple CPUs ?
>
> //////////////////////////////////////////////////////////////////////
> //
> // COFFEE.PRG
> //
> // Copyright:
> // Alaska Software, (c) 1997-2005. All rights reserved.
> //
> // Contents:
> // Example for advanced multi-threaded programming.
> //
> // This example is a real life simulation of a team of programmers
> // and a single coffee machine. It shows how to solve special
> problems
> // that may arise in multi-threaded programs.
> //
> // Remarks:
> // Watch the program's output before studying the code
> //
> // The program demonstrates two programming techniques for
> // multi-threading using a classical problem: multiple threads
> // access and change shared program resources at the same time and
> // must be coordinated. Thread coordination is accomplished using
> // one SYNC method (serialize program execution in multiple treads)
> // and two Signal objects (halt/restart program flow in one thread).
> //
> // The simulation uses:
> // 1) One thread for the coffee machine (C)
> // 2) Nine threads for the team of programmers (P)
> //
> // These are the real life assumptions of the program:
> // 1) When no coffee is left in the coffee machine, one thread (C)
> // must wait until another thread (P) fills the coffee machine
> // 2) While the coffee machine is running, up to nine threads (P)
> // must stop until the coffee is ready
> // 3) A programmer (P) works while he has coffee. When his cup is
> // empty, the programmer goes for a refill.
> // 4) Only one programmer (P) has access to the coffee machine (C)
> // at any point in time. If other programmers want to refill
> // their cups at the same time, the corresponding threads (P)
> // must stop.
> //
> //////////////////////////////////////////////////////////////////////
>
>
> /*
> * The Main procedure creates the threads, starts them and waits for a
> * key stroke to terminate the program. Ten threads are running while
> * Inkey(0) waits for a key.
> */
> PROCEDURE Main
> LOCAL i, oMachine
> LOCAL aTime := { 130, 100, 140, 90, 100, 110, 150, 120, 100 }
> LOCAL aNames:= { "Frank++ ", "Gernot ", "Andreas ", ;
> "Joerg ", "Michael ", "Steffen ", ;
> "Till ", "Volker ", "Wolfgang" }
> CLS
>
> // Start first thread (the coffee machine)
> oMachine := CoffeeMachine():new( 20 )
> oMachine:start()
>
> // Start nine additional threads (the team of programmers)
> FOR i := 1 TO 9
> Programmer():new( aNames[i], aTime[i], oMachine ):start()
> NEXT
>
> // Wait for a key stroke
> DispOutAt( 3, 0, "Press a key to QUIT" )
> Inkey(0)
>
> RETURN
>
>
>
> /*
> * This class simulates a coffee machine. Access to the coffee machine is
> * synchronized by the SYNC method :enter(). Two Signal objects make
> * sure that a programmer can get coffee only if coffee is ready, and
> * that the coffee machine waits to be filled when empty.
> */
> CLASS CoffeeMachine FROM Thread
> EXPORTED:
> VAR capacity, coffee, waterIsFilled, coffeeIsReady
>
> METHOD init, execute
> SYNC METHOD enter
> ENDCLASS
>
> METHOD CoffeeMachine:init( nCapacity )
> ::thread:init()
> ::setInterval( 10 )
> ::coffee := 0
> ::capacity := nCapacity
> ::waterIsFilled := Signal():new()
> ::coffeeIsReady := Signal():new()
> RETURN self
>
>
>
> /*
> * Only one object of the Programmer class can execute the :enter() method
> * at any point in time (SYNC method!). The color Red indicates
> * during runtime which thread is waiting to execute this method.
> */
> METHOD CoffeeMachine:enter( oProgrammer )
> oProgrammer:takeCoffee()
> RETURN self
>
>
>
> /*
> * As long as ::coffee >= 1, the CoffeeMachine thread issues the
> * ::coffeeIsReady signal which all Programmer threads are waiting for.
> * If ::coffee is less than 1, the thread waits until a Programmer thread
> * signals ::waterIsFilled. Then, the "coffee machine" enters the
> * DO WHILE loop which delays the ::coffeeIsReady signal.
> */
> METHOD CoffeeMachine:execute
> LOCAL n
>
> IF ::coffee < 1
> DispoutAt( 1, 0, PadR( "Coffee is empty! ",80 ), "W+/B" )
>
> ::waterIsFilled:wait()
>
> n := 0
> DO WHILE ++n <= ::capacity
> DispoutAt( 1, 0, PadR( "Coffee machine is running!
> "+Replicate(Chr(219),2*n), 80 ), "W+/B" )
> Sleep(35)
> ENDDO
> ::coffee := ::capacity
> ENDIF
>
> DispoutAt( 1, 0, PadR( "Coffee is ready!
> "+Replicate(Chr(176),::coffee*2), 80 ) )
> ::coffeeIsReady:signal()
>
> RETURN self
>
>
>
>
> /*
> * This class simulates a single programmer. A programmer works as long
> * as he has coffee.
> */
> CLASS Programmer FROM Thread
> EXPORTED:
> VAR name, coffee, coffeeMachine
> METHOD init, execute, takeCoffee
> ENDCLASS
>
>
>
> /*
> * A Programmer thread is re-started each time <nInterval> * 1/100 seconds
> * have elapsed. This is equivalent to the time a programmer needs to
> * drink his cup of coffee.
> */
> METHOD Programmer:init( cName, nInterval, oMachine )
> ::thread:init()
> ::setInterval( nInterval )
> ::coffee := 0
> ::name := cName
> ::coffeeMachine := oMachine
> RETURN self
>
>
>
> /*
> * This method simulates a working programmer. He works only if there is
> * coffee in his cup. If the cup is empty (::coffee == 0), the programmer
> * walks to the coffee machine (:enter()). By this, he restricts all other
> * Programmer threads from accessing the coffee machine.
> */
> METHOD Programmer:execute
> LOCAL nRow := ThreadID() * 2
>
> IF ::coffee == 0
> // Coffee cup is empty
> DispoutAt( nRow, 0, PadR( ::name + " NEEDS coffee", 80), "W+/R" )
>
> // When a Programmer thread executes the SYNC method :enter(),
> // all other Programmer threads are stopped here which want
> // to execute this method at the same time
> ::coffeeMachine:enter( self )
> ENDIF
>
> DispoutAt( nRow, 0, PadR( ::name + " is working - " + ;
> Replicate( ".", 10*::coffee), 80) )
>
> // A programmer sips coffee
> ::coffee := Max( ::coffee - 0.1, 0 )
> RETURN
>
>
>
> /*
> * A programer fills his cup in this method. If no coffee is left in the
> * coffee machine (::coffeeMachine:coffee < 1), the CoffeeMachine thread
> * is signaled (programmer fills coffee machine).
> */
> METHOD Programmer:takeCoffee
> LOCAL nRow := ThreadID() * 2
>
> IF ::coffeeMachine:coffee < 1
> // Coffee machine is empty
> DispoutAt( nRow, 0, PadR( ::name + " MAKES coffee", 80 ), "W+/B" )
>
> // The waiting CoffeeMachine thread resumes after being signaled
> ::coffeeMachine:waterIsFilled:signal()
> ENDIF
>
> // All Programmer threads wait at this point until the
> // CoffeeMachine thread signals "coffee is ready".
> // The signal is delayed while the coffee machine is running.
> ::coffeeMachine:coffeeIsReady:wait()
>
> DispoutAt( nRow, 0, PadR( ::name + " takes coffee ", 80 ), "N/G" )
>
> // A programmer fills his cup with coffee from the coffee machine
> ::coffeeMachine:coffee -= 1
>
> // Cup is filled again
> ::coffee := 1
> Sleep(100)
> RETURN self
>
>
>
Regards
Pritpal Bedi
--
View this message in context:
http://www.nabble.com/MT---Xbase%2B%2B---A-Code-Snippet-tp23783523p23783523.html
Sent from the Harbour - Dev mailing list archive at Nabble.com.
_______________________________________________
Harbour mailing list
[email protected]
http://lists.harbour-project.org/mailman/listinfo/harbour